$_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); // 去除字符两边的空格
}
}