From cfceed678b2a4474608411fa4afea76d6c389819 Mon Sep 17 00:00:00 2001 From: xiaochong0302 Date: Mon, 29 Jun 2020 19:29:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86IM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...{ImHotGroupList.php => ImNewGroupList.php} | 4 +- .../{ImHotUserList.php => ImNewUserList.php} | 4 +- ...ssengerController.php => ImController.php} | 64 +- app/Http/Web/Services/Im.php | 685 ++++++++++ app/Http/Web/Services/ImFriendTrait.php | 240 ++++ app/Http/Web/Services/ImGroupTrait.php | 259 ++++ app/Http/Web/Services/Messenger.php | 1111 ----------------- app/Library/Paginator/Query.php | 2 +- app/Models/Chapter.php | 8 +- app/Models/Course.php | 8 +- app/Models/Order.php | 10 +- app/Models/Task.php | 10 +- app/Models/User.php | 56 +- app/Traits/Auth.php | 8 +- app/Validators/User.php | 13 +- public/static/web/css/common.css | 4 + public/static/web/js/im.js | 12 + 17 files changed, 1323 insertions(+), 1175 deletions(-) rename app/Caches/{ImHotGroupList.php => ImNewGroupList.php} (94%) rename app/Caches/{ImHotUserList.php => ImNewUserList.php} (95%) rename app/Http/Web/Controllers/{MessengerController.php => ImController.php} (82%) create mode 100644 app/Http/Web/Services/Im.php create mode 100644 app/Http/Web/Services/ImFriendTrait.php create mode 100644 app/Http/Web/Services/ImGroupTrait.php delete mode 100644 app/Http/Web/Services/Messenger.php diff --git a/app/Caches/ImHotGroupList.php b/app/Caches/ImNewGroupList.php similarity index 94% rename from app/Caches/ImHotGroupList.php rename to app/Caches/ImNewGroupList.php index b17c2dcc..5a012de5 100644 --- a/app/Caches/ImHotGroupList.php +++ b/app/Caches/ImNewGroupList.php @@ -6,7 +6,7 @@ use App\Models\ImChatGroup as ImChatGroupModel; use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\ResultsetInterface; -class ImHotGroupList extends Cache +class ImNewGroupList extends Cache { protected $lifetime = 1 * 86400; @@ -18,7 +18,7 @@ class ImHotGroupList extends Cache public function getKey($id = null) { - return 'im_hot_group_list'; + return 'im_new_group_list'; } public function getContent($id = null) diff --git a/app/Caches/ImHotUserList.php b/app/Caches/ImNewUserList.php similarity index 95% rename from app/Caches/ImHotUserList.php rename to app/Caches/ImNewUserList.php index 682e651b..46b4124d 100644 --- a/app/Caches/ImHotUserList.php +++ b/app/Caches/ImNewUserList.php @@ -6,7 +6,7 @@ use App\Models\User as UserModel; use Phalcon\Mvc\Model\Resultset; use Phalcon\Mvc\Model\ResultsetInterface; -class ImHotUserList extends Cache +class ImNewUserList extends Cache { protected $lifetime = 1 * 86400; @@ -18,7 +18,7 @@ class ImHotUserList extends Cache public function getKey($id = null) { - return 'im_hot_user_list'; + return 'im_new_user_list'; } public function getContent($id = null) diff --git a/app/Http/Web/Controllers/MessengerController.php b/app/Http/Web/Controllers/ImController.php similarity index 82% rename from app/Http/Web/Controllers/MessengerController.php rename to app/Http/Web/Controllers/ImController.php index 54ee8c61..0961c80b 100644 --- a/app/Http/Web/Controllers/MessengerController.php +++ b/app/Http/Web/Controllers/ImController.php @@ -2,14 +2,14 @@ namespace App\Http\Web\Controllers; -use App\Http\Web\Services\Messenger as MessengerService; +use App\Http\Web\Services\Im as ImService; use App\Traits\Response as ResponseTrait; use Phalcon\Mvc\View; /** * @RoutePrefix("/im") */ -class MessengerController extends LayerController +class ImController extends LayerController { use ResponseTrait; @@ -19,7 +19,7 @@ class MessengerController extends LayerController */ public function initAction() { - $service = new MessengerService(); + $service = new ImService(); $data = $service->init(); @@ -31,7 +31,7 @@ class MessengerController extends LayerController */ public function groupMembersAction() { - $service = new MessengerService(); + $service = new ImService(); $list = $service->getGroupUsers(); @@ -41,11 +41,11 @@ class MessengerController extends LayerController /** * @Get("/msg/unread/count", name="web.im.unread_msg_count") */ - public function unreadMessagesCountAction() + public function countUnreadMessagesAction() { - $service = new MessengerService(); + $service = new ImService(); - $count = $service->getUnreadSystemMessagesCount(); + $count = $service->countUnreadSystemMessages(); return $this->jsonSuccess(['count' => $count]); } @@ -55,7 +55,7 @@ class MessengerController extends LayerController */ public function markMessagesAsReadAction() { - $service = new MessengerService(); + $service = new ImService(); $service->markSystemMessagesAsRead(); @@ -67,7 +67,7 @@ class MessengerController extends LayerController */ public function messageBoxAction() { - $service = new MessengerService(); + $service = new ImService(); $pager = $service->getSystemMessages(); @@ -80,7 +80,7 @@ class MessengerController extends LayerController */ public function systemMessagesAction() { - $service = new MessengerService(); + $service = new ImService(); $pager = $service->getSystemMessages(); @@ -95,7 +95,7 @@ class MessengerController extends LayerController */ public function chatLogAction() { - $service = new MessengerService(); + $service = new ImService(); $pager = $service->getChatMessages(); @@ -109,7 +109,7 @@ class MessengerController extends LayerController */ public function chatHistoryAction() { - $service = new MessengerService(); + $service = new ImService(); $pager = $service->getChatMessages(); @@ -121,10 +121,10 @@ class MessengerController extends LayerController */ public function findAction() { - $service = new MessengerService(); + $service = new ImService(); - $usersPager = $service->getHotUsers(); - $groupsPager = $service->getHotGroups(); + $usersPager = $service->getNewUsers(); + $groupsPager = $service->getNewGroups(); $usersPager->items = kg_array_object($usersPager->items); $groupsPager->items = kg_array_object($groupsPager->items); @@ -144,7 +144,7 @@ class MessengerController extends LayerController $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW); - $service = new MessengerService(); + $service = new ImService(); if ($type == 'user') { $this->view->pick('messenger/find_users'); @@ -167,7 +167,7 @@ class MessengerController extends LayerController */ public function bindUserAction() { - $service = new MessengerService(); + $service = new ImService(); $service->bindUser(); @@ -179,7 +179,7 @@ class MessengerController extends LayerController */ public function sendMessageAction() { - $service = new MessengerService(); + $service = new ImService(); $service->sendMessage(); @@ -206,7 +206,7 @@ class MessengerController extends LayerController */ public function updateOnlineAction() { - $service = new MessengerService(); + $service = new ImService(); $service->updateOnline(); @@ -218,19 +218,31 @@ class MessengerController extends LayerController */ public function updateSignatureAction() { - $service = new MessengerService(); + $service = new ImService(); $service->updateSignature(); return $this->jsonSuccess(); } + /** + * @Post("/skin/update", name="web.web.im.update_skin") + */ + public function updateSKinAction() + { + $service = new ImService(); + + $service->updateSkin(); + + return $this->jsonSuccess(); + } + /** * @Post("/friend/apply", name="web.im.apply_friend") */ public function applyFriendAction() { - $service = new MessengerService(); + $service = new ImService(); $service->applyFriend(); @@ -244,7 +256,7 @@ class MessengerController extends LayerController */ public function acceptFriendAction() { - $service = new MessengerService(); + $service = new ImService(); $service->acceptFriend(); @@ -256,7 +268,7 @@ class MessengerController extends LayerController */ public function refuseFriendAction() { - $service = new MessengerService(); + $service = new ImService(); $service->refuseFriend(); @@ -268,7 +280,7 @@ class MessengerController extends LayerController */ public function applyGroupAction() { - $service = new MessengerService(); + $service = new ImService(); $service->applyGroup(); @@ -282,7 +294,7 @@ class MessengerController extends LayerController */ public function acceptGroupAction() { - $service = new MessengerService(); + $service = new ImService(); $service->acceptGroup(); @@ -294,7 +306,7 @@ class MessengerController extends LayerController */ public function refuseGroupAction() { - $service = new MessengerService(); + $service = new ImService(); $service->refuseGroup(); diff --git a/app/Http/Web/Services/Im.php b/app/Http/Web/Services/Im.php new file mode 100644 index 00000000..96ef788d --- /dev/null +++ b/app/Http/Web/Services/Im.php @@ -0,0 +1,685 @@ +getLoginUser(); + + $user->afterFetch(); + + $mine = [ + 'id' => $user->id, + 'username' => $user->name, + 'avatar' => $user->avatar, + 'sign' => $user->im['sign'] ?? '', + 'status' => $user->im['online']['status'] ?? 'online', + ]; + + $friend = $this->handleFriendList($user); + $group = $this->handleGroupList($user); + + return [ + 'mine' => $mine, + 'friend' => $friend, + 'group' => $group, + ]; + } + + public function searchUsers($name) + { + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['name'] = $name; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $userRepo = new UserRepo(); + + $pager = $userRepo->paginate($params, $sort, $page, $limit); + + return $this->handleUserPager($pager); + } + + public function searchGroups($name) + { + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['name'] = $name; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $groupRepo = new ImChatGroupRepo(); + + $pager = $groupRepo->paginate($params, $sort, $page, $limit); + + return $this->handleGroupPager($pager); + } + + public function getNewUsers() + { + $cache = new ImNewUserListCache(); + + $items = $cache->get(); + + $pager = new \stdClass(); + + $pager->total_items = count($items); + $pager->total_pages = 1; + $pager->items = $items; + + return $pager; + } + + public function getNewGroups() + { + $cache = new ImNewGroupListCache(); + + $items = $cache->get(); + + $pager = new \stdClass(); + + $pager->total_items = count($items); + $pager->total_pages = 1; + $pager->items = $items; + + return $pager; + } + + public function getGroupUsers() + { + $id = $this->request->getQuery('id'); + + $validator = new ImChatGroupValidator(); + + $group = $validator->checkGroupCache($id); + + $groupRepo = new ImChatGroupRepo(); + + $users = $groupRepo->findGroupUsers($group->id); + + if ($users->count() == 0) { + return []; + } + + $baseUrl = kg_ci_base_url(); + + $result = []; + + foreach ($users->toArray() as $user) { + $user['avatar'] = $baseUrl . $user['avatar']; + $result[] = [ + 'id' => $user['id'], + 'username' => $user['name'], + 'avatar' => $user['avatar'], + 'sign' => $user['sign'], + ]; + } + + return $result; + } + + public function countUnreadSystemMessages() + { + $user = $this->getLoginUser(); + + $userRepo = new UserRepo(); + + return $userRepo->countUnreadImSystemMessages($user->id); + } + + public function getSystemMessages() + { + $user = $this->getLoginUser(); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $params['receiver_id'] = $user->id; + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + $messageRepo = new ImSystemMessageRepo(); + + return $messageRepo->paginate($params, $sort, $page, $limit); + } + + public function getChatMessages() + { + $user = $this->getLoginUser(); + + $pagerQuery = new PagerQuery(); + + $params = $pagerQuery->getParams(); + + $validator = new ImMessageValidator(); + + $validator->checkType($params['type']); + + $sort = $pagerQuery->getSort(); + $page = $pagerQuery->getPage(); + $limit = $pagerQuery->getLimit(); + + if ($params['type'] == 'friend') { + + $params['chat_id'] = ImFriendMessageModel::getChatId($user->id, $params['id']); + + $messageRepo = new ImFriendMessageRepo(); + + $pager = $messageRepo->paginate($params, $sort, $page, $limit); + + return $this->handleChatMessagePager($pager); + + } elseif ($params['type'] == 'group') { + + $params['group_id'] = $params['id']; + + $messageRepo = new ImGroupMessageRepo(); + + $pager = $messageRepo->paginate($params, $sort, $page, $limit); + + return $this->handleChatMessagePager($pager); + } + } + + public function bindUser() + { + $user = $this->getLoginUser(); + + $user->afterFetch(); + + $clientId = $this->request->getPost('client_id'); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + Gateway::bindUid($clientId, $user->id); + + $userRepo = new UserRepo(); + + $chatGroups = $userRepo->findImChatGroups($user->id); + + if ($chatGroups->count() > 0) { + foreach ($chatGroups as $group) { + Gateway::joinGroup($clientId, $this->getGroupName($group->id)); + } + } + + $this->pullUnreadFriendMessages($user); + + /** + * 保持上次的在线状态 + */ + $status = $user->im['online']['status'] ?? 'online'; + + $this->pushFriendOnlineTips($user, $status); + } + + public function sendMessage() + { + $user = $this->getLoginUser(); + + $user->afterFetch(); + + $from = $this->request->getPost('from'); + $to = $this->request->getPost('to'); + + $validator = new ImMessageValidator(); + + $validator->checkReceiver($to['id'], $to['type']); + $validator->checkIfBlocked($user->id, $to['id'], $to['type']); + + $from['content'] = $validator->checkContent($from['content']); + + $message = [ + 'username' => $from['username'], + 'avatar' => $from['avatar'], + 'content' => $from['content'], + 'fromid' => $from['id'], + 'id' => $from['id'], + 'type' => $to['type'], + 'timestamp' => 1000 * time(), + 'mine' => false, + ]; + + if ($to['type'] == 'group') { + $message['id'] = $to['id']; + } + + $content = json_encode([ + 'type' => 'show_chat_msg', + 'message' => $message, + ]); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + if ($to['type'] == 'friend') { + + /** + * 不推送自己给自己发送的消息 + */ + if ($user->id != $to['id']) { + + $online = Gateway::isUidOnline($to['id']); + + $messageModel = new ImFriendMessageModel(); + + $messageModel->create([ + 'sender_id' => $from['id'], + 'receiver_id' => $to['id'], + 'content' => $from['content'], + 'viewed' => $online ? 1 : 0, + ]); + + if ($online) { + Gateway::sendToUid($to['id'], $content); + } + } + + } elseif ($to['type'] == 'group') { + + $messageModel = new ImGroupMessageModel(); + + $messageModel->create([ + 'sender_id' => $from['id'], + 'group_id' => $to['id'], + 'content' => $from['content'], + ]); + + $excludeClientId = null; + + /** + * 不推送自己在群组中发的消息 + */ + if ($user->id == $from['id']) { + $excludeClientId = Gateway::getClientIdByUid($user->id); + } + + $groupName = $this->getGroupName($to['id']); + + Gateway::sendToGroup($groupName, $content, $excludeClientId); + } + } + + public function markSystemMessagesAsRead() + { + $user = $this->getLoginUser(); + + $userRepo = new UserRepo(); + + $messages = $userRepo->findUnreadImSystemMessages($user->id); + + if ($messages->count() > 0) { + foreach ($messages as $message) { + $message->viewed = 1; + $message->update(); + } + } + } + + public function updateOnline() + { + $user = $this->getLoginUser(); + + $user->afterFetch(); + + $status = $this->request->getPost('status'); + + $im = $user->im ?: []; + + $im['online']['status'] = $status; + + $user->update(['im' => $im]); + + $this->pushFriendOnlineTips($user, $status); + + return $user; + } + + public function updateSignature() + { + $user = $this->getLoginUser(); + + $user->afterFetch(); + + $sign = $this->request->getPost('sign'); + + $validator = new UserValidator(); + + $sign = $validator->checkImSign($sign); + + $im = $user->im ?? []; + + $im['sign'] = $sign; + + $user->update(['im' => $im]); + + return $user; + } + + public function updateSkin() + { + $user = $this->getLoginUser(); + + $user->afterFetch(); + + $skin = $this->request->getPost('skin'); + + $validator = new UserValidator(); + + $skin = $validator->checkImSkin($skin); + + $im = $user->im ?? []; + + $im['skin'] = $skin; + + $user->update(['im' => $im]); + + return $user; + } + + protected function pullUnreadFriendMessages(UserModel $user) + { + $userRepo = new UserRepo(); + + $messages = $userRepo->findUnreadImFriendMessages($user->id); + + if ($messages->count() == 0) { + return; + } + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $builder = new ImMessageListBuilder(); + + $senders = $builder->getSenders($messages->toArray()); + + foreach ($messages as $message) { + + $message->update(['viewed' => 1]); + + $sender = $senders[$message->sender_id]; + + $content = kg_json_encode([ + 'type' => 'show_chat_msg', + 'message' => [ + 'username' => $sender['name'], + 'avatar' => $sender['avatar'], + 'content' => $message->content, + 'fromid' => $sender['id'], + 'id' => $sender['id'], + 'timestamp' => 1000 * $message->create_time, + 'type' => 'friend', + 'mine' => false, + ], + ]); + + Gateway::sendToUid($user->id, $content); + } + } + + protected function pushFriendOnlineTips(UserModel $user, $status) + { + $user->afterFetch(); + + $time = $user->im['online']['time'] ?? 0; + $expired = time() - $time > 600; + + /** + * 检查间隔,避免频繁提醒干扰 + */ + if ($time > 0 && !$expired) { + return; + } + + $im = $user->im ?: []; + + $im['online']['status'] = $status; + $im['online']['time'] = time(); + + $user->update(['im' => $im]); + + $userRepo = new UserRepo(); + + $friendUsers = $userRepo->findImFriendUsers($user->id); + + if ($friendUsers->count() == 0) { + return; + } + + Gateway::$registerAddress = $this->getRegisterAddress(); + + foreach ($friendUsers as $friendUser) { + if (Gateway::isUidOnline($friendUser->friend_id)) { + $content = kg_json_encode([ + 'type' => 'show_online_tips', + 'friend' => [ + 'id' => $user->id, + 'name' => $user->name, + 'avatar' => $user->avatar, + ], + 'status' => $status == 'online' ? 'online' : 'offline', + ]); + Gateway::sendToUid($friendUser->friend_id, $content); + } + } + } + + protected function handleFriendList(UserModel $user) + { + $userRepo = new UserRepo(); + + $friendGroups = $userRepo->findImFriendGroups($user->id); + $friendUsers = $userRepo->findImFriendUsers($user->id); + + $items = []; + + $items[] = [ + 'id' => 0, + 'groupname' => '我的好友', + 'list' => [], + ]; + + if ($friendGroups->count() > 0) { + foreach ($friendGroups as $group) { + $items[] = [ + 'id' => $group->id, + 'groupname' => $group->name, + 'online' => 0, + 'list' => [], + ]; + } + } + + if ($friendUsers->count() == 0) { + return $items; + } + + $userIds = kg_array_column($friendUsers->toArray(), 'friend_id'); + + $users = $userRepo->findByIds($userIds); + + $userMappings = []; + + foreach ($users as $user) { + $userMappings[$user->id] = [ + 'id' => $user->id, + 'username' => $user->name, + 'avatar' => $user->avatar, + 'sign' => $user->im['sign'] ?? '', + 'status' => $user->im['online']['status'] ?? 'offline', + ]; + } + + foreach ($items as $key => $item) { + foreach ($friendUsers as $friendUser) { + $userId = $friendUser->friend_id; + if ($item['id'] == $friendUser->group_id) { + $items[$key]['list'][] = $userMappings[$userId]; + } else { + $items[0]['list'][] = $userMappings[$userId]; + } + } + } + + return $items; + } + + protected function handleGroupList(UserModel $user) + { + $userRepo = new UserRepo(); + + $groups = $userRepo->findImChatGroups($user->id); + + if ($groups->count() == 0) { + return []; + } + + $baseUrl = kg_ci_base_url(); + + $result = []; + + foreach ($groups->toArray() as $group) { + $group['avatar'] = $baseUrl . $group['avatar']; + $result[] = [ + 'id' => $group['id'], + 'groupname' => $group['name'], + 'avatar' => $group['avatar'], + ]; + } + + return $result; + } + + protected function handleChatMessagePager($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $messages = $pager->items->toArray(); + + $builder = new ImMessageListBuilder(); + + $senders = $builder->getSenders($messages); + + $items = []; + + foreach ($messages as $message) { + $sender = $senders[$message['sender_id']] ?? new \stdClass(); + $items[] = [ + 'id' => $message['id'], + 'content' => $message['content'], + 'timestamp' => $message['create_time'] * 1000, + 'user' => $sender, + ]; + } + + $pager->items = $items; + + return $pager; + } + + protected function handleUserPager($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $users = $pager->items->toArray(); + + $baseUrl = kg_ci_base_url(); + + $items = []; + + foreach ($users as $user) { + $user['avatar'] = $baseUrl . $user['avatar']; + $items[] = [ + 'id' => $user['id'], + 'name' => $user['name'], + 'avatar' => $user['avatar'], + 'about' => $user['about'], + 'vip' => $user['vip'], + ]; + } + + $pager->items = $items; + + return $pager; + } + + protected function handleGroupPager($pager) + { + if ($pager->total_items == 0) { + return $pager; + } + + $groups = $pager->items->toArray(); + + $baseUrl = kg_ci_base_url(); + + $items = []; + + foreach ($groups as $group) { + $group['avatar'] = $baseUrl . $group['avatar']; + $items[] = [ + 'id' => $group['id'], + 'name' => $group['name'], + 'avatar' => $group['avatar'], + 'about' => $group['about'], + ]; + } + + $pager->items = $items; + + return $pager; + } + + protected function getGroupName($groupId) + { + return "group_{$groupId}"; + } + + protected function getRegisterAddress() + { + return '127.0.0.1:1238'; + } + +} diff --git a/app/Http/Web/Services/ImFriendTrait.php b/app/Http/Web/Services/ImFriendTrait.php new file mode 100644 index 00000000..6a70533a --- /dev/null +++ b/app/Http/Web/Services/ImFriendTrait.php @@ -0,0 +1,240 @@ +request->getPost(); + + $user = $this->getLoginUser(); + + $validator = new ImFriendUserValidator(); + + $friend = $validator->checkFriend($post['friend_id']); + $group = $validator->checkGroup($post['group_id']); + $remark = $validator->checkRemark($post['remark']); + + $validator->checkIfSelfApply($user->id, $friend->id); + $validator->checkIfJoined($user->id, $friend->id); + $validator->checkIfBlocked($user->id, $friend->id); + + $this->handleApplyFriendNotice($user, $friend, $group, $remark); + } + + public function acceptFriend() + { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + $groupId = $this->request->getPost('group_id'); + + $validator = new ImFriendUserValidator(); + + $validator->checkGroup($groupId); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { + return; + } + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $friendUserRepo = new ImFriendUserRepo(); + + $friendUser = $friendUserRepo->findFriendUser($user->id, $sender->id); + + if (!$friendUser) { + $friendUserModel = new ImFriendUserModel(); + $friendUserModel->create([ + 'user_id' => $user->id, + 'friend_id' => $sender->id, + 'group_id' => $groupId, + ]); + } + + $friendUser = $friendUserRepo->findFriendUser($sender->id, $user->id); + + $groupId = $message->item_info['group']['id'] ?: 0; + + if (!$friendUser) { + $friendUserModel = new ImFriendUserModel(); + $friendUserModel->create([ + 'user_id' => $sender->id, + 'friend_id' => $user->id, + 'group_id' => $groupId, + ]); + } + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; + $message->update(['item_info' => $itemInfo]); + + $this->handleAcceptFriendNotice($user, $sender, $message); + } + + public function refuseFriend() + { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { + return; + } + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; + $message->update(['item_info' => $itemInfo]); + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $this->handleRefuseFriendNotice($user, $sender); + } + + protected function handleApplyFriendNotice(UserModel $sender, UserModel $receiver, ImFriendGroupModel $group, $remark) + { + $userRepo = new UserRepo(); + + $itemType = ImSystemMessageModel::TYPE_FRIEND_REQUEST; + + $message = $userRepo->findImSystemMessage($receiver->id, $itemType); + + if ($message) { + $expired = time() - $message->create_time > 7 * 86400; + $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; + if (!$expired && $pending) { + return; + } + } + + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REQUEST; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ], + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + ], + 'remark' => $remark, + 'status' => ImSystemMessageModel::REQUEST_PENDING, + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'refresh_msg_box']); + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleAcceptFriendNotice(UserModel $sender, UserModel $receiver, ImSystemMessageModel $applyMessage) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_ACCEPTED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + + /** + * 上层操作更新了item_info,类型发生了变化,故重新获取 + */ + $messageRepo = new ImSystemMessageRepo(); + $message = $messageRepo->findById($applyMessage->id); + $itemInfo = $message->item_info; + + $content = kg_json_encode([ + 'type' => 'friend_accepted', + 'friend' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ], + 'group' => [ + 'id' => $itemInfo['group']['id'], + 'name' => $itemInfo['group']['name'], + ], + ]); + + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleRefuseFriendNotice(UserModel $sender, UserModel $receiver) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REFUSED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'refresh_msg_box']); + Gateway::sendToUid($receiver->id, $content); + } + } + +} diff --git a/app/Http/Web/Services/ImGroupTrait.php b/app/Http/Web/Services/ImGroupTrait.php new file mode 100644 index 00000000..b5adf53f --- /dev/null +++ b/app/Http/Web/Services/ImGroupTrait.php @@ -0,0 +1,259 @@ +request->getPost(); + + $user = $this->getLoginUser(); + + $validator = new ImChatGroupUserValidator(); + + $group = $validator->checkGroup($post['group_id']); + $remark = $validator->checkRemark($post['remark']); + + $validator->checkIfJoined($user->id, $group->id); + $validator->checkIfBlocked($user->id, $group->id); + + $this->handleApplyGroupNotice($user, $group, $remark); + } + + public function acceptGroup() + { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { + return; + } + + $groupId = $message->item_info['group']['id'] ?: 0; + + $validator = new ImChatGroupValidator(); + + $group = $validator->checkGroup($groupId); + + $validator->checkOwner($user->id, $group->user_id); + + $userRepo = new UserRepo(); + + $applicant = $userRepo->findById($message->sender_id); + + $groupUserRepo = new ImChatGroupUserRepo(); + + $groupUser = $groupUserRepo->findGroupUser($group->id, $applicant->id); + + if (!$groupUser) { + $groupUserModel = new ImChatGroupUserModel(); + $groupUserModel->create([ + 'group_id' => $group->id, + 'user_id' => $applicant->id, + ]); + } + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; + $message->update(['item_info' => $itemInfo]); + + $this->handleAcceptGroupNotice($user, $applicant, $group); + + $this->handleNewGroupUserNotice($applicant, $group); + } + + public function refuseGroup() + { + $user = $this->getLoginUser(); + + $messageId = $this->request->getPost('message_id'); + + $validator = new ImMessageValidator(); + + $message = $validator->checkMessage($messageId, 'system'); + + if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { + return; + } + + $groupId = $message->item_info['group']['id'] ?: 0; + + $validator = new ImChatGroupValidator(); + + $group = $validator->checkGroup($groupId); + + $validator->checkOwner($user->id, $group->user_id); + + $itemInfo = $message->item_info; + $itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; + $message->update(['item_info' => $itemInfo]); + + $userRepo = new UserRepo(); + + $sender = $userRepo->findById($message->sender_id); + + $this->handleRefuseGroupNotice($user, $sender); + } + + protected function handleApplyGroupNotice(UserModel $sender, ImChatGroupModel $group, $remark) + { + $userRepo = new UserRepo(); + + $receiver = $userRepo->findById($group->user_id); + + $itemType = ImSystemMessageModel::TYPE_GROUP_REQUEST; + + $message = $userRepo->findImSystemMessage($receiver->id, $itemType); + + if ($message) { + $expired = time() - $message->create_time > 7 * 86400; + $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; + if (!$expired && $pending) { + return; + } + } + + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REQUEST; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ], + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + ], + 'remark' => $remark, + 'status' => ImSystemMessageModel::REQUEST_PENDING, + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + $content = kg_json_encode(['type' => 'refresh_msg_box']); + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleAcceptGroupNotice(UserModel $sender, UserModel $receiver, ImChatGroupModel $group) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_ACCEPTED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + $online = Gateway::isUidOnline($receiver->id); + + if ($online) { + + $content = kg_json_encode([ + 'type' => 'group_accepted', + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + 'avatar' => $group->avatar, + ], + ]); + + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleRefuseGroupNotice(UserModel $sender, UserModel $receiver) + { + $sysMsgModel = new ImSystemMessageModel(); + + $sysMsgModel->sender_id = $sender->id; + $sysMsgModel->receiver_id = $receiver->id; + $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REFUSED; + $sysMsgModel->item_info = [ + 'sender' => [ + 'id' => $sender->id, + 'name' => $sender->name, + 'avatar' => $sender->avatar, + ] + ]; + + $sysMsgModel->create(); + + Gateway::$registerAddress = $this->getRegisterAddress(); + + if (Gateway::isUidOnline($receiver->id)) { + $content = kg_json_encode(['type' => 'refresh_msg_box']); + Gateway::sendToUid($receiver->id, $content); + } + } + + protected function handleNewGroupUserNotice(UserModel $newUser, ImChatGroupModel $group) + { + $groupRepo = new ImChatGroupRepo(); + + $users = $groupRepo->findGroupUsers($group->id); + + if ($users->count() == 0) { + return; + } + + Gateway::$registerAddress = $this->getRegisterAddress(); + + foreach ($users as $user) { + $content = kg_json_encode([ + 'type' => 'new_group_user', + 'user' => [ + 'id' => $newUser->id, + 'name' => $newUser->name, + 'avatar' => $newUser->avatar, + ], + 'group' => [ + 'id' => $group->id, + 'name' => $group->name, + 'avatar' => $group->avatar, + ], + ]); + if (Gateway::isUidOnline($user->id)) { + Gateway::sendToUid($user->id, $content); + } + } + } + +} diff --git a/app/Http/Web/Services/Messenger.php b/app/Http/Web/Services/Messenger.php deleted file mode 100644 index 7e3826b4..00000000 --- a/app/Http/Web/Services/Messenger.php +++ /dev/null @@ -1,1111 +0,0 @@ -getLoginUser(); - - $mine = [ - 'id' => $user->id, - 'username' => $user->name, - 'sign' => $user->sign, - 'avatar' => $user->avatar, - 'status' => 'online', - ]; - - $friend = $this->handleFriendList($user); - - $group = $this->handleGroupList($user); - - return [ - 'mine' => $mine, - 'friend' => $friend, - 'group' => $group, - ]; - } - - public function searchUsers($name) - { - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $params['name'] = $name; - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $userRepo = new UserRepo(); - - $pager = $userRepo->paginate($params, $sort, $page, $limit); - - return $this->handleUserPager($pager); - } - - public function searchGroups($name) - { - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $params['name'] = $name; - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $groupRepo = new ImChatGroupRepo(); - - $pager = $groupRepo->paginate($params, $sort, $page, $limit); - - return $this->handleGroupPager($pager); - } - - public function getHotUsers() - { - $cache = new ImHotUserListCache(); - - $items = $cache->get(); - - $pager = new \stdClass(); - - $pager->total_items = count($items); - $pager->total_pages = 1; - $pager->items = $items; - - return $pager; - } - - public function getHotGroups() - { - $cache = new ImHotGroupListCache(); - - $items = $cache->get(); - - $pager = new \stdClass(); - - $pager->total_items = count($items); - $pager->total_pages = 1; - $pager->items = $items; - - return $pager; - } - - public function getGroupUsers() - { - $id = $this->request->getQuery('id'); - - $validator = new ImChatGroupValidator(); - - $group = $validator->checkGroupCache($id); - - $groupRepo = new ImChatGroupRepo(); - - $users = $groupRepo->findGroupUsers($group->id); - - if ($users->count() == 0) { - return []; - } - - $baseUrl = kg_ci_base_url(); - - $result = []; - - foreach ($users->toArray() as $user) { - $user['avatar'] = $baseUrl . $user['avatar']; - $result[] = [ - 'id' => $user['id'], - 'username' => $user['name'], - 'avatar' => $user['avatar'], - 'sign' => $user['sign'], - ]; - } - - return $result; - } - - public function getUnreadSystemMessagesCount() - { - $user = $this->getLoginUser(); - - $userRepo = new UserRepo(); - - return $userRepo->countUnreadImSystemMessages($user->id); - } - - public function getSystemMessages() - { - $user = $this->getLoginUser(); - - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $params['receiver_id'] = $user->id; - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - $messageRepo = new ImSystemMessageRepo(); - - return $messageRepo->paginate($params, $sort, $page, $limit); - } - - public function getChatMessages() - { - $user = $this->getLoginUser(); - - $pagerQuery = new PagerQuery(); - - $params = $pagerQuery->getParams(); - - $validator = new ImMessageValidator(); - - $validator->checkType($params['type']); - - $sort = $pagerQuery->getSort(); - $page = $pagerQuery->getPage(); - $limit = $pagerQuery->getLimit(); - - if ($params['type'] == 'friend') { - - $params['chat_id'] = ImFriendMessageModel::getChatId($user->id, $params['id']); - - $messageRepo = new ImFriendMessageRepo(); - - $pager = $messageRepo->paginate($params, $sort, $page, $limit); - - return $this->handleChatMessagePager($pager); - - } elseif ($params['type'] == 'group') { - - $params['group_id'] = $params['id']; - - $messageRepo = new ImGroupMessageRepo(); - - $pager = $messageRepo->paginate($params, $sort, $page, $limit); - - return $this->handleChatMessagePager($pager); - } - } - - public function bindUser() - { - $user = $this->getLoginUser(); - - $user->update([ - 'online' => 1, - 'active_time' => time(), - ]); - - $clientId = $this->request->getPost('client_id'); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - Gateway::bindUid($clientId, $user->id); - - $userRepo = new UserRepo(); - - $chatGroups = $userRepo->findImChatGroups($user->id); - - if ($chatGroups->count() > 0) { - foreach ($chatGroups as $group) { - Gateway::joinGroup($clientId, $this->getGroupName($group->id)); - } - } - - $this->pullUnreadFriendMessages($user); - - /** - * @todo 隐身登录 - */ - $this->pushFriendOnlineTips($user, 'online'); - } - - public function sendMessage() - { - $user = $this->getLoginUser(); - - $from = $this->request->getPost('from'); - $to = $this->request->getPost('to'); - - $validator = new ImMessageValidator(); - - $validator->checkReceiver($to['id'], $to['type']); - $validator->checkIfBlocked($user->id, $to['id'], $to['type']); - - $from['content'] = $validator->checkContent($from['content']); - - $message = [ - 'username' => $from['username'], - 'avatar' => $from['avatar'], - 'content' => $from['content'], - 'fromid' => $from['id'], - 'id' => $from['id'], - 'type' => $to['type'], - 'timestamp' => 1000 * time(), - 'mine' => false, - ]; - - if ($to['type'] == 'group') { - $message['id'] = $to['id']; - } - - $content = json_encode([ - 'type' => 'show_chat_msg', - 'message' => $message, - ]); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - if ($to['type'] == 'friend') { - - /** - * 不推送自己给自己发送的消息 - */ - if ($user->id != $to['id']) { - - $online = Gateway::isUidOnline($to['id']); - - $messageModel = new ImFriendMessageModel(); - - $messageModel->create([ - 'sender_id' => $from['id'], - 'receiver_id' => $to['id'], - 'content' => $from['content'], - 'viewed' => $online ? 1 : 0, - ]); - - if ($online) { - Gateway::sendToUid($to['id'], $content); - } - } - - } elseif ($to['type'] == 'group') { - - $messageModel = new ImGroupMessageModel(); - - $messageModel->create([ - 'sender_id' => $from['id'], - 'group_id' => $to['id'], - 'content' => $from['content'], - ]); - - $excludeClientId = null; - - /** - * 不推送自己在群组中发的消息 - */ - if ($user->id == $from['id']) { - $excludeClientId = Gateway::getClientIdByUid($user->id); - } - - $groupName = $this->getGroupName($to['id']); - - Gateway::sendToGroup($groupName, $content, $excludeClientId); - } - } - - public function markSystemMessagesAsRead() - { - $user = $this->getLoginUser(); - - $userRepo = new UserRepo(); - - $messages = $userRepo->findUnreadImSystemMessages($user->id); - - if ($messages->count() > 0) { - foreach ($messages as $message) { - $message->viewed = 1; - $message->update(); - } - } - } - - public function updateOnline() - { - $status = $this->request->getPost('status'); - - $user = $this->getLoginUser(); - - $online = $status == 'online' ? 1 : 0; - - $user->update(['online' => $online]); - - $this->pushFriendOnlineTips($user, $status); - - return $user; - } - - public function updateSignature() - { - $sign = $this->request->getPost('sign'); - - $user = $this->getLoginUser(); - - $validator = new UserValidator(); - - $validator->checkSign($sign); - - $user->update(['sign' => $sign]); - - return $user; - } - - public function applyFriend() - { - $post = $this->request->getPost(); - - $user = $this->getLoginUser(); - - $validator = new ImFriendUserValidator(); - - $friend = $validator->checkFriend($post['friend_id']); - $group = $validator->checkGroup($post['group_id']); - $remark = $validator->checkRemark($post['remark']); - - $validator->checkIfSelfApply($user->id, $friend->id); - $validator->checkIfJoined($user->id, $friend->id); - $validator->checkIfBlocked($user->id, $friend->id); - - $this->handleApplyFriendNotice($user, $friend, $group, $remark); - } - - public function acceptFriend() - { - $user = $this->getLoginUser(); - - $messageId = $this->request->getPost('message_id'); - $groupId = $this->request->getPost('group_id'); - - $validator = new ImFriendUserValidator(); - - $validator->checkGroup($groupId); - - $validator = new ImMessageValidator(); - - $message = $validator->checkMessage($messageId, 'system'); - - if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { - return; - } - - $userRepo = new UserRepo(); - - $sender = $userRepo->findById($message->sender_id); - - $friendUserRepo = new ImFriendUserRepo(); - - $friendUser = $friendUserRepo->findFriendUser($user->id, $sender->id); - - if (!$friendUser) { - $friendUserModel = new ImFriendUserModel(); - $friendUserModel->create([ - 'user_id' => $user->id, - 'friend_id' => $sender->id, - 'group_id' => $groupId, - ]); - } - - $friendUser = $friendUserRepo->findFriendUser($sender->id, $user->id); - - $groupId = $message->item_info['group']['id'] ?: 0; - - if (!$friendUser) { - $friendUserModel = new ImFriendUserModel(); - $friendUserModel->create([ - 'user_id' => $sender->id, - 'friend_id' => $user->id, - 'group_id' => $groupId, - ]); - } - - $itemInfo = $message->item_info; - $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; - $message->update(['item_info' => $itemInfo]); - - $this->handleAcceptFriendNotice($user, $sender, $message); - } - - public function refuseFriend() - { - $user = $this->getLoginUser(); - - $messageId = $this->request->getPost('message_id'); - - $validator = new ImMessageValidator(); - - $message = $validator->checkMessage($messageId, 'system'); - - if ($message->item_type != ImSystemMessageModel::TYPE_FRIEND_REQUEST) { - return; - } - - $itemInfo = $message->item_info; - $itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; - $message->update(['item_info' => $itemInfo]); - - $userRepo = new UserRepo(); - - $sender = $userRepo->findById($message->sender_id); - - $this->handleRefuseFriendNotice($user, $sender); - } - - public function applyGroup() - { - $post = $this->request->getPost(); - - $user = $this->getLoginUser(); - - $validator = new ImChatGroupUserValidator(); - - $group = $validator->checkGroup($post['group_id']); - $remark = $validator->checkRemark($post['remark']); - - $validator->checkIfJoined($user->id, $group->id); - $validator->checkIfBlocked($user->id, $group->id); - - $this->handleApplyGroupNotice($user, $group, $remark); - } - - public function acceptGroup() - { - $user = $this->getLoginUser(); - - $messageId = $this->request->getPost('message_id'); - - $validator = new ImMessageValidator(); - - $message = $validator->checkMessage($messageId, 'system'); - - if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { - return; - } - - $groupId = $message->item_info['group']['id'] ?: 0; - - $validator = new ImChatGroupValidator(); - - $group = $validator->checkGroup($groupId); - - $validator->checkOwner($user->id, $group->user_id); - - $userRepo = new UserRepo(); - - $applicant = $userRepo->findById($message->sender_id); - - $groupUserRepo = new ImChatGroupUserRepo(); - - $groupUser = $groupUserRepo->findGroupUser($group->id, $applicant->id); - - if (!$groupUser) { - $groupUserModel = new ImChatGroupUserModel(); - $groupUserModel->create([ - 'group_id' => $group->id, - 'user_id' => $applicant->id, - ]); - } - - $itemInfo = $message->item_info; - $itemInfo['status'] = ImSystemMessageModel::REQUEST_ACCEPTED; - $message->update(['item_info' => $itemInfo]); - - $this->handleAcceptGroupNotice($user, $applicant, $group); - - $this->handleNewGroupUserNotice($applicant, $group); - } - - public function refuseGroup() - { - $user = $this->getLoginUser(); - - $messageId = $this->request->getPost('message_id'); - - $validator = new ImMessageValidator(); - - $message = $validator->checkMessage($messageId, 'system'); - - if ($message->item_type != ImSystemMessageModel::TYPE_GROUP_REQUEST) { - return; - } - - $groupId = $message->item_info['group']['id'] ?: 0; - - $validator = new ImChatGroupValidator(); - - $group = $validator->checkGroup($groupId); - - $validator->checkOwner($user->id, $group->user_id); - - $itemInfo = $message->item_info; - $itemInfo['status'] = ImSystemMessageModel::REQUEST_REFUSED; - $message->update(['item_info' => $itemInfo]); - - $userRepo = new UserRepo(); - - $sender = $userRepo->findById($message->sender_id); - - $this->handleRefuseGroupNotice($user, $sender); - } - - protected function pullUnreadFriendMessages(UserModel $user) - { - $userRepo = new UserRepo(); - - $messages = $userRepo->findUnreadImFriendMessages($user->id); - - if ($messages->count() == 0) { - return; - } - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $builder = new ImMessageListBuilder(); - - $senders = $builder->getSenders($messages->toArray()); - - foreach ($messages as $message) { - - $message->update(['viewed' => 1]); - - $sender = $senders[$message->sender_id]; - - $content = kg_json_encode([ - 'type' => 'show_chat_msg', - 'message' => [ - 'username' => $sender['name'], - 'avatar' => $sender['avatar'], - 'content' => $message->content, - 'fromid' => $sender['id'], - 'id' => $sender['id'], - 'timestamp' => 1000 * $message->create_time, - 'type' => 'friend', - 'mine' => false, - ], - ]); - - Gateway::sendToUid($user->id, $content); - } - } - - protected function pushFriendOnlineTips(UserModel $user, $status) - { - /** - * 检查间隔,避免频繁提醒干扰 - */ - if (time() - $user->update_time < 600) { - return; - } - - $userRepo = new UserRepo(); - - $friendUsers = $userRepo->findImFriendUsers($user->id); - - if ($friendUsers->count() == 0) { - return; - } - - $friendIds = kg_array_column($friendUsers->toArray(), 'friend_id'); - - $friends = $userRepo->findByIds($friendIds); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - foreach ($friends as $friend) { - if (Gateway::isUidOnline($friend->id)) { - $content = kg_json_encode([ - 'type' => 'show_online_tips', - 'friend' => [ - 'id' => $user->id, - 'name' => $user->name, - 'avatar' => $user->avatar, - ], - 'status' => $status == 'online' ? 'online' : 'offline', - ]); - Gateway::sendToUid($friend->id, $content); - } - } - } - - protected function handleFriendList(UserModel $user) - { - $userRepo = new UserRepo(); - - $friendGroups = $userRepo->findImFriendGroups($user->id); - $friendUsers = $userRepo->findImFriendUsers($user->id); - - $items = []; - - $items[] = [ - 'id' => 0, - 'groupname' => '我的好友', - 'list' => [], - ]; - - if ($friendGroups->count() > 0) { - foreach ($friendGroups as $group) { - $items[] = [ - 'id' => $group->id, - 'groupname' => $group->name, - 'online' => 0, - 'list' => [], - ]; - } - } - - if ($friendUsers->count() == 0) { - return $items; - } - - $userIds = kg_array_column($friendUsers->toArray(), 'friend_id'); - - $users = $userRepo->findByIds($userIds); - - $userMappings = []; - - foreach ($users as $user) { - $userMappings[$user->id] = [ - 'id' => $user->id, - 'username' => $user->name, - 'avatar' => $user->avatar, - 'sign' => $user->sign, - 'status' => $user->online ? 'online' : 'offline', - ]; - } - - foreach ($items as $key => $item) { - foreach ($friendUsers as $friendUser) { - $userId = $friendUser->friend_id; - if ($item['id'] == $friendUser->group_id) { - $items[$key]['list'][] = $userMappings[$userId]; - } else { - $items[0]['list'][] = $userMappings[$userId]; - } - } - } - - return $items; - } - - protected function handleGroupList(UserModel $user) - { - $userRepo = new UserRepo(); - - $groups = $userRepo->findImChatGroups($user->id); - - if ($groups->count() == 0) { - return []; - } - - $baseUrl = kg_ci_base_url(); - - $result = []; - - foreach ($groups->toArray() as $group) { - $group['avatar'] = $baseUrl . $group['avatar']; - $result[] = [ - 'id' => $group['id'], - 'groupname' => $group['name'], - 'avatar' => $group['avatar'], - ]; - } - - return $result; - } - - protected function handleChatMessagePager($pager) - { - if ($pager->total_items == 0) { - return $pager; - } - - $messages = $pager->items->toArray(); - - $builder = new ImMessageListBuilder(); - - $senders = $builder->getSenders($messages); - - $items = []; - - foreach ($messages as $message) { - $sender = $senders[$message['sender_id']] ?? new \stdClass(); - $items[] = [ - 'id' => $message['id'], - 'content' => $message['content'], - 'timestamp' => $message['create_time'] * 1000, - 'user' => $sender, - ]; - } - - $pager->items = $items; - - return $pager; - } - - protected function handleUserPager($pager) - { - if ($pager->total_items == 0) { - return $pager; - } - - $users = $pager->items->toArray(); - - $baseUrl = kg_ci_base_url(); - - $items = []; - - foreach ($users as $user) { - $user['avatar'] = $baseUrl . $user['avatar']; - $items[] = [ - 'id' => $user['id'], - 'name' => $user['name'], - 'avatar' => $user['avatar'], - 'about' => $user['about'], - 'location' => $user['location'], - 'gender' => $user['gender'], - 'vip' => $user['vip'], - 'follower_count' => $user['follower_count'], - 'following_count' => $user['following_count'], - ]; - } - - $pager->items = $items; - - return $pager; - } - - protected function handleGroupPager($pager) - { - if ($pager->total_items == 0) { - return $pager; - } - - $groups = $pager->items->toArray(); - - $baseUrl = kg_ci_base_url(); - - $items = []; - - foreach ($groups as $group) { - $group['avatar'] = $baseUrl . $group['avatar']; - $items[] = [ - 'id' => $group['id'], - 'name' => $group['name'], - 'avatar' => $group['avatar'], - 'about' => $group['about'], - 'user_count' => $group['user_count'], - ]; - } - - $pager->items = $items; - - return $pager; - } - - protected function handleApplyFriendNotice(UserModel $sender, UserModel $receiver, ImFriendGroupModel $group, $remark) - { - $userRepo = new UserRepo(); - - $itemType = ImSystemMessageModel::TYPE_FRIEND_REQUEST; - - $message = $userRepo->findImSystemMessage($receiver->id, $itemType); - - if ($message) { - $expired = time() - $message->create_time > 7 * 86400; - $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; - if (!$expired && $pending) { - return; - } - } - - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REQUEST; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ], - 'group' => [ - 'id' => $group->id, - 'name' => $group->name, - ], - 'remark' => $remark, - 'status' => ImSystemMessageModel::REQUEST_PENDING, - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $online = Gateway::isUidOnline($receiver->id); - - if ($online) { - $content = kg_json_encode(['type' => 'refresh_msg_box']); - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleAcceptFriendNotice(UserModel $sender, UserModel $receiver, ImSystemMessageModel $applyMessage) - { - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_ACCEPTED; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ] - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $online = Gateway::isUidOnline($receiver->id); - - if ($online) { - - /** - * 上层操作更新了item_info,类型发生了变化,故重新获取 - */ - $messageRepo = new ImSystemMessageRepo(); - $message = $messageRepo->findById($applyMessage->id); - $itemInfo = $message->item_info; - - $content = kg_json_encode([ - 'type' => 'friend_accepted', - 'friend' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ], - 'group' => [ - 'id' => $itemInfo['group']['id'], - 'name' => $itemInfo['group']['name'], - ], - ]); - - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleRefuseFriendNotice(UserModel $sender, UserModel $receiver) - { - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_FRIEND_REFUSED; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ] - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $online = Gateway::isUidOnline($receiver->id); - - if ($online) { - $content = kg_json_encode(['type' => 'refresh_msg_box']); - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleApplyGroupNotice(UserModel $sender, ImChatGroupModel $group, $remark) - { - $userRepo = new UserRepo(); - - $receiver = $userRepo->findById($group->user_id); - - $itemType = ImSystemMessageModel::TYPE_GROUP_REQUEST; - - $message = $userRepo->findImSystemMessage($receiver->id, $itemType); - - if ($message) { - $expired = time() - $message->create_time > 7 * 86400; - $pending = $message->item_info['status'] == ImSystemMessageModel::REQUEST_PENDING; - if (!$expired && $pending) { - return; - } - } - - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REQUEST; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ], - 'group' => [ - 'id' => $group->id, - 'name' => $group->name, - ], - 'remark' => $remark, - 'status' => ImSystemMessageModel::REQUEST_PENDING, - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $online = Gateway::isUidOnline($receiver->id); - - if ($online) { - $content = kg_json_encode(['type' => 'refresh_msg_box']); - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleAcceptGroupNotice(UserModel $sender, UserModel $receiver, ImChatGroupModel $group) - { - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_ACCEPTED; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ] - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - $online = Gateway::isUidOnline($receiver->id); - - if ($online) { - - $content = kg_json_encode([ - 'type' => 'group_accepted', - 'group' => [ - 'id' => $group->id, - 'name' => $group->name, - 'avatar' => $group->avatar, - ], - ]); - - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleRefuseGroupNotice(UserModel $sender, UserModel $receiver) - { - $sysMsgModel = new ImSystemMessageModel(); - - $sysMsgModel->sender_id = $sender->id; - $sysMsgModel->receiver_id = $receiver->id; - $sysMsgModel->item_type = ImSystemMessageModel::TYPE_GROUP_REFUSED; - $sysMsgModel->item_info = [ - 'sender' => [ - 'id' => $sender->id, - 'name' => $sender->name, - 'avatar' => $sender->avatar, - ] - ]; - - $sysMsgModel->create(); - - Gateway::$registerAddress = $this->getRegisterAddress(); - - if (Gateway::isUidOnline($receiver->id)) { - $content = kg_json_encode(['type' => 'refresh_msg_box']); - Gateway::sendToUid($receiver->id, $content); - } - } - - protected function handleNewGroupUserNotice(UserModel $newUser, ImChatGroupModel $group) - { - $groupRepo = new ImChatGroupRepo(); - - $users = $groupRepo->findGroupUsers($group->id); - - if ($users->count() == 0) { - return; - } - - Gateway::$registerAddress = $this->getRegisterAddress(); - - foreach ($users as $user) { - $content = kg_json_encode([ - 'type' => 'new_group_user', - 'user' => [ - 'id' => $newUser->id, - 'name' => $newUser->name, - 'avatar' => $newUser->avatar, - ], - 'group' => [ - 'id' => $group->id, - 'name' => $group->name, - 'avatar' => $group->avatar, - ], - ]); - if (Gateway::isUidOnline($user->id)) { - Gateway::sendToUid($user->id, $content); - } - } - } - - protected function getGroupName($groupId) - { - return "group_{$groupId}"; - } - - protected function getRegisterAddress() - { - return '127.0.0.1:1238'; - } - -} diff --git a/app/Library/Paginator/Query.php b/app/Library/Paginator/Query.php index 8b52d817..da05ed7a 100644 --- a/app/Library/Paginator/Query.php +++ b/app/Library/Paginator/Query.php @@ -27,7 +27,7 @@ class Query public function getLimit() { - $limit = $this->request->get('limit', 'int', 15); + $limit = $this->request->get('limit', 'int', 12); return $limit > 100 ? 100 : $limit; } diff --git a/app/Models/Chapter.php b/app/Models/Chapter.php index e51fc963..bdc74fcf 100644 --- a/app/Models/Chapter.php +++ b/app/Models/Chapter.php @@ -107,7 +107,7 @@ class Chapter extends Model /** * 扩展属性 * - * @var string + * @var string|array */ public $attrs; @@ -225,7 +225,7 @@ class Chapter extends Model { $this->update_time = time(); - if (is_array($this->attrs) && !empty($this->attrs)) { + if (is_array($this->attrs)) { $this->attrs = kg_json_encode($this->attrs); } } @@ -264,8 +264,10 @@ class Chapter extends Model public function afterFetch() { - if (!empty($this->attrs)) { + if (!empty($this->attrs) && is_string($this->attrs)) { $this->attrs = json_decode($this->attrs, true); + } else { + $this->attrs = []; } } diff --git a/app/Models/Course.php b/app/Models/Course.php index efb1ec3a..b7305ac7 100644 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -160,7 +160,7 @@ class Course extends Model /** * 扩展属性 * - * @var string + * @var string|array */ public $attrs; @@ -295,7 +295,7 @@ class Course extends Model $this->cover = self::getCoverPath($this->cover); } - if (is_array($this->attrs) && !empty($this->attrs)) { + if (is_array($this->attrs)) { $this->attrs = kg_json_encode($this->attrs); } } @@ -318,8 +318,10 @@ class Course extends Model $this->cover = kg_ci_cover_img_url($this->cover); } - if (!empty($this->attrs)) { + if (!empty($this->attrs) && is_string($this->attrs)) { $this->attrs = json_decode($this->attrs, true); + } else { + $this->attrs = []; } } diff --git a/app/Models/Order.php b/app/Models/Order.php index ef5d20df..48100c4e 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -162,10 +162,10 @@ class Order extends Model $this->sn = date('YmdHis') . rand(1000, 9999); $this->create_time = time(); - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } else { - $this->item_info = ''; + $this->item_info = ''; // text类型不能填充默认值 } } @@ -173,7 +173,7 @@ class Order extends Model { $this->update_time = time(); - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } } @@ -192,8 +192,10 @@ class Order extends Model { $this->amount = (float)$this->amount; - if (!empty($this->item_info)) { + if (!empty($this->item_info) && is_string($this->item_info)) { $this->item_info = json_decode($this->item_info, true); + } else { + $this->item_info = []; } } diff --git a/app/Models/Task.php b/app/Models/Task.php index 3b69dbc2..ce2e72ed 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -50,7 +50,7 @@ class Task extends Model /** * 条目内容 * - * @var string + * @var string|array */ public $item_info; @@ -103,7 +103,7 @@ class Task extends Model if (!empty($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } else { - $this->item_info = ''; + $this->item_info = ''; // text类型不能填充默认值 } } @@ -111,15 +111,17 @@ class Task extends Model { $this->update_time = time(); - if (is_array($this->item_info) && !empty($this->item_info)) { + if (is_array($this->item_info)) { $this->item_info = kg_json_encode($this->item_info); } } public function afterFetch() { - if (!empty($this->item_info)) { + if (!empty($this->item_info) && is_string($this->item_info)) { $this->item_info = json_decode($this->item_info, true); + } else { + $this->item_info = []; } } diff --git a/app/Models/User.php b/app/Models/User.php index 841a7343..b651c594 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -22,6 +22,20 @@ class User extends Model const EDU_ROLE_STUDENT = 1; // 学员 const EDU_ROLE_TEACHER = 2; // 讲师 + /** + * @var array + * + * 即时通讯设置 + */ + protected $_im = [ + 'sign' => '', + 'skin' => '', + 'online' => [ + 'status' => 'online', + 'time' => 0, + ], + ]; + /** * 主键编号 * @@ -50,13 +64,6 @@ class User extends Model */ public $title; - /** - * 签名 - * - * @var string - */ - public $sign; - /** * 介绍 * @@ -64,6 +71,13 @@ class User extends Model */ public $about; + /** + * im设置 + * + * @var string|array + */ + public $im; + /** * 所在地 * @@ -74,7 +88,7 @@ class User extends Model /** * 性别 * - * @var string + * @var int */ public $gender; @@ -92,13 +106,6 @@ class User extends Model */ public $admin_role; - /** - * 在线标识 - * - * @var int - */ - public $online; - /** * 会员标识 * @@ -111,7 +118,7 @@ class User extends Model * * @var int */ - public $block; + public $locked; /** * 删除标识 @@ -176,6 +183,8 @@ class User extends Model { $this->create_time = time(); + $this->im = kg_json_encode($this->_im); + if (Text::startsWith($this->avatar, 'http')) { $this->avatar = self::getAvatarPath($this->avatar); } elseif (empty($this->avatar)) { @@ -190,6 +199,10 @@ class User extends Model if (Text::startsWith($this->avatar, 'http')) { $this->avatar = self::getAvatarPath($this->avatar); } + + if (is_array($this->im)) { + $this->im = kg_json_encode($this->im); + } } public function afterCreate() @@ -204,6 +217,12 @@ class User extends Model if (!Text::startsWith($this->avatar, 'http')) { $this->avatar = kg_ci_avatar_img_url($this->avatar); } + + if (!empty($this->im) && is_string($this->im)) { + $this->im = json_decode($this->im, true); + } else { + $this->im = []; + } } public static function getAvatarPath($url) @@ -232,4 +251,9 @@ class User extends Model ]; } + public function setAvatar($avatar) + { + $this->avatar = $avatar; + } + } diff --git a/app/Traits/Auth.php b/app/Traits/Auth.php index bd14d5f8..b0abb240 100644 --- a/app/Traits/Auth.php +++ b/app/Traits/Auth.php @@ -40,7 +40,13 @@ trait Auth $userRepo = new UserRepo(); - return $userRepo->findById($authUser['id']); + $user = $userRepo->findById($authUser['id']); + + if (time() - $user->active_time > 600) { + $user->update(['active_time' => time()]); + } + + return $user; } /** diff --git a/app/Validators/User.php b/app/Validators/User.php index 6e019c63..bb745222 100644 --- a/app/Validators/User.php +++ b/app/Validators/User.php @@ -101,19 +101,28 @@ class User extends Validator return $value; } - public function checkSign($sign) + public function checkImSign($sign) { $value = $this->filter->sanitize($sign, ['trim', 'string']); $length = kg_strlen($value); if ($length > 50) { - throw new BadRequestException('user.sign_too_long'); + throw new BadRequestException('user.im_sign_too_long'); } return $value; } + public function checkImSkin($url) + { + if (empty($url)) { + throw new BadRequestException('user.invalid_im_skin'); + } + + return $url; + } + public function checkGender($value) { $list = UserModel::genderTypes(); diff --git a/public/static/web/css/common.css b/public/static/web/css/common.css index 38f4bf91..101f960c 100644 --- a/public/static/web/css/common.css +++ b/public/static/web/css/common.css @@ -78,6 +78,10 @@ padding-bottom: 1px; } +.layui-fixbar { + bottom: 60px; +} + #header { left: 0; top: 0; diff --git a/public/static/web/js/im.js b/public/static/web/js/im.js index d5359d6d..c532f6b9 100644 --- a/public/static/web/js/im.js +++ b/public/static/web/js/im.js @@ -65,6 +65,10 @@ layui.use(['jquery', 'layim'], function () { sendChatMessage(res); }); + layim.on('chatChange', function (res) { + console.log(res); + }); + layim.on('online', function (status) { $.ajax({ type: 'POST', @@ -81,6 +85,14 @@ layui.use(['jquery', 'layim'], function () { }); }); + layim.on('setSkin', function (file, src) { + $.ajax({ + type: 'POST', + url: '/im/skin/update', + data: {skin: src} + }); + }); + function bindUser(res) { $.ajax({ type: 'POST',