Message.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. <?php
  2. use addons\fastchat\library\Common;
  3. use GatewayWorker\Lib\Gateway;
  4. use think\Db;
  5. /**
  6. *
  7. */
  8. class Message
  9. {
  10. function __construct()
  11. {
  12. }
  13. /*清退链接*/
  14. public function clear($client_id)
  15. {
  16. Gateway::closeClient($client_id);
  17. }
  18. public function ping()
  19. {
  20. // 用户端心跳
  21. }
  22. /*直接标记消息已读*/
  23. public function read_message($client_id, $data)
  24. {
  25. Db::name('fastchat_record')->where('id', $data['record_id'])->update(['status' => 1]);
  26. }
  27. /*推送消息*/
  28. public function push_message($client_id, $data)
  29. {
  30. if (!isset($data['token']) || !isset($data['service_user'])) {
  31. Gateway::closeClient($client_id);
  32. }
  33. // 验证 token
  34. $token = Common::getEncryptedToken($data['token']);
  35. $service_user = Db::name('fastchat_service_user')
  36. ->where('id', $data['service_user'])
  37. ->where('status', '1')
  38. ->where('deletetime', NULL)
  39. ->find();
  40. if (!$service_user || $service_user['token'] != $token) {
  41. Gateway::closeClient($client_id);
  42. }
  43. $service_user_id = $service_user['id'] . '||service_user';
  44. // 发送消息给用户
  45. if (isset($data['user'])) {
  46. $user = explode(',', $data['user']);
  47. foreach ($user as $key => $value) {
  48. $session_user = $value . '||user';
  49. Common::send_message($service_user_id, $session_user, $data['content']);
  50. }
  51. }
  52. // 发送消息给助教
  53. if (isset($data["massager"])) {
  54. $massager = explode(',', $data['massager']);
  55. foreach ($massager as $key => $value) {
  56. $session_user = $value . '||massager';
  57. Common::send_message($service_user_id, $session_user, $data['content']);
  58. }
  59. }
  60. // 发送消息给管理员
  61. if (isset($data['admin'])) {
  62. $user = explode(',', $data['admin']);
  63. foreach ($user as $key => $value) {
  64. $session_user = $value . '||admin';
  65. Common::send_message($service_user_id, $session_user, $data['content']);
  66. }
  67. }
  68. // 发送消息给用户组
  69. if (isset($data['user_group']) && $data['user_group']) {
  70. // 查得这个组中的所有用户
  71. $user = Db::name('user')->field('id')->whereIn('group_id', $data['user_group'])->select();
  72. foreach ($user as $key => $value) {
  73. $session_user = $value['id'] . '||user';
  74. Common::send_message($service_user_id, $session_user, $data['content']);
  75. }
  76. }
  77. // 发送消息给管理员组
  78. if (isset($data['admin_group']) && $data['admin_group']) {
  79. // 查得这个组中的所有管理员
  80. $user = Db::name('auth_group_access')->field('uid')->distinct(true)->where('group_id', $data['admin_group'])->select();
  81. foreach ($user as $key => $value) {
  82. $session_user = $value['uid'] . '||admin';
  83. Common::send_message($service_user_id, $session_user, $data['content']);
  84. }
  85. }
  86. }
  87. public function del_session($client_id, $data)
  88. {
  89. $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();
  90. if (!$session_info) {
  91. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'del_session', 'code' => 0, 'msg' => '会话找不到啦!']));
  92. }
  93. if ($session_info['deleteuser'] && $session_info['deleteuser'] != $_SESSION['user_id']) {
  94. Db::name('fastchat_session')->where('id', $data['session_id'])->update(['deletetime' => time()]);
  95. } else {
  96. Db::name('fastchat_session')->where('id', $data['session_id'])->update(['deleteuser' => $_SESSION['user_id']]);
  97. }
  98. }
  99. public function send_message($client_id, $data)
  100. {
  101. if (!isset($data['session_id'])) {
  102. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,会话找不到啦!']));
  103. }
  104. $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();
  105. if (!$session_info) {
  106. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,会话找不到啦!']));
  107. }
  108. // 确定收信人
  109. $session_user = Common::session_user($session_info);
  110. $res = Common::send_message($_SESSION['user_id'], $session_user, $data['message']);
  111. Gateway::sendToClient($client_id, json_encode($res));
  112. }
  113. /*聊天记录*/
  114. public function chat_record($client_id, $data)
  115. {
  116. $page_count = 20;//一次加载20条
  117. if (!isset($data['session_id'])) {
  118. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'chat_record', 'code' => 1, 'data' =>
  119. [
  120. 'chat_record' => [],
  121. 'session_info' => [
  122. 'nickname' => '无会话'
  123. ],
  124. 'next_page' => 'done',
  125. 'page' => $data['page']
  126. ]
  127. ]));
  128. return '';
  129. }
  130. if (!isset($data['page'])) {
  131. $data['page'] = 1;
  132. }
  133. $chat_record_count = Db::name('fastchat_record')
  134. ->where('session_id', $data['session_id'])
  135. ->where('is_del', 0)
  136. ->count('id');
  137. $page_number = ceil($chat_record_count / $page_count);
  138. if ($data['page'] == 1) {
  139. $min = 0;
  140. } else {
  141. $min = ($data['page'] - 1) * $page_count;
  142. }
  143. // 会话信息
  144. $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();
  145. if (!$session_info) {
  146. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'chat_record', 'code' => 0, 'msg' => '会话找不到啦!']));
  147. }
  148. // 标记此会话所有不是当前用户发的消息为已读->SQL不使用不等于->查得会话对象的ID
  149. $session_user = Common::session_user($session_info);
  150. Db::name('fastchat_record')->where('sender', $session_user)->where('status', 0)->update(['status' => 1]);
  151. $session_user_info = Common::user_info($session_user);
  152. // 是否屏蔽此人
  153. $session_user_info['blacklist'] = Db::name('fastchat_blacklist')
  154. ->where('user_id', $_SESSION['user_id'])
  155. ->where('session_user_id', $session_user)
  156. ->value('id');
  157. $chat_record = Db::name('fastchat_record')
  158. ->where('session_id', $data['session_id'])
  159. ->where('is_del', 0)
  160. ->limit($min, $page_count)
  161. ->order('createtime desc')
  162. ->select();
  163. if ($data['page'] == 1) {
  164. $chat_record = array_reverse($chat_record, false);
  165. }
  166. // 消息按时间分组
  167. if ($chat_record) {
  168. $record_temp = [];
  169. $createtime = $chat_record[0]['createtime'];
  170. foreach ($chat_record as $key => $value) {
  171. $value['sender'] = ($value['sender'] == $_SESSION['user_id']) ? 'me' : 'you';
  172. $value['message'] = htmlspecialchars_decode($value['message']);
  173. if (($value['createtime'] - $createtime) < 3600) {
  174. $record_temp[$createtime][] = $value;
  175. } else {
  176. $createtime = $value['createtime'];
  177. $record_temp[$createtime][] = $value;
  178. }
  179. }
  180. unset($chat_record);
  181. foreach ($record_temp as $key => $value) {
  182. $chat_record[] = [
  183. 'datetime' => Common::format_time($key),
  184. 'data' => $value
  185. ];
  186. }
  187. unset($record_temp);
  188. } else {
  189. $chat_record[] = [
  190. 'datetime' => '还没有消息',
  191. 'data' => []
  192. ];
  193. }
  194. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'chat_record', 'code' => 1, 'data' =>
  195. [
  196. 'chat_record' => $chat_record,
  197. 'session_info' => $session_user_info,
  198. 'next_page' => ($data['page'] >= $page_number) ? 'done' : $data['page'] + 1,
  199. 'page' => $data['page']
  200. ]
  201. ]));
  202. }
  203. /*获取会话列表*/
  204. public function session_list($client_id, $data)
  205. {
  206. $user = Common::user_info($_SESSION['user_id']);
  207. $session_list = Db::name('fastchat_session')
  208. ->where(function ($query) {
  209. $query->where('user_id', $_SESSION['user_id'])->where('deletetime', null);
  210. })->whereOr(function ($query) use ($user) {
  211. $query->where('session_user_id', $user['id'])->where('session_type', $user['session_type'])->where('deletetime', null);
  212. })
  213. ->order('createtime desc')
  214. ->select();
  215. if (!$session_list) {
  216. // 添加需要自动添加的会话
  217. $auto_add_session = Db::name('fastchat_service_user')
  218. ->field('CONCAT(id,"||service_user") as id,CONCAT(admin_id,"||admin") as admin_id,welcome_news,add_sessiondata')
  219. ->where("add_sessiondata='0' OR add_sessiondata='1'")
  220. ->where('status', '1')
  221. ->where('deletetime', NULL)
  222. ->select();
  223. foreach ($auto_add_session as $key => $value) {
  224. if (($value['add_sessiondata'] == 0 && Gateway::isUidOnline($value['id'])) || $value['add_sessiondata'] == 1) {
  225. $session = $session_list[] = Common::add_session($value['id']);
  226. // 发送欢迎消息
  227. if ($value['welcome_news']) {
  228. $message = [
  229. 'session_id' => $session['id'],
  230. 'sender' => $value['id'],
  231. 'message' => $value['welcome_news'],
  232. 'createtime' => time()
  233. ];
  234. Db::name('fastchat_record')->insert($message);
  235. }
  236. }
  237. }
  238. }
  239. $session_list = array_reverse($session_list, false);
  240. foreach ($session_list as $key => $value) {
  241. if ($value['deleteuser'] == $_SESSION['user_id']) {
  242. unset($session_list[$key]);
  243. continue;
  244. }
  245. $session_list[$key]['last_time'] = Common::format_time($value['createtime']);
  246. // 最后一条聊天记录
  247. $last_message = Db::name('fastchat_record')
  248. ->where('session_id', $value['id'])
  249. ->order('createtime desc')
  250. ->find();
  251. $session_list[$key]['session_user'] = $session_user = Common::session_user($value);
  252. $session_user_info = Common::user_info($session_user);
  253. $session_list[$key]['avatar'] = $session_user_info['avatar'];
  254. $session_list[$key]['nickname'] = $session_user_info['nickname'];
  255. if ($last_message) {
  256. $session_list[$key]['last_message'] = Common::session_message($last_message['message']);
  257. $last_message['message'] = htmlspecialchars_decode($last_message['message']);
  258. $session_list[$key]['last_time'] = Common::format_time($last_message['createtime']);
  259. } else if (isset($session_user_info['bio'])) {
  260. $session_list[$key]['last_message'] = $session_user_info['bio'];
  261. } else {
  262. $session_list[$key]['last_message'] = '';
  263. }
  264. // 未读消息条数->查询不是当前用户发送的消息
  265. $session_list[$key]['unread_msg_count'] = Db::name('fastchat_record')
  266. ->where('session_id', $value['id'])
  267. ->where('sender', $session_user)
  268. ->where('status', 0)
  269. ->count('id');
  270. // 会话对象是否在线
  271. if ($session_user_info['session_type'] == 5 && $session_user_info['online_status'] == 0) {
  272. $session_list[$key]['online'] = 1;
  273. } else {
  274. $session_list[$key]['online'] = Gateway::isUidOnline($session_user);
  275. }
  276. }
  277. $session_list = array_values($session_list);
  278. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'message_list', 'data' => $session_list]));
  279. }
  280. /*搜索用户*/
  281. public function search_user($client_id, $keywords)
  282. {
  283. $config_data = get_addon_config('fastchat');
  284. $where = array();
  285. $session_type = explode(',', $config_data['session_type']);
  286. foreach ($session_type as $key => $value) {
  287. switch ($value) {
  288. case "username":
  289. $where['username'] = ['like', '%' . $keywords . '%'];
  290. break;
  291. case "usermobile":
  292. $where['mobile'] = $keywords;
  293. break;
  294. case "userid":
  295. $where['id'] = $keywords;
  296. break;
  297. case "nickname":
  298. $where['nickname'] = ['like', '%' . $keywords . '%'];
  299. break;
  300. }
  301. }
  302. // 每种身份最多搜索出 8 位预选人,可随意调整
  303. $user_list = Db::name('user')->field('CONCAT(id,"||user") as id,nickname,avatar')->whereOr($where)->limit(8)->select();
  304. unset($where['mobile']);
  305. if ($config_data['user_to_admin'] == 1) {
  306. $admin_list = Db::name('admin')->field('CONCAT(id,"||admin") as id,nickname,avatar')->whereOr($where)->limit(8)->select();
  307. } else {
  308. $admin_list = array();
  309. }
  310. if (isset($where['username'])) {
  311. $where['nickname'] = $where['username'];
  312. unset($where['username']);
  313. }
  314. $service_users = Db::name('fastchat_service_user')
  315. ->field('CONCAT(id,"||service_user") as id,nickname,avatar')
  316. ->whereOr($where)
  317. ->limit(8)
  318. ->select();
  319. $user_list = array_merge($user_list, $admin_list, $service_users);
  320. foreach ($user_list as $key => $value) {
  321. $user_list[$key]['avatar'] = $value['avatar'] ? cdnurl($value['avatar'], $_SESSION['origin']) : $_SESSION['origin'] . '/assets/img/avatar.png';
  322. // 去掉用户自己
  323. if ($value['id'] == $_SESSION['user_id']) {
  324. unset($user_list[$key]);
  325. }
  326. }
  327. $user_list = array_values($user_list);
  328. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'search_user', 'data' => $user_list]));
  329. }
  330. /*屏蔽会话*/
  331. public function shielding_session($client_id, $data)
  332. {
  333. if (!isset($data['session_id']) || $data['session_id'] <= 0) {
  334. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '会话找不到啦!']));
  335. return;
  336. }
  337. $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();
  338. if (!$session_info) {
  339. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '会话找不到啦!']));
  340. }
  341. // 获取会话人
  342. $session_user_id = Common::session_user($session_info);
  343. $blacklist_id = Db::name('fastchat_blacklist')
  344. ->where('user_id', $_SESSION['user_id'])
  345. ->where('session_user_id', $session_user_id)
  346. ->value('id');
  347. if ($blacklist_id) {
  348. if (Db::name('fastchat_blacklist')->where('id', $blacklist_id)->delete()) {
  349. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 2, 'session_id' => $data['session_id']]));
  350. } else {
  351. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '操作失败,请重试!']));
  352. }
  353. return;
  354. }
  355. $blacklist = [
  356. 'user_id' => $_SESSION['user_id'],
  357. 'session_user_id' => $session_user_id,
  358. 'createtime' => time()
  359. ];
  360. if (Db::name('fastchat_blacklist')->insert($blacklist)) {
  361. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 1, 'session_id' => $data['session_id']]));
  362. } else {
  363. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '操作失败,请重试!']));
  364. }
  365. }
  366. /*添加会话*/
  367. public function add_session($client_id, $data)
  368. {
  369. $config_data = get_addon_config('fastchat');
  370. if (!isset($data['user_id']) || $data['user_id'] <= 0) {
  371. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '用户找不到啦!']));
  372. return;
  373. }
  374. $session_user = Common::user_info($data['user_id']);
  375. $user_info = Common::user_info($_SESSION['user_id']);
  376. if ($user_info['session_type'] == 2 || $user_info['session_type'] == 3 || $user_info['session_type'] == 4) {
  377. if (!$config_data['anonymous_to_admin'] && $session_user['session_type'] == 1) {
  378. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '禁止匿名向管理员发起会话!']));
  379. return;
  380. }
  381. if (!$config_data['anonymous_to_user'] && $session_user['session_type'] == 0) {
  382. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '禁止匿名向用户发起会话!']));
  383. return;
  384. }
  385. }
  386. // 插入会话表
  387. $existing_session = false;
  388. $session = Db::name('fastchat_session')->where(function ($query) use ($session_user) {
  389. $query->where('user_id', $_SESSION['user_id'])
  390. ->where('session_type', $session_user['session_type'])
  391. ->where('session_user_id', $session_user['id']);
  392. })->whereOr(function ($query) use ($data, $user_info) {
  393. $query->where('user_id', $data['user_id'])
  394. ->where('session_type', $user_info['session_type'])
  395. ->where('session_user_id', $user_info['id']);
  396. })
  397. ->find();
  398. if (!$session) {
  399. $session = [
  400. 'user_id' => $_SESSION['user_id'],
  401. 'session_type' => $session_user['session_type'],
  402. 'session_user_id' => $session_user['id'],
  403. 'createtime' => time()
  404. ];
  405. Db::name('fastchat_session')->insert($session);
  406. $session['id'] = Db::name('fastchat_session')->getLastInsID();
  407. } else {
  408. // 会话列表已存在此会话,修改会话的时间
  409. $existing_session = true;
  410. if ($session['deletetime']) {
  411. // deleteuser 改为对方
  412. $session_user_id = Common::session_user($session);
  413. Db::name('fastchat_session')->where('id', $session['id'])->update(['deleteuser' => $session_user_id, 'deletetime' => NULL, 'createtime' => time()]);
  414. } else if ($session['deleteuser'] == $_SESSION['user_id']) {
  415. Db::name('fastchat_session')->where('id', $session['id'])->update(['deleteuser' => '', 'deletetime' => NULL, 'createtime' => time()]);
  416. } else {
  417. Db::name('fastchat_session')->where('id', $session['id'])->update(['createtime' => time()]);
  418. }
  419. }
  420. // 用户与客服聊天
  421. if (strstr($_SESSION["user_id"], "service_user") || $session["session_type"] == 5) {
  422. $record = Db::name("fastchat_record")->where([
  423. "session_id" => $session["id"],
  424. "message" => "您稍等,客服正在接通中..."
  425. ]);
  426. if (!$record) {
  427. Db::name("fastchat_record")->insert([
  428. "session_id" => $session["id"],
  429. "sender" => strstr($_SESSION["user_id"], "service_user") ? $_SESSION["user_id"] : "{$session["session_user_id"]}||service_user",
  430. "message" => "您稍等,客服正在接通中...",
  431. "status" => 0,
  432. "is_del" => 0,
  433. "createtime" => time()
  434. ]);
  435. }
  436. }
  437. // 用户与助教聊天
  438. if (strstr($_SESSION["user_id"], "massager") || $session["session_type"] == 6) {
  439. $record = Db::name("fastchat_record")->where([
  440. "session_id" => $session["id"],
  441. "message" => "客户,您好!"
  442. ]);
  443. if (!$record) {
  444. Db::name("fastchat_record")->insert([
  445. "session_id" => $session["id"],
  446. "sender" => strstr($_SESSION["user_id"], "massager") ? $_SESSION["user_id"] : "{$session["session_user_id"]}||massager",
  447. "message" => "客户,您好!",
  448. "status" => 0,
  449. "is_del" => 0,
  450. "createtime" => time()
  451. ]);
  452. }
  453. }
  454. // 读取最后一条聊天记录
  455. $last_message = Db::name('fastchat_record')
  456. ->where('session_id', $session['id'])
  457. ->order('createtime desc')
  458. ->find();
  459. if ($last_message) {
  460. $last_message_text = $last_message['message'];
  461. } else if (isset($session_user['bio'])) {
  462. $last_message_text = $session_user['bio'];
  463. } else {
  464. $last_message_text = '';
  465. }
  466. $blacklist_id = Db::name('fastchat_blacklist')
  467. ->where('user_id', $_SESSION['user_id'])
  468. ->where('session_user_id', $data['user_id'])
  469. ->value('id');
  470. $resdata = [
  471. 'id' => $session['id'],
  472. 'avatar' => $session_user['avatar'],
  473. 'nickname' => isset($session_user['nickname']) ? $session_user['nickname'] : (isset($session_user["name"]) ? $session_user["name"] : "未知"),
  474. 'last_message' => Common::session_message($last_message_text),
  475. 'existing_session' => $existing_session,
  476. 'blacklist' => $blacklist_id
  477. ];
  478. // 会话对象是否在线
  479. if ($session_user['session_type'] == 5 && $session_user['online_status'] == 0) {
  480. $resdata['online'] = 1;
  481. } else {
  482. if (!isset($session_user_id)) {
  483. $session_user_id = Common::session_user($session);
  484. }
  485. $resdata['session_user'] = $session_user_id;
  486. $resdata['online'] = Gateway::isUidOnline($session_user_id);
  487. }
  488. if ($existing_session || !$last_message['createtime']) {
  489. $resdata['last_time'] = Common::format_time(null);
  490. } else {
  491. $resdata['last_time'] = Common::format_time($last_message['createtime']);
  492. }
  493. dump($resdata);
  494. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 1, 'data' => $resdata]));
  495. }
  496. }