2020-11-02 22:45:37 +08:00
|
|
|
<?php
|
2021-07-20 23:12:18 +08:00
|
|
|
declare(strict_types=1);
|
2020-11-02 22:45:37 +08:00
|
|
|
|
2021-07-08 19:09:06 +08:00
|
|
|
namespace App\Service\Message;
|
|
|
|
|
2021-07-28 23:42:21 +08:00
|
|
|
use App\Cache\GroupCache;
|
2021-07-08 19:09:06 +08:00
|
|
|
use App\Cache\SocketRoom;
|
2021-07-20 23:12:18 +08:00
|
|
|
use App\Constants\TalkEventConstant;
|
|
|
|
use App\Constants\TalkModeConstant;
|
2021-07-09 22:57:19 +08:00
|
|
|
use App\Model\Talk\TalkRecords;
|
2021-07-08 19:09:06 +08:00
|
|
|
use App\Model\User;
|
2022-01-16 10:29:16 +08:00
|
|
|
use App\Model\ContactApply;
|
2020-11-29 14:44:11 +08:00
|
|
|
use App\Service\SocketClientService;
|
2021-07-08 19:09:06 +08:00
|
|
|
use App\Service\UserService;
|
2020-11-02 22:45:37 +08:00
|
|
|
|
2021-07-08 19:09:06 +08:00
|
|
|
class SubscribeHandleService
|
2020-11-02 22:45:37 +08:00
|
|
|
{
|
2020-11-27 19:48:41 +08:00
|
|
|
/**
|
2020-12-01 17:47:25 +08:00
|
|
|
* 消息事件与回调事件绑定
|
|
|
|
*
|
|
|
|
* @var array
|
2020-11-27 19:48:41 +08:00
|
|
|
*/
|
2020-11-22 23:10:00 +08:00
|
|
|
const EVENTS = [
|
2020-11-27 19:48:41 +08:00
|
|
|
// 聊天消息事件
|
2021-07-20 23:12:18 +08:00
|
|
|
TalkEventConstant::EVENT_TALK => 'onConsumeTalk',
|
2020-11-27 19:48:41 +08:00
|
|
|
|
|
|
|
// 键盘输入事件
|
2021-07-20 23:12:18 +08:00
|
|
|
TalkEventConstant::EVENT_KEYBOARD => 'onConsumeKeyboard',
|
2020-11-27 19:48:41 +08:00
|
|
|
|
|
|
|
// 用户在线状态事件
|
2021-07-20 23:12:18 +08:00
|
|
|
TalkEventConstant::EVENT_ONLINE_STATUS => 'onConsumeOnlineStatus',
|
2020-11-27 19:48:41 +08:00
|
|
|
|
|
|
|
// 聊天消息推送事件
|
2021-07-20 23:12:18 +08:00
|
|
|
TalkEventConstant::EVENT_REVOKE_TALK => 'onConsumeRevokeTalk',
|
2020-11-27 19:48:41 +08:00
|
|
|
|
|
|
|
// 好友申请相关事件
|
2021-07-20 23:12:18 +08:00
|
|
|
TalkEventConstant::EVENT_FRIEND_APPLY => 'onConsumeFriendApply'
|
2020-11-22 23:10:00 +08:00
|
|
|
];
|
|
|
|
|
2020-11-21 19:53:01 +08:00
|
|
|
/**
|
2021-07-08 19:09:06 +08:00
|
|
|
* @var SocketClientService
|
2020-11-02 22:45:37 +08:00
|
|
|
*/
|
2021-07-08 19:09:06 +08:00
|
|
|
private $clientService;
|
2020-11-02 22:45:37 +08:00
|
|
|
|
2021-07-08 19:09:06 +08:00
|
|
|
public function __construct(SocketClientService $clientService)
|
2020-11-22 23:10:00 +08:00
|
|
|
{
|
2021-07-08 19:09:06 +08:00
|
|
|
$this->clientService = $clientService;
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
|
2021-07-09 22:57:19 +08:00
|
|
|
/**
|
2021-09-05 21:13:48 +08:00
|
|
|
* @param array $data 数据
|
2022-01-17 21:06:27 +08:00
|
|
|
* <pre>
|
|
|
|
* [
|
|
|
|
* 'uuid' => '',
|
|
|
|
* 'event' => '',
|
|
|
|
* 'data' => '',
|
|
|
|
* 'options' => ''
|
|
|
|
* ];
|
|
|
|
* </pre>
|
2021-07-09 22:57:19 +08:00
|
|
|
*/
|
|
|
|
public function handle(array $data)
|
|
|
|
{
|
2021-07-10 10:55:25 +08:00
|
|
|
if (!isset($data['uuid'], $data['event'], $data['data'], $data['options'])) {
|
2021-09-05 21:13:48 +08:00
|
|
|
return;
|
2021-07-10 10:55:25 +08:00
|
|
|
}
|
|
|
|
|
2021-07-09 22:57:19 +08:00
|
|
|
if (isset(self::EVENTS[$data['event']])) {
|
|
|
|
call_user_func([$this, self::EVENTS[$data['event']]], $data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-22 23:10:00 +08:00
|
|
|
/**
|
|
|
|
* 对话聊天消息
|
|
|
|
*
|
2021-07-08 19:09:06 +08:00
|
|
|
* @param array $data 队列消息
|
2020-11-22 23:10:00 +08:00
|
|
|
*/
|
2021-07-17 00:07:24 +08:00
|
|
|
public function onConsumeTalk(array $data): void
|
2020-11-02 22:45:37 +08:00
|
|
|
{
|
2021-07-05 21:52:44 +08:00
|
|
|
$talk_type = $data['data']['talk_type'];
|
|
|
|
$sender_id = $data['data']['sender_id'];
|
|
|
|
$receiver_id = $data['data']['receiver_id'];
|
|
|
|
$record_id = $data['data']['record_id'];
|
|
|
|
|
2021-06-29 17:30:43 +08:00
|
|
|
$fds = [];
|
2021-04-08 09:20:51 +08:00
|
|
|
$groupInfo = null;
|
2020-11-21 19:53:01 +08:00
|
|
|
|
2021-07-20 23:12:18 +08:00
|
|
|
if ($talk_type == TalkModeConstant::PRIVATE_CHAT) {
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds[] = $this->clientService->findUserFds($sender_id);
|
|
|
|
$fds[] = $this->clientService->findUserFds($receiver_id);
|
2021-07-20 23:12:18 +08:00
|
|
|
} else if ($talk_type == TalkModeConstant::GROUP_CHAT) {
|
2021-07-05 21:52:44 +08:00
|
|
|
foreach (SocketRoom::getInstance()->getRoomMembers(strval($receiver_id)) as $uid) {
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds[] = $this->clientService->findUserFds(intval($uid));
|
2020-11-03 14:07:54 +08:00
|
|
|
}
|
2021-03-31 17:28:58 +08:00
|
|
|
|
2021-07-28 23:42:21 +08:00
|
|
|
$groupInfo = GroupCache::getInstance()->getOrSetCache($receiver_id);
|
2020-11-21 19:53:01 +08:00
|
|
|
}
|
|
|
|
|
2021-08-31 21:31:45 +08:00
|
|
|
if (empty($fds)) return;
|
|
|
|
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds = array_unique(array_merge(...$fds));
|
|
|
|
|
2020-12-01 13:54:40 +08:00
|
|
|
// 客户端ID去重
|
2021-08-06 23:57:49 +08:00
|
|
|
if (!$fds) return;
|
2021-07-17 00:07:24 +08:00
|
|
|
|
2021-07-05 21:52:44 +08:00
|
|
|
$result = TalkRecords::leftJoin('users', 'users.id', '=', 'talk_records.user_id')
|
|
|
|
->where('talk_records.id', $record_id)
|
2020-11-21 19:53:01 +08:00
|
|
|
->first([
|
2021-07-05 21:52:44 +08:00
|
|
|
'talk_records.id',
|
|
|
|
'talk_records.talk_type',
|
|
|
|
'talk_records.msg_type',
|
|
|
|
'talk_records.user_id',
|
|
|
|
'talk_records.receiver_id',
|
|
|
|
'talk_records.content',
|
|
|
|
'talk_records.is_revoke',
|
|
|
|
'talk_records.created_at',
|
2020-11-21 19:53:01 +08:00
|
|
|
'users.nickname',
|
2021-03-31 17:28:58 +08:00
|
|
|
'users.avatar',
|
2020-11-21 19:53:01 +08:00
|
|
|
]);
|
|
|
|
|
2021-07-17 00:07:24 +08:00
|
|
|
if (!$result) return;
|
2020-11-21 19:53:01 +08:00
|
|
|
|
2021-07-23 21:34:29 +08:00
|
|
|
$message = di()->get(FormatMessageService::class)->handleChatRecords([$result->toArray()])[0];
|
2022-01-17 21:06:27 +08:00
|
|
|
|
|
|
|
$this->push($fds, $this->toJson(TalkEventConstant::EVENT_TALK, [
|
2021-07-05 21:52:44 +08:00
|
|
|
'sender_id' => $sender_id,
|
|
|
|
'receiver_id' => $receiver_id,
|
|
|
|
'talk_type' => $talk_type,
|
2021-07-17 00:07:24 +08:00
|
|
|
'data' => array_merge($message, [
|
2021-07-28 23:42:21 +08:00
|
|
|
'group_name' => $groupInfo ? $groupInfo['group_name'] : '',
|
|
|
|
'group_avatar' => $groupInfo ? $groupInfo['avatar'] : ''
|
2020-11-21 19:53:01 +08:00
|
|
|
])
|
2022-01-17 21:06:27 +08:00
|
|
|
]));
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 键盘输入事件消息
|
|
|
|
*
|
2021-07-08 19:09:06 +08:00
|
|
|
* @param array $data 队列消息
|
2020-11-22 23:10:00 +08:00
|
|
|
*/
|
2021-07-17 00:07:24 +08:00
|
|
|
public function onConsumeKeyboard(array $data): void
|
2020-11-22 23:10:00 +08:00
|
|
|
{
|
2021-07-08 19:09:06 +08:00
|
|
|
$fds = $this->clientService->findUserFds($data['data']['receiver_id']);
|
2020-12-01 13:54:40 +08:00
|
|
|
|
2022-01-17 21:06:27 +08:00
|
|
|
$this->push($fds, $this->toJson(TalkEventConstant::EVENT_KEYBOARD, $data['data']));
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 用户上线或下线消息
|
|
|
|
*
|
2021-07-08 19:09:06 +08:00
|
|
|
* @param array $data 队列消息
|
2020-11-22 23:10:00 +08:00
|
|
|
*/
|
2021-07-17 00:07:24 +08:00
|
|
|
public function onConsumeOnlineStatus(array $data): void
|
2020-11-22 23:10:00 +08:00
|
|
|
{
|
2021-07-05 21:52:44 +08:00
|
|
|
$user_id = (int)$data['data']['user_id'];
|
|
|
|
$status = (int)$data['data']['status'];
|
2020-11-22 23:10:00 +08:00
|
|
|
|
2021-07-23 21:34:29 +08:00
|
|
|
$ids = di()->get(UserService::class)->getFriendIds($user_id);
|
2021-08-31 21:31:45 +08:00
|
|
|
|
|
|
|
if (empty($ids)) return;
|
|
|
|
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds = [];
|
2021-07-07 19:43:09 +08:00
|
|
|
foreach ($ids as $friend_id) {
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds[] = $this->clientService->findUserFds(intval($friend_id));
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds = array_unique(array_merge(...$fds));
|
|
|
|
|
2022-01-17 21:06:27 +08:00
|
|
|
$this->push($fds, $this->toJson(TalkEventConstant::EVENT_ONLINE_STATUS, [
|
|
|
|
'user_id' => $user_id,
|
|
|
|
'status' => $status
|
2021-07-05 21:52:44 +08:00
|
|
|
]));
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 撤销聊天消息
|
|
|
|
*
|
2021-07-08 19:09:06 +08:00
|
|
|
* @param array $data 队列消息
|
2020-11-22 23:10:00 +08:00
|
|
|
*/
|
2021-07-17 00:07:24 +08:00
|
|
|
public function onConsumeRevokeTalk(array $data): void
|
2020-11-22 23:10:00 +08:00
|
|
|
{
|
2021-07-05 21:52:44 +08:00
|
|
|
$record = TalkRecords::where('id', $data['data']['record_id'])->first(['id', 'talk_type', 'user_id', 'receiver_id']);
|
2020-11-22 23:10:00 +08:00
|
|
|
|
|
|
|
$fds = [];
|
2021-07-20 23:12:18 +08:00
|
|
|
if ($record->talk_type == TalkModeConstant::PRIVATE_CHAT) {
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds[] = $this->clientService->findUserFds($record->user_id);
|
|
|
|
$fds[] = $this->clientService->findUserFds($record->receiver_id);
|
2021-07-20 23:12:18 +08:00
|
|
|
} else if ($record->talk_type == TalkModeConstant::GROUP_CHAT) {
|
2021-08-06 23:57:49 +08:00
|
|
|
foreach (SocketRoom::getInstance()->getRoomMembers(strval($record->receiver_id)) as $uid) {
|
|
|
|
$fds[] = $this->clientService->findUserFds((int)$uid);
|
2020-11-22 23:10:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-31 21:31:45 +08:00
|
|
|
if (empty($fds)) return;
|
|
|
|
|
2021-08-06 23:57:49 +08:00
|
|
|
$fds = array_unique(array_merge(...$fds));
|
|
|
|
|
|
|
|
if (!$fds) return;
|
|
|
|
|
2022-01-17 21:06:27 +08:00
|
|
|
$this->push($fds, $this->toJson(TalkEventConstant::EVENT_REVOKE_TALK, [
|
2021-07-05 21:52:44 +08:00
|
|
|
'talk_type' => $record->talk_type,
|
|
|
|
'sender_id' => $record->user_id,
|
|
|
|
'receiver_id' => $record->receiver_id,
|
|
|
|
'record_id' => $record->id,
|
2022-01-17 21:06:27 +08:00
|
|
|
]));
|
2020-11-02 22:45:37 +08:00
|
|
|
}
|
2020-11-27 19:48:41 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 好友申请消息
|
|
|
|
*
|
2021-07-08 19:09:06 +08:00
|
|
|
* @param array $data 队列消息
|
2020-11-27 19:48:41 +08:00
|
|
|
*/
|
2021-07-17 00:07:24 +08:00
|
|
|
public function onConsumeFriendApply(array $data): void
|
2020-11-27 19:48:41 +08:00
|
|
|
{
|
2021-07-07 19:43:09 +08:00
|
|
|
$data = $data['data'];
|
|
|
|
|
2022-01-16 10:29:16 +08:00
|
|
|
$applyInfo = ContactApply::where('id', $data['apply_id'])->first();
|
2021-07-17 00:07:24 +08:00
|
|
|
if (!$applyInfo) return;
|
2021-07-07 19:43:09 +08:00
|
|
|
|
2021-07-08 19:09:06 +08:00
|
|
|
$fds = $this->clientService->findUserFds($data['type'] == 1 ? $applyInfo->friend_id : $applyInfo->user_id);
|
2021-07-07 19:43:09 +08:00
|
|
|
|
|
|
|
if ($data['type'] == 1) {
|
|
|
|
$msg = [
|
|
|
|
'sender_id' => $applyInfo->user_id,
|
|
|
|
'receiver_id' => $applyInfo->friend_id,
|
|
|
|
'remark' => $applyInfo->remark,
|
|
|
|
];
|
|
|
|
} else {
|
|
|
|
$msg = [
|
|
|
|
'sender_id' => $applyInfo->friend_id,
|
|
|
|
'receiver_id' => $applyInfo->user_id,
|
|
|
|
'status' => $applyInfo->status,
|
|
|
|
'remark' => $applyInfo->remark,
|
|
|
|
];
|
|
|
|
}
|
2020-11-29 14:44:11 +08:00
|
|
|
|
2021-07-07 19:43:09 +08:00
|
|
|
$friendInfo = User::select(['id', 'avatar', 'nickname', 'mobile', 'motto'])->find($data['type'] == 1 ? $applyInfo->user_id : $applyInfo->friend_id);
|
|
|
|
|
|
|
|
$msg['friend'] = [
|
|
|
|
'user_id' => $friendInfo->id,
|
|
|
|
'avatar' => $friendInfo->avatar,
|
|
|
|
'nickname' => $friendInfo->nickname,
|
|
|
|
'mobile' => $friendInfo->mobile,
|
|
|
|
];
|
|
|
|
|
2022-01-17 21:06:27 +08:00
|
|
|
$this->push(array_unique($fds), $this->toJson(TalkEventConstant::EVENT_FRIEND_APPLY, $msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
private function toJson(string $event, array $data): string
|
|
|
|
{
|
|
|
|
return json_encode(["event" => $event, "content" => $data]);
|
2020-12-01 13:54:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* WebSocket 消息推送
|
|
|
|
*
|
2021-09-05 21:13:48 +08:00
|
|
|
* @param array $fds
|
|
|
|
* @param string $message
|
2020-12-01 13:54:40 +08:00
|
|
|
*/
|
2021-09-05 21:13:48 +08:00
|
|
|
private function push(array $fds, string $message): void
|
2020-12-01 13:54:40 +08:00
|
|
|
{
|
2020-11-30 22:59:49 +08:00
|
|
|
$server = server();
|
2020-11-27 19:48:41 +08:00
|
|
|
foreach ($fds as $fd) {
|
2021-05-22 14:47:46 +08:00
|
|
|
$server->exist(intval($fd)) && $server->push(intval($fd), $message);
|
2020-11-27 19:48:41 +08:00
|
|
|
}
|
2020-12-01 13:54:40 +08:00
|
|
|
}
|
2020-11-02 22:45:37 +08:00
|
|
|
}
|