getAll(['user_id' => $user_ids], compact('_field')); $users = arrayFormatKey($users, 'user_id'); $objGroupInfo = new TableHelper('group_info', 'dw_chat'); $_field = 'group_id, group_name, group_title, cover_photo'; $groups = $objGroupInfo->getAll(['group_id' => $group_ids], compact('_field')); $groups = arrayFormatKey($groups, 'group_id'); $userGroups = []; if ($currentGroupId) { $objUserGroup = new UserGroup(); $userGroups = $objUserGroup->objTable->getAll(['user_id' => $user_ids, 'group_id' => $currentGroupId], ['_field' => 'user_id, group_id']); $userGroups = arrayFormatKey($userGroups, 'user_id', 'group_id'); } foreach ($list as $i => $item) { if ($item['is_group']) { $group = $groups[$item['session_id']]; $item['name'] = $group['group_title'] ?: $group['group_name']; $item['cover_photo'] = $group['cover_photo']; } else { // 把自己的用户名换掉 $key = str_replace([$user_id, '-'], ['', ''], $item['session_id']); $user = $users[$key]; $item['name'] = $user['nick_name']; $item['cover_photo'] = $user['cover_photo']; $item['in_group'] = $userGroups[$key] ? 1 : 0; // 已经在群 } $list[$i] = $item; } return $list; } public function getMsgList($session_id, $read_hash, $load_type, $is_group) { $where2 = [ 'state' => 1, ]; if ($is_group) { $_field = '`hash`, `from`, `msg`, `msg_type`, `state`, create_time_int'; $objMsg = new TableHelper('group_msg', 'dw_chat'); $where2['group_id'] = $session_id; } else { $_field = '`hash`, `from`, `to`, `msg`, `msg_type`, `state`, create_time_int'; $objMsg = new TableHelper('person_msg', 'dw_chat'); $where2['session_id'] = $session_id; } if ($read_hash) { $currentRow = $objMsg->getRow(['hash' => $read_hash], compact('_field')); $create_time_int = (int) $currentRow['create_time_int']; } else { $create_time_int = 0; } $_limit = 100; $maxNum = 1000; $need_clear = false; if ($load_type == 0) { // 正常加载 if ($create_time_int > 0) { $_limit = $maxNum; // 需要判断是否存在过多未读消息 $_where = "create_time_int > {$create_time_int}"; $num = $objMsg->getCount($where2, compact('_where')); if ($num > $maxNum) { // 这种情况抛弃create_time_int...,消息太多了,只拿最新的1000条记录 $create_time_int = 0; $need_clear = true; } } $create_time_int && $_where = "create_time_int > {$create_time_int}"; $_sortKey = "create_time_int DESC"; $keyWord2 = compact('_where', '_sortKey', '_limit', '_field'); $list = $objMsg->getAll($where2, $keyWord2); } else { // 加载历史记录 $_where = "create_time_int < {$create_time_int}"; $_sortKey = "create_time_int DESC"; $keyWord3 = compact('_where', '_sortKey', '_limit', '_field'); $list = $objMsg->getAll($where2, $keyWord3); } $list = array_reverse($list); $list = $this->appendExtInfo($list); $user_ids = array_column($list, 'from'); if (!$is_group) { $to_ids = array_column($list, 'to'); $user_ids = array_merge($user_ids, $to_ids); } $user_ids = array_unique($user_ids); $userMap = $this->getUserMap($user_ids); return compact('userMap', 'list', 'need_clear'); } /** * 额外信息 * @author solu * @param $list * @return mixed */ private function appendExtInfo($list) { $userId = User::getUserId(); $objRedpackLog = new RedpackLog(); $trxIds = array_map(function($v) { $msg = Utils::decodeRC4($v['msg']); $data = json_decode($msg, true); return $data['trxId']; }, array_filter($list, function($v) { return $v['msg_type'] == self::MSG_TYPE_REDPACK; })); $redpack = []; if ($trxIds) { $objRedpack = new Redpack(); $redpack = $objRedpack->objTable->getAll(['transfer_trx_id' => $trxIds], ['_field' => 'transfer_trx_id, status']); $redpack = arrayFormatKey($redpack, 'transfer_trx_id', 'status'); } foreach ($list as $k => $v) { if ($v['msg_type'] == self::MSG_TYPE_REDPACK) { $msg = Utils::decodeRC4($v['msg']); $data = json_decode($msg, true); $trxId = $data['trxId']; $v['ext']['grabbed'] = $objRedpackLog->userGrabbed($userId, $trxId); $v['ext']['redpack_status'] = intval($redpack[$trxId]); } $list[$k] = $v; } return $list; } public function getUserMap($user_ids) { $objUserInfo = new TableHelper('user_info', 'dw_chat'); $datas = $objUserInfo->getAll(['user_id' => $user_ids], ['_field' => 'user_id, user_name, nick_name, cover_photo']); return arrayFormatKey($datas, 'user_id'); } /** * 修改状态 * @param $session_id * @param $newData * @param $ext; */ public function updateState($session_id, $newData, $ext = []) { $where = compact('session_id'); $where = array_merge($where, $ext); $newData['update_time'] = NOW; $newData['update_time_int'] = microtime(true) * 1000; $this->objTable->updateObject($newData, $where); } /** * 检测私聊session * @author solu * @param $from * @param $sessionId * @return array * @throws Exception */ public function checkPersonSession($from, $sessionId) { $uids = explode('-', $sessionId); $uids = array_filter($uids, function ($v) {return $v > 0;}); // if (count($uids) != 2 || !$this->objTable->getRow(['user_id' => $from, 'session_id' => $sessionId])) { // throw new Exception('session_id error', CODE_PARAM_ERROR); // } if (!in_array($from, $uids)) { throw new Exception('user not in session', CODE_NO_PERMITION); } $to = 0; foreach ($uids as $uid) { if ($uid != $from) { $to = $uid; break; } } return [$from, $to]; } /** * 检测群session * @author solu * @param $from * @param $sessionId * @return bool * @throws Exception */ public function checkGroupSession($from, $sessionId) { if (!$this->objTable->getRow(['user_id' => $from, 'session_id' => $sessionId])) { throw new Exception('user not in session', CODE_NO_PERMITION); } return true; } public static function getPersonSessionId($from, $to) { if ($from > $to) { return "{$to}-{$from}"; } else { return "{$from}-{$to}"; } } private function initPersonSession($from, $to) { $session_id = self::getPersonSessionId($from, $to); $num = $this->objTable->getCount(compact('session_id')); if (!$num) { // 插入双方的session $datas = [[ 'user_id' => $from, 'session_id' => $session_id, 'is_group' => 0, ], [ 'user_id' => $to, 'session_id' => $session_id, 'is_group' => 0, ] ]; // 第一次初始化,需要初始化 $this->objTable->addObjectsIfNoExist($datas); } } /** * 发送私聊消息 * @author solu * @param $from * @param $sessionId * @param $msg_type * @param $msg * @param $noEvent * @return array * @throws Exception */ public function sendPersonMsg($from, $sessionId, $msg_type, $msg, $noEvent = false) { list($from, $to) = $this->checkPersonSession($from, $sessionId); $this->initPersonSession($from, $to); $t = self::getMS(); 0 == $msg_type && $msg = htmlentities($msg); $data = [ 'session_id' => $sessionId, 'from' => intval($from), 'to' => intval($to), 'msg_type' => $msg_type, 'msg' => $msg, 'create_time' => NOW, 'create_time_int' => $t, ]; $data['hash'] = self::_genHash($data); $objPersonMsg = new TableHelper('person_msg', 'dw_chat'); if (!$objPersonMsg->addObject($data)) { throw new Exception('send message error', CODE_NORMAL_ERROR); } $eventData = [ 'type' => 'msg', 'from' => $from, 'to' => strval($to), 'content' => self::_msgHandle($msg, $msg_type), 'hash' => $data['hash'], 'timestamp' => $t, ]; !$noEvent && ThirdApi::pushPersonEvent($to, $eventData); $this->updateState($sessionId, []); $eventData['content'] = $msg; return $eventData; } /** * 发送群聊消息 * @author solu * @param $from * @param $groupId * @param $msg_type * @param $msg * @param $noEvent * @return array * @throws Exception */ public function sendGroupMsg($from, $groupId, $msg_type, $msg, $noEvent = false) { $userMap = null; if (!$this->objTable->getRow(['user_id' => $from, 'session_id' => $groupId])) { // 聊天就自动加入群 $objGroup = new GroupInfo(); $objGroup->joinGroup($from, $groupId); // 第一次发言,需要返回用户信息 $userMap = $this->getUserMap($from); } else if ((new UserGroup())->isBlock($groupId, $from)) { throw new Exception('Banned', CODE_NORMAL_ERROR); } $t = self::getMS(); 0 == $msg_type && $msg = htmlentities($msg); $data = [ 'group_id' => intval($groupId), 'from' => $from, 'msg_type' => $msg_type, 'msg' => $msg, 'create_time' => NOW, 'create_time_int' => $t, ]; $data['hash'] = self::_genHash($data); $objGroupMsg = new TableHelper('group_msg', 'dw_chat'); if (!$objGroupMsg->addObject($data)) { throw new Exception('send message error', CODE_NORMAL_ERROR); } $eventData = [ 'type' => 'msg', 'msg_type' => $msg_type, 'from' => $from, 'content' => self::_msgHandle($msg, $msg_type), 'hash' => $data['hash'], 'timestamp' => $t, ]; !$noEvent && ThirdApi::pushGroupEvent($groupId, $eventData); $eventData['content'] = $msg; $eventData['userMap'] = $userMap; return $eventData; } private static function _genHash($data) { return md5(json_encode($data)); } public static function _msgHandle($content, $msg_type, $len = 16) { if ($msg_type > 0) { // 只处理文本 return $content; } $source = Utils::decodeRC4($content); !$source && $source = $content; if (mb_strlen($source) > $len) { $source = mb_substr($source, 0, $len); } return Utils::encodeRC4($source); } public static function getMS() { return intval(microtime(true) * 1000); } }