/** * 获取存储于数据库的永久历史聊天记录 * 请求参数 是否必须 类型(示例) 说明 * chatid true string 属于该chatid下的聊天记录 * time false string 根据这个时间查找,rangeTm时可以没有 * class true string 查看的消息类型 nomal/image/attach * type true int 0:查以前的,1:查以后的 * accountid true/false string 如果chatid是群组则必须(查询入群时间)。否则非必须 * rangeTm false string 查询的范围。month/months/year * * 返回值 消息列表 * array(); */ public function doList() { $chatid = $this->toStr('chatid'); $accountid = $this->toStr('accountid'); $keywords = $this->toStr('keywords'); $time = $this->toStr('time'); $type = $this->toStr('classType') ? $this->toStr('classType') : 'nomal'; $selectType = $this->toInt('selectType'); $rangeMode = $this->toStr('rangeMode') ? $this->toStr('rangeMode') : ''; //根据rangeMode获取最小时间与最大时间 $timearr = self::getRangeTimestamp($rangeMode); $sTime = $timearr['stime']; //范围中 最小时间 $bTime = $timearr['btime']; //范围中最大时间 if (!$chatid) { $this->_error('参数出错'); } $time = false === strpos($time, '-') ? $time : strtotime($time) + 24 * 3600; //消息类型处理 $allowType = array(Storekey::CHAT_MSG_TYPE => 'nomal', Storekey::IMAGE_MSG_TYPE => 'image', Storekey::ATTACH_MSG_TYPE => 'attach'); if (!in_array($type, $allowType)) { $this->_error('参数出错'); } $type = array_search($type, $allowType); //如果是群聊天,获取用户进入该群的时间 $jointime = ''; if (false === strpos($chatid, '--')) { if (!$accountid) { $this->_error('参数缺少accountid'); } $group = explode('-', $chatid); $jointime = Mgroup::getJoinTime(array('master' => $group[0], 'uuid' => $group[1], 'accountid' => $accountid)); } $msgList = Mmessage::getMsgList(array('limit' => 10, 'fields' => array('fromuser', 'message', 'time'), 'time' => $time, 'chatid' => $chatid, 'joinTime' => $jointime, 'type' => $type, 'order' => 'order by id desc', 'selectType' => $selectType, 'stime' => $sTime, 'btime' => $bTime, 'keywords' => $keywords)); $this->_success($msgList); }
/** * 设置群的生存时间 * * 请求参数 是否必须 类型(示例) 说明 * chatid true string(cuihb-165726534) 唯一的groupid,可以是群主-时间戳 * * 返回值 :无返回值 */ public function doExpires() { $chatid = $this->toStr('chatid'); $group = explode('-', $chatid); Mgroup::setGroupExpire(array('master' => $group[0], 'uuid' => $group[1])); }
/** * 有消息时 * @param int $client_id * @param string $message */ public static function onMessage($client_id, $message) { // debug //echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n"; // 客户端传递的是json数据 $messageData = json_decode($message, true); if (!$messageData) { return; } // 根据类型执行不同的业务 switch ($messageData['type']) { // 客户端回应服务端的心跳 case 'pong': return; // 客户端登录 message格式: {type:login, clientName:xx} ,添加到客户端,广播给所有客户端xx上线 // 客户端登录 message格式: {type:login, clientName:xx} ,添加到客户端,广播给所有客户端xx上线 case 'login': // 判断是否有有名字 if (!isset($messageData['clientName'])) { throw new \Exception("\$messageData['clientName'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:{$message}"); } $clientName = htmlspecialchars(urldecode($messageData['clientName'])); //判断数据库中是否存在用户,不存在则关闭链接 if (!Muser::getUserinfo(array('accountid' => $clientName))) { //忽略的消息传给用户 Gateway::sendToCurrentClient(json_encode(array('type' => 'error', 'info' => 'erroruser', 'msg' => '用户名不存在'))); Gateway::closeClient($client_id); return; } // 把用户名放到session中 $_SESSION['clientName'] = $clientName; //存储用户到在线列表 self::addUserToOnlineList($client_id, $clientName); //转播给在线客户,xx上线 message {type:login, client_id:xx, name:xx} $new_message = array('type' => $messageData['type'], 'clientName' => $clientName, 'time' => time()); Gateway::sendToAll(json_encode($new_message)); return; case 'say': // 非法请求 if (!isset($_SESSION['clientName'])) { throw new \Exception("\$_SESSION['clientName'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}"); } $clientName = $_SESSION['clientName']; $chatid = $messageData['chatid']; //获取群成员 $chatList = Muser::getChatListFromChatid($messageData['chatid']); if (!is_array($chatList)) { return; } //判断消息类型 $msgType = Storekey::CHAT_MSG_TYPE; $filemd5 = ''; if (isset($messageData['msgType'])) { if ($messageData['msgType'] === 'file') { $msgType = Storekey::ATTACH_MSG_TYPE; $filemd5 = $messageData['filemd5']; } elseif ($messageData['msgType'] === 'image') { $msgType = Storekey::IMAGE_MSG_TYPE; } } //所有单人聊天、群组聊天消息都压入redis队列中,以便存储 $pushArr = self::makeMsg($chatid, $clientName, $messageData['content'], $msgType, $filemd5); self::msgIntoQueue($pushArr); // 聊天内容 $new_message = self::makeMsg($chatid, $clientName, $messageData['content'], 'say'); $jsonNewMessage = json_encode($new_message); //获取所有存储的在线用户 $clientLists = Muser::getOnlineUsers(); //获取该组用户在线的clientid,并广播 $onlineClientIds = self::getClientidsFromUsers($clientLists, $chatList); if ($onlineClientIds) { Gateway::sendToAll($jsonNewMessage, $onlineClientIds); } //获取该组用户所有不在线的用户,并生成离线消息队列 $offlineUsers = self::getOfflineUsers($clientLists, $chatList); if ($offlineUsers) { foreach ($offlineUsers as $offname) { Mmessage::addUnreadMsg($offname, $chatid, Storekey::UNREAD_MSG); } } return; case 'broadcast': if (!isset($messageData['touser']['member'])) { return; } $toUsersList = $messageData['touser']['member']; if (!$toUsersList || !is_array($toUsersList)) { return; } $toUsersList = array_unique($toUsersList); // 非法请求 if (!isset($_SESSION['clientName'])) { throw new \Exception("\$_SESSION['clientName'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}"); } $clientName = $_SESSION['clientName']; //makeMsg($chatid, $from, $content='', $type=0) //所有广播消息压入redis队列中,以便存储 $messageData['title'] = isset($messageData['title']) ? $messageData['title'] : '无标题'; $pushArr = array('fromuser' => $clientName, 'touser' => '-' . implode('-', $messageData['touser']['member']) . '-', 'touserTitle' => $messageData['touser']['title'], 'title' => addslashes($messageData['title']), 'content' => addslashes($messageData['content']), 'time' => time(), 'type' => Storekey::BROADCAST_MSG_TYPE); self::msgIntoQueue($pushArr); // 聊天内容.修改type,前端发送不必发送所有用户 $pushArr['type'] = 'broadcast'; unset($pushArr['touser']); $jsonNewMessage = json_encode($pushArr); //获取所有存储的在线用户 $clientLists = Muser::getOnlineUsers(); //获取该组用户在线的clientid $onlineClientIds = self::getClientidsFromUsers($clientLists, $toUsersList); if ($onlineClientIds) { Gateway::sendToAll($jsonNewMessage, $onlineClientIds); } //获取该组用户所有不在线的用户 $offlineUsers = self::getOfflineUsers($clientLists, $toUsersList); if ($offlineUsers) { foreach ($offlineUsers as $offname) { Mbroadcast::addUnreadBroadcastNum($offname, Storekey::UNREAD_BROADCAST); } } return; case 'groupset': // 非法请求 if (!isset($_SESSION['clientName'])) { throw new \Exception("\$_SESSION['clientName'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}"); } $clientName = $_SESSION['clientName']; //修改群组成员 $chatInfo = explode('-', $messageData['chatid']); //master=$chatInfo[0],uuid=$chatInfo[1] //获取已有群成员信息 $originalMembers = \Api\Model\Mgroup::getGroupMembers(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1])); $setRes = \Api\Model\Mgroup::setGroup(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1], 'title' => $messageData['title'])); if (!$setRes) { return; } $messageData['members'] = array_unique($messageData['members']); //根据 $originalMembers 和 $messageData['members'] 获取分别要添加和减少的成员 $addMembers = array_diff($messageData['members'], $originalMembers); $delMembers = array_diff($originalMembers, $messageData['members']); if (!is_array($addMembers) || !is_array($delMembers) || !is_array($originalMembers)) { return; } //删除用户 \Api\Model\Mgroup::setGroupMembers(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1], 'type' => 'del', 'userList' => $delMembers)); //把删除用户的该chatid的最近联系人删除 \Api\Model\Mgroup::remRecentMembers($messageData['chatid'], $delMembers); //添加用户 \Api\Model\Mgroup::setGroupMembers(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1], 'type' => 'add', 'userList' => $addMembers)); //要广播的信息 $broadMsg = array('type' => $messageData['type'], 'chatid' => $messageData['chatid'], 'fromuser' => $clientName, 'delMember' => $delMembers, 'addMember' => $addMembers); //获取所有存储的在线的用户 $clientLists = Muser::getOnlineUsers(); //获取该组原本用户在线的clientid,并广播 if ($originalMembers) { $onlineClientIds = self::getClientidsFromUsers($clientLists, $originalMembers); } if (isset($onlineClientIds) && $onlineClientIds) { Gateway::sendToAll(json_encode($broadMsg), $onlineClientIds); } return; case 'systemNotice': // 非法请求 if (!isset($_SESSION['clientName'])) { throw new \Exception("\$_SESSION['clientName'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}"); } $clientName = $_SESSION['clientName']; //群组info $chatInfo = explode('-', $messageData['chatid']); //master=$chatInfo[0],uuid=$chatInfo[1] //获取已有群成员信息 $originalMembers = \Api\Model\Mgroup::getGroupMembers(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1])); //如果本身不在群里则禁止操作 if (!in_array($clientName, $originalMembers)) { return; } //要广播的信息 $broadMsg = array('fromuser' => $clientName, 'type' => $messageData['type'], 'chatid' => $messageData['chatid'], 'action' => $messageData['action']); switch ($messageData['action']) { case "grouptitle": //修改群title $setRes = \Api\Model\Mgroup::setGroup(array('master' => $chatInfo[0], 'uuid' => $chatInfo[1], 'title' => $messageData['title'])); $broadMsg['title'] = $messageData['title']; if (!$setRes) { return; } break; case "opennotice": //打开群消息提醒 break; case "grouptitle": //屏蔽群消息提醒 break; } //获取所有存储的在线的用户 $clientLists = Muser::getOnlineUsers(); //获取该组原本用户在线的clientid,并广播 if ($originalMembers) { $onlineClientIds = self::getClientidsFromUsers($clientLists, $originalMembers); } if (isset($onlineClientIds) && $onlineClientIds) { Gateway::sendToAll(json_encode($broadMsg), $onlineClientIds); } return; } }