$_SESSION['user_id'], 'session_type' => $session_user['session_type'], 'session_user_id' => $session_user['id'], 'createtime' => time(), 'deletetime' => NULL, 'deleteuser' => '' ]; Db::name('fastchat_session')->insert($session); $session['id'] = Db::name('fastchat_session')->getLastInsID(); return $session; } /** * 获取一个用户的基本信息 * @param string user 待标识符的用户id * @return array */ public static function user_info($user) { $user = explode('||', $user); if (isset($user[1])) { if ($user[1] == 'user' || $user[1] == 'admin') { $user_info = Db::name($user[1])->where('id', $user[0])->find(); $user_info['source'] = $user[1]; $user_info['session_type'] = ($user[1] == 'user') ? 0 : 1; } elseif ($user[1] == 'tourists') { $user_info = Db::name('fastchat_tourists')->where('id', $user[0])->find(); $user_info['source'] = $user[1]; $user_info['session_type'] = 2; } elseif ($user[1] == 'service_user') { $user_info = Db::name('fastchat_service_user')->where('id', $user[0])->find(); $user_info['session_type'] = 5; } elseif ($user[1] == 'massager') { $user_info = Db::name("massager")->where("id", $user[0])->find(); $avatar = ''; if (isset($user_info["photo_images"]) && mb_strlen($user_info["photo_images"]) > 0) { $avatar = explode(",", $user_info["photo_images"])[0]; } $user_info["avatar"] = $avatar; $user_info["nickname"] = isset($user_info['name']) ? $user_info['name'] : "未知"; $user_info['session_type'] = 6; } if (!isset($user_info) || !isset($user_info['id'])) { $user_info['id'] = $user[0]; $user_info['source'] = 'unknown'; $user_info['nickname'] = '未知用户' . $user[0]; $user_info['avatar'] = false; $user_info['session_type'] = 4; } $user_info['avatar'] = self::img_src_fill($user_info['avatar']); } else { $user_info['id'] = $user[0]; $user_info['source'] = 'none'; $user_info['nickname'] = '未知' . $user[0]; $user_info['avatar'] = self::img_src_fill(false); $user_info['session_type'] = 3; } return $user_info; } /** * 获取图片的完整地址 * @param string src 待处理的图片 * @return string */ public static function img_src_fill($src) { $upload = \app\common\model\Config::upload(); \think\Hook::listen("upload_config_init", $upload); $view_cdn = config('view_replace_str.__CDN__'); $view_cdn = $view_cdn ? $view_cdn : cdnurl('', true); $domain = $upload['cdnurl'] ?? $view_cdn; return $src ? cdnurl($src, $domain) : $domain . '/assets/img/avatar.png'; } /** * 发送消息 * @param string user_id 带标识符的发送人 * @param string session_user_id 带标识符的接受人 * @param string message 消息内容 * @return array */ public static function send_message($user_id, $session_user_id, $message) { // 检查黑名单 $blacklist = Db::name('fastchat_blacklist') ->where('user_id', $session_user_id) ->where('session_user_id', $user_id) ->value('id'); if ($blacklist) { return ['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,对方已屏蔽您的发言!']; } // 检查是否有会话,没有则添加,有则直接发送消息 $user = self::user_info($user_id); $session_user = self::user_info($session_user_id); $session = Db::name('fastchat_session')->where(function ($query) use ($user_id, $session_user) { $query->where('user_id', $user_id) ->where('session_type', $session_user['session_type']) ->where('session_user_id', $session_user['id']); })->whereOr(function ($query) use ($session_user_id, $user) { $query->where('user_id', $session_user_id) ->where('session_type', $user['session_type']) ->where('session_user_id', $user['id']); }) ->find(); if (!$session) { $session = [ 'user_id' => $user_id, 'session_type' => $session_user['session_type'], 'session_user_id' => $session_user['id'], 'createtime' => time(), 'deletetime' => NULL, 'deleteuser' => '' ]; Db::name('fastchat_session')->insert($session); $session['id'] = Db::name('fastchat_session')->getLastInsID(); } $message_text = strip_tags($message, '
'); $message = [ 'session_id' => $session['id'], 'sender' => $user_id, 'message' => $message_text, 'createtime' => time() ]; if (Db::name('fastchat_record')->insert($message)) { $message['record_id'] = Db::name('fastchat_record')->getLastInsID();//消息记录ID // 确定会话状态 Db::name('fastchat_session')->where('id', $session['id'])->update(['deleteuser' => '', 'deletetime' => NULL, 'createtime' => time()]); if (Gateway::isUidOnline($session_user_id)) { // 加上发信人的信息 $message['avatar'] = $user['avatar']; $message['nickname'] = $user['nickname']; $message['session_user'] = $user_id; $message['online'] = 1; $message['id'] = $message['session_id'];// 兼容前台 unset($message['session_id']); $message['last_message'] = self::session_message($message_text); $message['last_time'] = self::format_time(NULL); $message['message'] = htmlspecialchars_decode($message['message']); // 查询当前用户发送的未读消息条数 $message['unread_msg_count'] = Db::name('fastchat_record') ->where('session_id', $message['id']) ->where('sender', $user_id) ->where('status', 0) ->count('id'); $message['sender'] = 'you'; Gateway::sendToUid($session_user_id, json_encode(['msgtype' => 'new_message', 'data' => $message])); } else { // 检查是否有绑定服务号 if ($session_user['session_type'] == 1) { $service_user = Db::name('fastchat_service_user') ->where('admin_id', $session_user['id']) ->where('status', '1') ->where('deletetime', NULL) ->find(); if ($service_user) { $msg = '对方正使用服务账号【' . $service_user['nickname'] . '】接收消息,您的消息可能无法被对方查看!'; return ['msgtype' => 'send_message', 'code' => 0, 'msg' => $msg]; } } } return ['msgtype' => 'send_message', 'code' => 1]; } else { return ['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,请重试!']; } } /** * 格式化消息-将图片和连接用文字代替 * @param string message 消息内容 * @return string */ public static function session_message($message) { $message = htmlspecialchars_decode($message); $message = preg_replace("//", '[图片]', $message); $message = preg_replace("//", '[链接]', $message); return $message; } /** * 格式化时间 * @param int time 时间戳 * @return string */ public static function format_time($time = NULL) { $text = ''; $now_time = time(); $time = ($time === NULL || $time > $now_time || $time == $now_time) ? $now_time + 1 : intval($time); $t = (int)($now_time - $time); //时间差 (秒) $y = date('Y', $time) - date('Y', $now_time);//是否跨年 switch ($t) { case $t <= 0: $text = '刚刚'; break; case $t < 60: $text = $t . '秒前'; // 一分钟内 break; case $t < 60 * 60: $text = floor($t / 60) . '分钟前'; //一小时内 break; case $t < 60 * 60 * 24: $text = floor($t / (60 * 60)) . '小时前'; // 一天内 break; case $t < 60 * 60 * 24 * 3: $text = floor($time / (60 * 60 * 24)) == 1 ? '昨天' . date('H:i', $time) : '前天' . date('H:i', $time); //昨天和前天 break; case $t < 60 * 60 * 24 * 30: $text = date('m-d H:i', $time); //一个月内 break; case $t < 60 * 60 * 24 * 365 && $y == 0: $text = date('m-d', $time); //一年内 break; default: $text = date('Y-m-d', $time); //一年以前 break; } return $text; } /** * 用户token加密 * @param string $token 待加密的token */ public static function getEncryptedToken($token) { $token_config = \think\Config::get('token'); $config = array( // 缓存前缀 'key' => $token_config['key'], // 加密方式 'hashalgo' => $token_config['hashalgo'] ); return hash_hmac($config['hashalgo'], $token, $config['key']); } /** * 检查用户身份 * @param string user_cookie 用户cookie * @param int user_id 用户ID直接登录 */ public static function check_fa_user($user_cookie = null, $user_id = 0) { if ($user_cookie && !$user_id) { $cookie_httponly = config('cookie.httponly'); if (!$cookie_httponly) { $user_id = Db::name('user_token')->where('token', Common::getEncryptedToken($user_cookie))->value('user_id'); } else { list($id, $key) = explode('|', $user_cookie); $user_token_list = Db::name('user_token') ->where('user_id', $id) ->where('expiretime', '>', time()) ->select(); foreach ($user_token_list as $user_token) { $sign = $user_token['token'] . 'fastchat_user_sign_additional'; $user_key = md5(md5($id) . md5($sign)); if ($user_key == $key) { $user_id = $id; break; } else { $user_id = false; } } } } if ($user_id) { $user_info = Db::name('user') ->field('password,salt,token', true) ->where('id', $user_id) ->find(); if ($user_info) { $user_info['user_id'] = $user_info['id'] . '||user'; return $user_info; } else { return false; } } else { return false; } } /** * 检查助教身份 * @param string $token * @param int user_id 用户ID直接登录 */ public static function check_massager($token = null) { if ($token) { $massager_info = Db::name('massager') ->where('session_token', $token) ->find(); if ($massager_info) { $massager_info['user_id'] = $massager_info['id'] . '||massager'; return $massager_info; } } return false; } /** * 检查管理员身份 * @param string keeplogin 管理员cookie信息 * @param int admin_id 管理员ID直接登录 * @return array */ public static function check_admin($keeplogin, $admin_id = 0) { if ($admin_id) { $admin = Db::name('admin')->field(['password', 'salt'], true)->where('id', $admin_id)->find(); if (!$admin) { return false; } } else { list($id, $keeptime, $expiretime, $key) = explode('|', $keeplogin); if ($id && $keeptime && $expiretime && $key && $expiretime > time()) { $admin = Db::name('admin')->where('id', $id)->find(); if (!$admin || !$admin['token']) { return false; } //token有变更 $sign = $id . 'fastchat_admin_sign_additional'; if ($key != md5(md5($sign) . md5($keeptime) . md5($expiretime) . $admin['token'])) { return false; } } else { return false; } } // 检查是否与服务号绑定 $service_user = Db::name('fastchat_service_user') ->where('admin_id', $admin['id']) ->where('status', '1') ->where('deletetime', NULL) ->find(); if ($service_user) { $service_user['username'] = $service_user['nickname']; $service_user['user_id'] = $service_user['id'] . '||service_user'; $service_user['token'] = $admin['token']; return $service_user; } $admin['user_id'] = $admin['id'] . '||admin'; $admin['admin_id'] = $admin['id'];// 和服务号字段统一 return $admin; } /** * 将游客的会话转到用户 * @param string tourists 游客的cookie信息 * @param string user_id 带标识符的用户id * @return bool */ public static function tourists_to_login($tourists, $user_id) { $user = self::user_info($user_id);//登录人信息 $tourists_info = self::check_tourists($tourists);//游客信息 if (!$tourists_info) { return; } // 查出游客的所有会话-》把 user_id 没有的会话转给 user_id $session_list = Db::name('fastchat_session') ->where(function ($query) use ($tourists_info) { $query->where('user_id', $tourists_info['user_id']); })->whereOr(function ($query) use ($tourists_info) { $query->where('session_user_id', $tourists_info['id'])->where('session_type', 2); }) ->order('createtime desc') ->select(); foreach ($session_list as $key => $value) { $session_user = Common::session_user($value, $tourists_info['user_id']);//本会话的会话对象 $session_user_info = Common::user_info($session_user);//会话对象信息 $session = Db::name('fastchat_session')->where(function ($query) use ($user_id, $session_user_info) { $query->where('user_id', $user_id) ->where('session_type', $session_user_info['session_type']) ->where('session_user_id', $session_user_info['id']); })->whereOr(function ($query) use ($session_user, $user) { $query->where('user_id', $session_user) ->where('session_type', $user['session_type']) ->where('session_user_id', $user['id']); }) ->find(); if (!$session) { // 将此会话转给用户 if ($value['user_id'] == $tourists_info['user_id']) { Db::name('fastchat_session') ->where('id', $value['id']) ->update(['user_id' => $user_id]); } else { Db::name('fastchat_session') ->where('id', $value['id']) ->update(['session_user_id' => $user['id'], 'session_type' => $user['session_type']]); } Db::name('fastchat_record') ->where('session_id', $value['id']) ->where('sender', $tourists_info['user_id']) ->update(['sender' => $user_id]); } } return true; } /** * 检查游客身份 * @param string tourists 游客的cookie信息 * @return array */ public static function check_tourists($tourists) { list($id, $keeptime, $expiretime, $key) = explode('|', $tourists); if ($id && $keeptime && $expiretime && $key && $expiretime > time()) { $tourists = Db::name('fastchat_tourists')->where('id', $id)->find(); if (!$tourists || !$tourists['token']) { return false; } //token有变更 if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $tourists['token'])) { return false; } } else { return false; } $tourists['user_id'] = $tourists['id'] . '||tourists'; $tourists['username'] = $tourists['nickname']; unset($tourists['token']); return $tourists; } /** * 获取用户的未读消息->获取他的会话->获取会话中的非他自己发送的未读消息 * @param string user_id 带标识符的用户id * @param bool is_latest 是否只获取用户未链接websocket时的消息 * @return string */ public static function get_unread_messages($user_id, $is_latest = false) { $new_msg = ''; $user = self::user_info($user_id); $session_list = Db::name('fastchat_session')->where(function ($query) use ($user_id) { $query->where('user_id', $user_id); })->whereOr(function ($query) use ($user) { $query->where('session_user_id', $user['id'])->where('session_type', $user['session_type']); }) ->order('createtime desc') ->select(); foreach ($session_list as $key => $value) { $session_user = self::session_user($value, $user_id); $where['session_id'] = $value['id']; $where['sender'] = $session_user; $where['status'] = 0; if ($is_latest) { $where['createtime'] = ['>', time() - 10]; } $new_msg = Db::name('fastchat_record') ->where($where) ->value('id'); if ($new_msg) { $session_user_info = self::user_info($session_user); $new_msg = $session_user_info['nickname'] . ' 发来一条新消息!'; break; } } return $new_msg; } /** * 获取会话的会话对象 * @param array session 会话信息 * @param string user_id 带标识符的当前用户id * @return string */ public static function session_user($session, $oneself = NULL) { if (!$oneself) { $oneself = $_SESSION['user_id']; } if ($oneself == $session['user_id']) { switch ($session['session_type']) { case '0': $session_user = $session['session_user_id'] . '||user'; break; case '1': $session_user = $session['session_user_id'] . '||admin'; break; case '2': $session_user = $session['session_user_id'] . '||tourists'; break; case '5': $session_user = $session['session_user_id'] . '||service_user'; break; case '6': $session_user = $session['session_user_id'] . '||massager'; break; default: $session_user = $session['session_user_id'] . '||none'; break; } } else { $session_user = $session['user_id']; } return $session_user; } /** * 处理前台搜索框的提示文字 * @param string search_type 配置信息 * @return string */ public static function search_tip_fill($search_type) { $search_tip = ''; if ($search_type && strstr($search_type, 'none') === false) { $search_type = explode(',', $search_type); foreach ($search_type as $key => $value) { switch ($value) { case "username": $search_tip .= '用户名/'; break; case "usermobile": $search_tip .= '手机号/'; break; case "userid": $search_tip .= '用户ID/'; break; case "nickname": $search_tip .= '用户昵称/'; break; default: $search_tip .= '未知/'; break; } } } if (!$search_tip) { $search_tip = '搜索其实很简单'; } else { $search_tip = '搜索' . trim($search_tip, '/') . '发起会话'; } return $search_tip; } /* * 检查/过滤变量 */ public static function check_variable(&$variable) { $variable = htmlspecialchars($variable); $variable = stripslashes($variable); // 删除反斜杠 $variable = addslashes($variable); // 转义特殊符号 $variable = trim($variable); // 去除字符两边的空格 } }