* @copyright walkor * @link http://www.workerman.net/ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ /** *可能存在的问题 * sendToClient 可能发送给不是当前房间的用户 */ /** * 聊天主逻辑 * 主要是处理 onMessage onClose */ use \GatewayWorker\Lib\Gateway; use \GatewayWorker\Lib\Store; use \GatewayWorker\Lib\Memcache; use \Application\AdminClient; use \Application\Crontab; class Events { /** * 有消息时 * @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数据 $message_data = json_decode($message, true); if(!$message_data) { return ; } if (empty($_SESSION) && strcmp($message_data['_method_'], 'login') !== 0) { return ; } //判断是否有登录。 if (strcmp($message_data['_method_'], 'login') !== 0) { if ($_SESSION['user_id'] == -1 && in_array($message_data['_method_'], array('SendPubMsg','SendPrvMsg','sendGift','Manage'))) { Gateway::sendToCurrentClient(json_encode(array('type'=>'sysmsg.alert','content'=>'请登录!'))); return ; } // 查看当前用户权限是否修改 $role = isset($_SESSION['role']) ? $_SESSION['role'] : null; $action = AdminClient::checkUserRoleChanged($_SESSION['user_id'], $_SESSION['room_id'], $role); if (!is_null($action)) { if (in_array($action, array('addSysAdminer','removeSysAdminer'))) { AdminClient::$action($_SESSION['room_id'], $_SESSION['user_id']); } else if (in_array($action, array('adminer','removeAdminer'))) { AdminClient::$action($_SESSION['room_id'], $_SESSION['user_id'], $client_id, $_SESSION['client_name'], true, false); } } } // 根据类型执行不同的业务 switch($message_data['_method_']) { // 客户端回应服务端的心跳,代表在线。 case 'pong': if (isset($_SESSION['room_id']) && isset($_SESSION['role']) && strcmp($_SESSION['role'], 'owner') === 0) { //isset($message_data['device']) && strcmp($message_data['device'], 'android') Crontab::setAnchorOnline($_SESSION['room_id'], $_SESSION['user_id']); } return; // 客户端登录 message格式: {_method_ :login, name:xx, room_id:1} ,添加到客户端,广播给所有客户端xx进入聊天室 case 'logout': // 从房间的客户端列表中删除 if(isset($_SESSION['room_id'])) { $room_id = $_SESSION['room_id']; $new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'user_id'=>$_SESSION['user_id'], 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s')); if (isset($_SESSION['role']) && strcmp($_SESSION['role'], 'owner') === 0) { $new_message['role'] = 'owner'; } Gateway::unbindUid($client_id, $_SESSION['user_id']); //解除与uid的绑定。 Gateway::leaveGroup($client_id, $room_id); //离开当前的用户住,代表当前房间 Gateway::sendToGroup($room_id, json_encode($new_message)); //客户端断开连接需要执行此操作。 $_SESSION = array(); } return ; case 'login': // 判断是否有房间号 if(!isset($message_data['room_id'])) { return; } $viewer = false; if (!isset($message_data['user_name']) || !isset($message_data['user_id']) || $message_data['user_id'] <= 0 || $message_data['user_name'] == "") { $viewer = true; $message_data['user_name'] = '游客'.rand(10000,99999); $message_data['user_id'] = -1; $message_data['levelid'] = 0; $message_data['ucuid'] = -1; $message_data['vip'] = 0; } $client_name = htmlspecialchars($message_data['user_name']); $room_id = $message_data['room_id']; $user_id = $message_data['user_id']; if (!$viewer) { if (!AdminClient::isLogged($user_id, $message_data['token'])) { // close this connection Gateway::sendToCurrentClient(json_encode(array('type'=>'error' , 'content'=>'请先登录'))); Gateway::closeClient($client_id); return; } } $vip = $viewer ? 0 : AdminClient::hasVipPrivilete($user_id); if ( $vip == 0 && AdminClient::isRoomFull($room_id)) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error.kicked','content'=>"非VIP用户不能进入满员房间~"))); // 延迟关闭连接 AdminClient::delayCloseClient(5,$client_id); // Gateway::closeClient($client_id); return; } $expire = 0; $role = $viewer ? '' : AdminClient::getClientRole($room_id, $user_id, $expire); if (!$vip &&strcmp($role, 'kicked') === 0 && $expire > time()) { //TODO 关闭连接 已被踢出房间 $left = floor(($expire - time()) / 60); Gateway::sendToCurrentClient(json_encode(array('type'=>'error.kicked','content'=>"您已被踢出房间, {$left}分钟后再进入房间"))); // 延迟关闭连接 AdminClient::delayCloseClient(5,$client_id); // Gateway::closeClient($client_id); return; } // 把房间号昵称放到session中 $isAdminer = false; if (!is_null($role) && (strcmp($role, 'adminer') === 0 || strcmp($role, 'owner') === 0) || strcmp($role, 'sysAdminer') === 0) { $_SESSION['role'] = $role; if (strcmp($role, 'owner') === 0) { AdminClient::setAnchorOnlie($user_id); } $isAdminer = true; } else if (!$vip && !is_null($role) && strcmp($role, 'disableMsg') === 0) { $_SESSION['disableMsg'] = 1; $_SESSION['expire'] = $expire; } $ucuid = $message_data['ucuid']; $_SESSION['client_name'] = $client_name; $_SESSION['user_id'] = $user_id; $_SESSION['room_id'] = $room_id; $_SESSION['ucuid'] = $ucuid; $_SESSION['client_id'] = $client_id; $_SESSION['vip'] = $vip; $_SESSION['levelid'] = $message_data['levelid']; $_SESSION['time'] = 0; $_SESSION['msged'] = false; $new_message = array('type'=>$message_data['_method_'], 'client_id'=>$client_id, 'client_name'=>htmlspecialchars($client_name), 'user_id'=>$user_id, 'ucuid'=>$ucuid,'vip'=>$vip,'levelid'=>$_SESSION['levelid'], 'time'=>date('H:i')); $new_message['levelid'] = $message_data['levelid']; if ($isAdminer) { $new_message['role'] = 'adminer'; } if (isset($message_data['daoju'])) { $new_message['daoju'] = $message_data['daoju']; } // if ((strcmp($role, 'owner') !== 0)) { // Gateway::sendToGroup($room_id, json_encode($new_message)); // } Gateway::joinGroup($client_id, $room_id); Gateway::bindUid($client_id, $user_id); AdminClient::sendSysMsg($client_id, !isset($message_data['lang']) ? 'ch' : $message_data['lang']); print_r($_SESSION); // For APP Crontab::sendOnLineList($room_id, $_SESSION); print_r($new_message) ; // For PC Gateway::sendToCurrentClient(json_encode($new_message)); // Gateway::sendToGroup($room_id, json_encode($new_message)); return; // 客户端发言 message: {_method_:SendPubMsg, to_client_id:xx, content:xx} case 'LightHeart': if(!isset($_SESSION['room_id'])) { return; } $new_message = array( 'type'=>'LightHeart', 'color'=> isset($message_data['color']) ? $message_data['color'] : 'red', 'client_id'=>$client_id, 'user_id'=>$_SESSION['user_id'], 'client_name'=>$_SESSION['client_name'], 'levelid'=>$_SESSION['levelid'], 'vip'=>$_SESSION['vip'], 'time'=>date('H:i'), ); return Gateway::sendToGroup($_SESSION['room_id'], json_encode($new_message)); case 'SendPubMsg': // 非法请求 if(!isset($_SESSION['room_id'])) { return; } if (trim($message_data['content']) == "") { Gateway::sendToClient($client_id, json_encode(array("type"=>"error","content"=>"您不能发送空内容"))); return ; } // 是否可以发言 if (!AdminClient::isEnableMsg()) { Gateway::sendToCurrentClient(json_encode(array("type"=>"error","content"=>"您已被管理员禁言"))); return ; } $msg = ''; if (!AdminClient::msgFrequency(strlen($message_data['content']), $msg)) { Gateway::sendToCurrentClient(json_encode(array("type"=>"error","content"=>$msg))); return ; } $room_id = $_SESSION['room_id']; $client_name = $_SESSION['client_name']; $new_message = array( 'type'=>'SendPubMsg', 'from_user_id'=>$_SESSION['user_id'], 'from_client_name' =>$client_name, 'vip'=>$_SESSION['vip'], 'levelid'=>$_SESSION['levelid'], 'avatar'=>AdminClient::getAvatar($_SESSION['user_id']), // 'to_client_id'=>'all', 'content'=>nl2br(htmlspecialchars(AdminClient::filter($message_data['content']))), 'time'=>date('H:i'), ); // 飞屏特效 $new_message['fly'] = isset($message_data['fly']) ? $message_data['fly'] : ''; return Gateway::sendToGroup($room_id ,json_encode($new_message)); case 'SendPrvMsg': // 非法请求 if(!isset($_SESSION['room_id'])) { return; } if (trim($message_data['content']) == "") { Gateway::sendToClient($client_id, json_encode(array("type"=>"error","content"=>"您不能发送空内容"))); return ; } // 是否可以发言 if (!AdminClient::isEnableMsg()) { Gateway::sendToClient($client_id, json_encode(array("type"=>"error","content"=>"您已被管理员禁言"))); return ; } if (!AdminClient::ablePriMsg()){ Gateway::sendToClient($client_id, json_encode(array("type"=>"error","content"=>"富豪等级3以下不能发私信,快快升级吧"))); return ; } $msg = ''; if (!AdminClient::msgFrequency(strlen($message_data['content']), $msg)) { Gateway::sendToCurrentClient(json_encode(array("type"=>"error","content"=>$msg))); return ; } $room_id = $_SESSION['room_id']; $client_name = $_SESSION['client_name']; // 私聊 $new_message = array( 'type'=>'SendPrvMsg', 'from_user_id'=>$_SESSION['user_id'], 'from_client_name' =>$client_name, 'vip'=>$_SESSION['vip'], 'levelid'=>$_SESSION['levelid'], 'avatar'=> AdminClient::getAvatar($_SESSION['user_id']), 'to_client_name'=>$message_data['to_client_name'], 'to_user_id'=>isset($message_data['to_user_id']) ? $message_data['to_user_id'] : 0, 'pub'=>$message_data['pub'], 'content'=>nl2br(htmlspecialchars(AdminClient::filter($message_data['content']))), 'time'=>date('H:i'), ); // 飞屏特效 // $new_message['fly'] = isset($message_data['fly']) ? $message_data['fly'] : ''; //可公开的私聊 if ($message_data['pub']) { return Gateway::sendToGroup($room_id ,json_encode($new_message)); } else { //私密聊天,不公开 Gateway::sendToClient($message_data['to_client_id'], json_encode($new_message)); // $new_message['content'] = nl2br(htmlspecialchars($message_data['content'])); return Gateway::sendToCurrentClient(json_encode($new_message)); } case 'vodSong': if (!isset($message_data['songName'])) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'请填写歌曲!'))); return ; } if ($_SESSION['user_id'] == -1) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'游客不能点歌!'))); return ; } $new_message = array('type'=>'vodSong'); return Gateway::sendToGroup($_SESSION['room_id'] ,json_encode($new_message)); case 'setBackground': case 'cancelBackground': $error = ""; $new_message = array(); if (!isset($_SESSION['role']) || !in_array($_SESSION['role'],array('owner','sysAdminer'))) { $error = "您不是房主或系统管理员"; } if ( strcmp($message_data['_method_'],'setBackground') == 0 && (!isset($message_data['bgimg']) || $message_data['bgimg'] == "")) { $error = "参数错误,请稍后尝试..."; } if ($error != "") { return Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>$error))); } return Gateway::sendToGroup($_SESSION['room_id'], json_encode(array('type'=>$message_data['_method_'],'bgimg'=>$message_data['bgimg']))); case 'setSongApply': if (!isset($_SESSION['role']) || strcmp($_SESSION['role'],'owner') != 0) { return Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'您不是房主哦!'))); } if (!isset($message_data['apply'])) { return Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'参数错误'))); } return Gateway::sendToGroup($_SESSION['room_id'],json_encode(array('type'=>'setSongApply','apply'=>$message_data['apply']))); case 'disAgreeSong': case 'agreeSong': if (!isset($_SESSION['role']) || strcmp($_SESSION['role'], 'owner') !== 0) { // 当前用户不在该房间 Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'您不是房主哦!'))); return ; } $new_message = array('type'=>$message_data['_method_']); if ($message_data['_method_'] == 'agreeSong') { $new_message['client_name'] = $message_data['userName']; $new_message['songName'] = $message_data['songName']; } return Gateway::sendToGroup($_SESSION['room_id'],json_encode($new_message)); case 'sendGift': // 此接口已废弃 // Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'此接口已废弃'))); // return ; // 非法请求 if(!isset($_SESSION['room_id'])) { return; } $room_id = $_SESSION['room_id']; $client_name = $_SESSION['client_name']; // 防止别人冒名发消息 if (strcmp($client_name, $message_data['userName']) !== 0) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'不能冒名发送礼物'))); return ; } unset($message_data['_method_']); unset($message_data['userName']); $message_data['from_client_name'] = $client_name; $message_data['type'] = 'sendGift'; $message_data['code'] = 0; $message_data['time'] = date('H:i'); $new_message = $message_data; $new_message['from_client_id'] = $client_id; $new_message['from_user_id'] = $_SESSION['user_id']; $new_message['vip'] = $_SESSION['vip']; $new_message['levelid'] = $_SESSION['levelid']; return Gateway::sendToGroup($room_id ,json_encode($new_message)); case 'Manage': // 非法请求 if(!isset($_SESSION['room_id'])) { return; } // 是否有管理员权限 if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], array('adminer','owner','sysAdminer'))) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'您没有管理员权限'))); return; } $room_id = $_SESSION['room_id']; $client_name = $_SESSION['client_name']; $managed_user_id = $message_data['managed_user_id']; // $managed_client_id = $message_data['managed_client_id']; // $uidToClientArray = Gateway::getClientIdByUid($managed_user_id); // $managed_client_id = array_shift($uidToClientArray); $managed_client_id_array = Gateway::getClientIdByUid($managed_user_id); $managed_user_name = $message_data['managed_user_name']; $type = $message_data['_type_']; if ( $managed_user_id == -1 && in_array($type, array('adminer','removeAdminer'))) { Gateway::sendToCurrentClient(json_encode(array('type'=>'sysmsg.alert','content'=>'无法对游客做此操作!'))); return ; } // if (!Gateway::isUidOnline($managed_user_id)) { // // 当前用户不在该房间 // Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'当前用户不在该房间'))); // return ; // } if (in_array($type, array('adminer','removeAdminer','addKicked','removeKicked','disableMsg','enableMsg'))) { if ( $managed_user_id == -1 && in_array($type, array(array('adminer','removeAdminer')))) { Gateway::sendToCurrentClient(json_encode(array('type'=>'sysmsg.alert','content'=>'无法对游客做此操作!'))); return ; } // 查看VIP状态 if (in_array($type, array('addKicked','disableMsg')) && AdminClient::hasVipPrivilete($managed_user_id)) { Gateway::sendToCurrentClient(json_encode(array('type'=>'sysmsg.alert','content'=>'该用户为 VIP 会员,操作失败!'))); return ; } if (!AdminClient::ableToManage($managed_user_id, $room_id)) { Gateway::sendToCurrentClient(json_encode(array('type'=>'error','content'=>'无法操作管理员'))); return; } Gateway::sendToCurrentClient(json_encode(array('type'=>'sysmsg.alert','content'=>'操作成功!'))); AdminClient::$type($room_id, $managed_user_id, $managed_client_id_array, $managed_user_name); } } } /** * 当客户端断开连接时 * @param integer $client_id 客户端id */ public static function onClose($client_id) { // debug // echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n"; // 从房间的客户端列表中删除 if(isset($_SESSION['room_id'])) { /* if (isset($_SESSION['role']) && strcmp($_SESSION['role'], 'owner') === 0) { Crontab::delAnchorOnline($_SESSION['room_id']); AdminClient::setAnchorOffLine($_SESSION['user_id']); } */ $room_id = $_SESSION['room_id']; $new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'user_id'=>$_SESSION['user_id'], 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s')); Gateway::sendToGroup($room_id, json_encode($new_message)); } } }