['int', 'desc' => '群id'], ]; Param::checkParam2($rules, $args); $objGroupInfo = new GroupInfo(); $_field = 'group_id, group_name, group_title, group_notice, cover_photo, member_num, creator'; $group = $objGroupInfo->objTable->getRow($args, compact('_field')); $group && $group['invite_url'] = GroupInfo::genInviteUrl($group['group_name']); $group['increase_num'] = 0; $_field = 'user_id, is_admin, is_block, join_time'; $objUserGroup = new UserGroup(); $groupUsers = $objUserGroup->objTable->getAll(['group_id' => $args['group_id'], 'state' => 1], ['_field' => $_field, '_sortKey' => 'join_time ASC', '_limit' => 100]); $joinMap = arrayFormatKey($groupUsers, 'user_id', 'join_time'); $user_ids = []; $blockList = []; $adminList = []; foreach ($groupUsers as $_u) { $_uid = intval($_u['user_id']); $user_ids[] = $_uid; $_u['is_block'] && $blockList[] = $_uid; $_u['is_admin'] && $adminList[] = $_uid; } // 获取pin的消息 $objGroupMsg = new TableHelper('group_msg', 'dw_chat'); $where2 = [ 'group_id' => $args['group_id'], 'is_pin' => 1, '_field' => '`from`, hash, msg, msg_type' ]; $pinMsg = $objGroupMsg->getRow($where2); $inList = in_array($pinMsg['from'], $user_ids); $user_ids[] = $pinMsg['from']; $objUserInfo = new TableHelper('user_info', 'dw_chat'); $_field = 'user_id, user_name, nick_name, cover_photo'; $members = $objUserInfo->getAll(['user_id' => $user_ids], compact('_field')); coverReplaceArrImage($members, 'cover_photo'); $members = arrayFormatKey($members, 'user_id'); $joinTimes = []; $adminNum = 0; $newMembers = []; foreach ($groupUsers as $_u) { $_uid = intval($_u['user_id']); if ($members[$_uid]) { $joinTime = strtotime($joinMap[$_uid]); $joinTime < 0 && $joinTime = time(); if ($_u['is_block']) { $members[$_uid]['is_block'] = (int) $_u['is_block']; } if ($_u['is_admin']) { $members[$_uid]['is_admin'] = (int) $_u['is_admin']; $joinTime = $adminNum++; if ($group['creator'] == $_uid) { $members[$_uid]['is_admin'] = 2; $joinTime = -1; } } $newMembers[] = $members[$_uid]; $joinTimes[$_uid] = $joinTime; } } $members = $newMembers; array_multisort($joinTimes, SORT_ASC, $members); // 置顶消息用户信息 $pinMsg = array_merge($pinMsg, arrayFilter($members[$pinMsg['from']], ['user_name', 'nick_name', 'cover_photo'])); if (!$inList) { foreach ($members as $i => $member) { if ($pinMsg['from'] == $member['user_id']) { unset($members[$pinMsg['from']]); } } $members = array_values($members); } $user_id = User::getUserId(); $sessionInfo = null; if ($user_id) { $objSession = new Session(); $sessionInfo = $objSession->objTable->getRow(['user_id' => $user_id, 'session_id' => $args['group_id']], ['_field' => 'is_pin, pin_time_int, is_mute']); } $objGroupEos = new TableHelper('group_eos', 'dw_chat'); $eosInfo = $objGroupEos->getRow($args); return compact('group', 'eosInfo', 'members', 'pinMsg', 'sessionInfo', 'blockList', 'adminList'); } /** * 群聊 获取最新消息【不需要登录】 * @author benzhan */ public function actionNewMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'client_hash' => ['string', 'nullable' => true, 'desc' => '客户端上的最新消息的hash'], ]; Param::checkParam2($rules, $args); $load_type = 0; return $this->_msg($args['group_id'], $load_type, $args['client_hash']); } /** * 群聊 获取历史消息【不需要登录】 * @author benzhan */ public function actionHistoryMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'client_hash' => ['string', 'desc' => '客户端上的最旧消息的hash'], ]; Param::checkParam2($rules, $args); $load_type = -1; return $this->_msg($args['group_id'], $load_type, $args['client_hash']); } /** * 获取消息列表 * @param $session_id string 会话id * @param $load_type int 加载方式:-1:历史消息, 0:最新消息 * @param $client_hash string 客户端的hash * * @return array */ private function _msg($session_id, $load_type, $client_hash) { $where = compact('session_id'); $keyWord = [ '_field' => 'is_group, read_hash, read_num', ]; $objSession = new Session(); $row = $objSession->objTable->getRow($where, $keyWord); if (!$row) { Response::error(CODE_NO_PERMITION, 'session is not found'); } else if (!$row['is_group']) { Response::error(CODE_NO_PERMITION, 'session is not group'); } $data = $objSession->getMsgList($session_id, $client_hash, $load_type, 1); $userId = User::getUserId(); if ($userId) { $c = count($data['list']); $lastNum = $data['list'][$c-1]['msg_num']; if ($lastNum > $row['read_num']) { $objSession->updateState($session_id, ['read_num' => $lastNum], ['user_id' => $userId]); } } $data['list'] = array_filter($data['list'], function ($v) { return $v['state'] == 1; }); return $data; } /** * 发送群聊消息 * @author solu * @param $args * @return array */ public function actionSendMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'msg_type' => ['int', 'nullable' => true, 'default' => 0, 'desc' => '消息类型:0:文本,1:图片,2:视频'], 'msg' => ['string', 'desc' => '内容'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); $objSession = new Session(); $data = []; try { $data = $objSession->sendGroupMsg($userId, $args['group_id'], $args['msg_type'], $args['msg']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } return $data; } public function actionSendImageMsg($args) { return $this->actionSendFile($args); } /** * 群聊 发送多媒体消息 * @author solu * @param $args * @return array */ public function actionSendFile($args) { $args = array_merge($args, $_FILES); $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'res' => ['array', 'desc' => '资源文件'], ]; Param::checkParam2($rules, $args); $data = null; try { $msgType = FileUrl::getType($args['res']['type']); $maxSize = 1000 * 1000; // 默认最大1MB switch ($msgType) { case FileUrl::TYPE_IMAGE: $maxSize = 1000 * 1000; // 图片最大1MB break; case FileUrl::TYPE_VIDEO: $maxSize = 3000 * 1000; // 视频最大3MB break; case FileUrl::TYPE_AUDIO: $maxSize = 2000 * 1000; // 音频最大2MB break; default: Response::error(CODE_PARAM_ERROR, 'unknown type:' . $args['res']['type']); } $size = filesize($args['res']['tmp_name']); if ($size > $maxSize) { Response::error(CODE_PARAM_ERROR, "file is too big. size:{$size}"); } $url = (new FileUrl())->getFileUrl($args['res']['tmp_name'], $args['res']['name'], $args['res']['type']); $url = awsReplaceImg($url); $msg = Utils::encodeRC4($url); $userId = User::getUserId(); $objSession = new Session(); $data = $objSession->sendGroupMsg($userId, $args['group_id'], $msgType, $msg); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } return $data; } /** * 群聊 置顶消息 * @author solu * @param $args */ public function actionPinMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'hash' => ['string', 'desc' => '消息hash'], ]; Param::checkParam2($rules, $args); $group_id = (int) $args['group_id']; $this->_checkGroupAdmin($group_id); $objGroupMsg = new TableHelper('group_msg', 'dw_chat'); $_field = '`from`, hash, msg, msg_type'; $row = $objGroupMsg->getRow($args, compact('_field')); if (!$row) { Response::error(CODE_NORMAL_ERROR, 'can not find the msg'); } $where2 = [ 'group_id' => $group_id, 'is_pin' => 1, ]; // 取消老的pin $objGroupMsg->updateObject(['is_pin' => 0], $where2); $objGroupMsg->updateObject(['is_pin' => 1], $args); $objUser = new TableHelper('user_info', 'dw_chat'); $user = $objUser->getRow(['user_id' => $row['from']]); $row = array_merge($row, arrayFilter($user, ['user_name', 'nick_name', 'cover_photo'])); // 给群组发消息有pinMsg ThirdApi::pushGroupEvent($group_id, [ 'type' => 'pin_msg', 'group_id' => $group_id, 'pinMsg' => $row, ]); return $row; } /** * 群聊 取消置顶消息 * @author solu * @param $args */ public function actionUnpinMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'hash' => ['string', 'desc' => '消息hash'], ]; Param::checkParam2($rules, $args); $group_id = (int) $args['group_id']; $this->_checkGroupAdmin($group_id); $objGroupMsg = new TableHelper('group_msg', 'dw_chat'); $count = $objGroupMsg->getCount($args); if (!$count) { Response::error(CODE_NORMAL_ERROR, 'can not find the msg'); } // 取消老的pin $objGroupMsg->updateObject(['is_pin' => 0], $args); // 给群组发消息有人加入了 ThirdApi::pushGroupEvent($group_id, [ 'type' => 'unpin_msg', 'group_id' => $group_id, 'hash' => $args['hash'], ]); return $args['hash']; } /** * 获取朋友 * @author benzhan */ public function actionGetFriends($args) { Param::checkParam2([], $args); $user_id = User::getUserId(); $is_group = 0; $where = compact('user_id', 'is_group'); $keyWord = [ '_field' => 'session_id', '_sort' => 'update_time_int DESC', '_limit' => 500, // 最多加载500个会话 ]; $objSession = new Session(); $session_ids = $objSession->objTable->getCol($where, $keyWord); $friend_ids = array_map(function($session_id) use ($user_id) { return str_replace(['-', $user_id], ['', ''], $session_id); }, $session_ids); $objUserInfo = new TableHelper('user_info', 'dw_chat'); $_field = 'user_id, user_name, nick_name, cover_photo'; $users = $objUserInfo->getAll(['user_id' => $friend_ids], compact('_field')); return $users; } // 只过滤出真正的朋友 private function _getFriendList($userId, $friend_id_list) { $friend_ids = explode(',', $friend_id_list); $map = []; foreach ($friend_ids as $friend_id) { $friend_id = (int) $friend_id; $sessionId = Session::getPersonSessionId($userId, $friend_id); $map[$sessionId] = $friend_id; } if (!$map) { return []; } $where = [ 'user_id' => $userId, 'session_id' => array_keys($map), ]; $_field = 'session_id'; $objSession = new Session(); $sessionIds = $objSession->objTable->getCol($where, compact('_field')); if (!$sessionIds) return []; $friend_ids = []; foreach ($sessionIds as $sessionId) { $friend_ids[] = $map[$sessionId]; } return $friend_ids; } /** * 创建群组 * @author benzhan */ public function actionCreate($args) { $rules = [ 'group_title' => ['string', 'desc' => '群名称'], 'cover_photo' => ['string', 'nullable' => true, 'desc' => '群logo'], 'user_id_list' => ['string', 'nullable' => true, 'desc' => '好友id列表用,隔开'], ]; Param::checkParam2($rules, $args); $user_id_list = arrayPop($args, 'user_id_list'); $creator = User::getUserId(); $objGroupInfo = new GroupInfo(); $num = $objGroupInfo->objTable->getCount(compact('creator')); if ($num >= 100) { Response::error(CODE_NO_PERMITION, "create group num >= {$num}"); } $args['creator'] = User::getUserId(); $args['member_num'] = 0; $args['create_time'] = $args['update_time'] = NOW; $objGroupInfo->objTable->addObject($args); $group_id = $objGroupInfo->objTable->getInsertId(); // 设置group_name $objGroupInfo->objTable->updateObject(['group_name' => $group_id], ['group_id' => $group_id]); // 默认加群 $this->actionJoin(compact('group_id')); // 设置为管理员 $objUserGroup = new UserGroup(); $data = [ 'is_admin' => 1, 'state' => UserGroup::STATE_IN_GROUP, ]; $objUserGroup->setData($group_id, $creator, $data); $friend_ids = $this->_getFriendList($creator, $user_id_list); if ($friend_ids) { $objGroupInfo->appendToGroup($friend_ids, $group_id); } $objSession = new Session(); $_field = 'session_id, is_group, read_hash, is_pin, pin_time_int, is_mute'; $sesion = $objSession->objTable->getRow(['session_id' => $group_id], compact('_field')); $sesion['name'] = $args['group_title']; $sesion['cover_photo'] = $args['cover_photo']; return $sesion; } /** * 加入群组 * @author solu */ public function actionJoin($args) { $rules = [ 'group_id' => ['int', 'desc' => '群组id'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); try { (new GroupInfo())->joinGroup($userId, $args['group_id']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } /** * 离开群组 * @author solu */ public function actionLeave($args) { $rules = [ 'group_id' => ['int', 'desc' => '群组id'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); try { (new GroupInfo())->leaveGroup($userId, $args['group_id']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } /** * 封禁用户 * @author benzhan */ public function actionBlockUser($args) { $rules = [ 'group_id' => ['int', 'desc' => '群组id'], 'block_id' => ['int', 'desc' => '用户id'], ]; Param::checkParam2($rules, $args); $group_id = (int) $args['group_id']; $user_id = (int) $args['block_id']; $this->_checkGroupAdmin($group_id); $objUserGroup = new UserGroup(); $objUserGroup->setBlock($group_id, $user_id, 1); $eventData = [ 'type' => 'block', 'group_id' => $group_id, 'from' => User::getUserId(), 'to' => $user_id, 'timestamp' => Session::getMS(), ]; ThirdApi::pushGroupEvent($group_id, $eventData); } /** * 解禁用户 * @author solu */ public function actionUnblockUser($args) { $rules = [ 'group_id' => ['int', 'desc' => '群组id'], 'block_id' => ['int', 'desc' => '用户id'], ]; Param::checkParam2($rules, $args); $group_id = (int) $args['group_id']; $user_id = (int) $args['block_id']; $this->_checkGroupAdmin($group_id); $objUserGroup = new UserGroup(); $objUserGroup->setBlock($group_id, $user_id, 0); $eventData = [ 'type' => 'unblock', 'group_id' => $group_id, 'from' => User::getUserId(), 'to' => $user_id, 'timestamp' => Session::getMS(), ]; ThirdApi::pushGroupEvent($group_id, $eventData); } private function _checkGroupAdmin($group_id) { $owner = User::getUserId(); $objUserGroup = new UserGroup(); if (!$objUserGroup->isAdmin($group_id, $owner)) { Response::error(CODE_NO_PERMITION); } } /** * 更新群名称(只能一次 * @author solu * @param $args */ public function actionChangeName($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'name' => ['string', 'reg' => '/^[a-z0-9\.]+/i', 'desc' => '新群名'], ]; Param::checkParam2($rules, $args); $objGroup = new GroupInfo(); $userId = User::getUserId(); $groupId = (int)$args['group_id']; if (is_numeric($args['name'])) { Response::error(CODE_PARAM_ERROR, 'name can not be pure numbers'); } $groupInfo = $objGroup->objTable->getRow(['group_id' => $groupId]); if (!$groupInfo) { Response::error(CODE_PARAM_ERROR, 'group not exists'); } // 已修改过群名称 if ($groupInfo['group_id'] != $groupInfo['group_name']) { Response::error(CODE_PARAM_ERROR, 'only one change group name'); } if ($objGroup->objTable->getRow(['group_name' => $args['name']])) { Response::error(CODE_PARAM_ERROR, 'group name exists'); } $data = [ 'group_name' => htmlentities($args['name']), ]; try { $objGroup->setData($userId, $args['group_id'], $data); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } ThirdApi::pushGroupEvent($args['group_id'], [ 'type' => 'update', 'from' => $userId, ]); } /** * 更新群公告 * @author solu * @param $args */ public function actionChangeNotice($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'notice' => ['string', 'desc' => '新公告'], ]; Param::checkParam2($rules, $args); $objGroup = new GroupInfo(); $userId = User::getUserId(); $data = [ 'group_notice' => htmlentities($args['notice']), ]; try { $objGroup->setData($userId, $args['group_id'], $data); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } ThirdApi::pushGroupEvent($args['group_id'], [ 'type' => 'update', 'from' => $userId, ]); } /** * 更新群图标 * @author solu * @param $args */ public function actionChangeCover($args) { $args = array_merge($args, $_FILES); $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'cover_photo' => ['array', 'desc' => '头像文件'], ]; Param::checkParam2($rules, $args); $file = $args['cover_photo']; $cover_photo = ''; try { $cover_photo = (new FileUrl())->getFileUrl($file['tmp_name'], $file['name'], $file['type'], true); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } $objGroup = new GroupInfo(); $userId = User::getUserId(); $data = [ 'cover_photo' => $cover_photo, ]; try { $objGroup->setData($userId, $args['group_id'], $data); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } ThirdApi::pushGroupEvent($args['group_id'], [ 'type' => 'update', 'from' => $userId, ]); } /** * 更新群标题 * @author solu * @param $args */ public function actionChangeTitle($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'title' => ['string', 'desc' => '新标题'], ]; Param::checkParam2($rules, $args); $objGroup = new GroupInfo(); $userId = User::getUserId(); $data = [ 'group_title' => htmlentities($args['title']), ]; try { $objGroup->setData($userId, $args['group_id'], $data); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } ThirdApi::pushGroupEvent($args['group_id'], [ 'type' => 'update', 'from' => $userId, ]); GroupInfo::setGroupNameById($args['group_id'], $data['group_title']); } /** * 批量邀请用户加入群 * @author solu * @param $args * @return array */ public function actionInvites($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'user_ids' => ['string', 'desc' => '用户id 多人,分割'], ]; Param::checkParam2($rules, $args); $groupId = (int)$args['group_id']; $userIds = array_filter(explode(',', $args['user_ids']), function ($v) { return intval($v) > 0; }); $adminId = User::getUserId(); if (!(new UserGroup())->isAdmin($groupId, $adminId)) { Response::error(CODE_NO_PERMITION, 'no permission'); } $count = count($userIds); $success = 0; $objGroupInfo = new GroupInfo(); foreach ($userIds as $userId) { try { $objGroupInfo->joinGroup($userId, $groupId); $success += 1; } catch (Exception $e) {} } return compact('count', 'success'); } /** * 批量移除群用户 * @author solu * @param $args * @return array */ public function actionRemoves($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'user_ids' => ['string', 'desc' => '用户id 多人,分割'], ]; Param::checkParam2($rules, $args); $groupId = (int)$args['group_id']; $userIds = array_filter(explode(',', $args['user_ids']), function ($v) { return intval($v) > 0; }); $adminId = User::getUserId(); if (!(new UserGroup())->isAdmin($groupId, $adminId)) { Response::error(CODE_NO_PERMITION, 'no permission'); } $count = count($userIds); $success = 0; $objGroupInfo = new GroupInfo(); $group = $objGroupInfo->objTable->getRow(['group_id' => $groupId]); if (!$group) { Response::error(CODE_PARAM_ERROR, 'group not exists'); } foreach ($userIds as $userId) { try { $objGroupInfo->leaveGroup($userId, $groupId, $group); $success += 1; } catch (Exception $e) {} } return compact('count', 'success'); } /** * 撤销消息 * @author solu * @param $args */ public function actionRepealMsg($args) { $rules = [ 'group_id' => ['string', 'desc' => '群id'], 'hash' => ['string', 'desc' => '消息hash'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); $objMsg = new GroupMsg(); try { $objMsg->repeal($userId, $args['group_id'], $args['hash']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } /** * 添加管理员 * @author solu * @param $args */ public function actionAddAdmin($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'user_ids' => ['string', 'desc' => '用户id , 分割'], ]; Param::checkParam2($rules, $args); $creator = User::getUserId(); $userIds = array_map('intval', explode(',', $args['user_ids'])); try { (new GroupInfo())->addAdmin($args['group_id'], $creator, $userIds); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } /** * 移除管理员 * @author solu * @param $args */ public function actionRemoveAdmin($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'admin_id' => ['int', 'desc' => '管理员id'], ]; Param::checkParam2($rules, $args); $creator = User::getUserId(); try { (new GroupInfo())->removeAdmin($args['group_id'], $creator, $args['admin_id']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } /** * 搜索群成员信息 * @author solu * @param $args * @return array */ public function actionMemberSearch($args) { $rules = [ 'keyword' => ['string', 'desc' => '关键字'], 'group_id' => ['int', 'desc' => '群id'], ]; Param::checkParam2($rules, $args); return (new GroupInfo())->memberSearch($args['group_id'], $args['keyword']); } /** * 申请群认证 * @author solu * @param $args * @return array */ public function actionAuth($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); if (!(new UserGroup())->isAdmin($args['group_id'], $userId)) { Response::error(CODE_NO_PERMITION); } $serverId = 1; // 客服id $msg =<<sendPersonMsg($serverId, $sessionId, Session::MSG_TYPE_TEXT, $msg, true); } catch (Exception $e) {} return compact('serverId'); } /** * 转移群主 * @author solu * @param $args */ public function actionChangeCreator($args) { $rules = [ 'group_id' => ['int', 'desc' => '群id'], 'new_creator' => ['int', 'desc' => '新群主id'], ]; Param::checkParam2($rules, $args); $userId = User::getUserId(); try { (new GroupInfo())->changeCreator($args['group_id'], $userId, $args['new_creator']); } catch (Exception $e) { Response::error($e->getCode(), $e->getMessage()); } } }