ChatService.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Chat 客服聊天服务
  4. // +----------------------------------------------------------------------
  5. namespace app\services\workerman\chat;
  6. use Channel\Client;
  7. use app\services\workerman\ChannelService;
  8. use app\services\workerman\Response;
  9. use Workerman\Connection\TcpConnection;
  10. use Workerman\Lib\Timer;
  11. use Workerman\Worker;
  12. class ChatService
  13. {
  14. protected $worker;
  15. protected $connections = [];
  16. protected $user = [];
  17. protected $kefuUser = [];
  18. protected $handle;
  19. protected $response;
  20. protected $timer;
  21. public function __construct(Worker $worker)
  22. {
  23. $this->worker = $worker;
  24. $this->handle = new ChatHandle($this);
  25. $this->response = new Response();
  26. }
  27. public function setUser(TcpConnection $connection)
  28. {
  29. $this->user[$connection->user->uid] = $connection;
  30. }
  31. public function kefuUser()
  32. {
  33. return $this->kefuUser;
  34. }
  35. public function setKefuUser(TcpConnection $connection, bool $isUser = true)
  36. {
  37. $this->kefuUser[$connection->kefuUser->uid] = $connection;
  38. if ($isUser) {
  39. $this->user[$connection->user->uid] = $connection;
  40. }
  41. }
  42. public function user($key = null)
  43. {
  44. return $key ? ($this->user[$key] ?? false) : $this->user;
  45. }
  46. public function onConnect(TcpConnection $connection)
  47. {
  48. $this->connections[$connection->id] = $connection;
  49. $connection->lastMessageTime = time();
  50. }
  51. public function onMessage(TcpConnection $connection, $res)
  52. {
  53. $connection->lastMessageTime = time();
  54. $res = json_decode($res, true);
  55. if (!$res || !isset($res['type']) || !$res['type'] || $res['type'] == 'ping') {
  56. return $this->response->connection($connection)->success('ping', ['now' => time()]);
  57. }
  58. if (!method_exists($this->handle, $res['type'])) return;
  59. try {
  60. $this->handle->{$res['type']}($connection, $res + ['data' => []], $this->response->connection($connection));
  61. } catch (\Throwable $e) {
  62. // 忽略异常
  63. }
  64. }
  65. public function onWorkerStart(Worker $worker)
  66. {
  67. ChannelService::connet();
  68. Client::on('muyinjie_chat', function ($eventData) use ($worker) {
  69. if (!isset($eventData['type']) || !$eventData['type']) return;
  70. $ids = isset($eventData['ids']) && count($eventData['ids']) ? $eventData['ids'] : array_keys($this->user);
  71. foreach ($ids as $id) {
  72. if (isset($this->user[$id])) {
  73. $this->response->connection($this->user[$id])->success($eventData['type'], $eventData['data'] ?? null);
  74. }
  75. }
  76. });
  77. $this->timer = Timer::add(15, function () use (&$worker) {
  78. $time_now = time();
  79. foreach ($worker->connections as $connection) {
  80. if ($time_now - $connection->lastMessageTime > 12) {
  81. $this->response->connection($connection)->close('timeout');
  82. }
  83. }
  84. });
  85. }
  86. public function onClose(TcpConnection $connection)
  87. {
  88. unset($this->connections[$connection->id]);
  89. if (isset($connection->user->uid)) {
  90. unset($this->user[$connection->user->uid]);
  91. }
  92. if (isset($connection->kefuUser->uid)) {
  93. unset($this->kefuUser[$connection->kefuUser->uid]);
  94. }
  95. }
  96. }