From 5b882ad1902aa6b2c4aa53a724c6d0c68b19bd86 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Sat, 20 May 2023 18:27:04 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E6=AD=A3=E5=90=91=20ws=20adapter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ZM/Context/Trait/BotActionTrait.php | 8 +++++- src/ZM/Middleware/WebSocketFilter.php | 1 + src/ZM/Plugin/OneBot/BotMap.php | 32 ++++++++++++++++++++++++ src/ZM/Plugin/OneBot/OneBot12Adapter.php | 27 ++++++++++++-------- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/ZM/Context/Trait/BotActionTrait.php b/src/ZM/Context/Trait/BotActionTrait.php index 4ca3f6d4..7dccdb6b 100644 --- a/src/ZM/Context/Trait/BotActionTrait.php +++ b/src/ZM/Context/Trait/BotActionTrait.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace ZM\Context\Trait; use OneBot\Driver\Coroutine\Adaptive; +use OneBot\Driver\Interfaces\WebSocketClientInterface; use OneBot\Util\Utils; use OneBot\V12\Object\Action; use OneBot\V12\Object\ActionResponse; @@ -72,7 +73,12 @@ trait BotActionTrait logger()->error("机器人 [{$self['platform']}:{$self['user_id']}] 没有连接或未就绪,无法发送数据"); return false; } - $result = ws_socket($fd_map[0])->send(json_encode($a->jsonSerialize()), $fd_map[1]); + // 如果没指定 flag,但指定了第三个参数且为 WebSocketClientInterface,就是客户端模式 + if ($fd_map[0] === null && ($fd_map[2] ?? null) instanceof WebSocketClientInterface) { + $result = $fd_map[2]->send(json_encode($a->jsonSerialize())); + } else { + $result = ws_socket($fd_map[0])->send(json_encode($a->jsonSerialize()), $fd_map[1]); + } } elseif ($this instanceof BotConnectContext) { // self 为空,说明可能是发送的元动作,需要通过 fd 来查找对应的 connect 连接 $flag = $this->getFlag(); diff --git a/src/ZM/Middleware/WebSocketFilter.php b/src/ZM/Middleware/WebSocketFilter.php index 86912642..572a7a4b 100644 --- a/src/ZM/Middleware/WebSocketFilter.php +++ b/src/ZM/Middleware/WebSocketFilter.php @@ -48,6 +48,7 @@ class WebSocketFilter implements MiddlewareInterface, PipelineInterface return false; } // 过滤连接信息 + // 这里需要考虑一下 ws client 的情况,TODO $conn = ConnectionUtil::getConnection($event->getFd()); foreach ($this->args as $k => $v) { if (!isset($conn[$k])) { diff --git a/src/ZM/Plugin/OneBot/BotMap.php b/src/ZM/Plugin/OneBot/BotMap.php index ee260d6c..9814fc6d 100644 --- a/src/ZM/Plugin/OneBot/BotMap.php +++ b/src/ZM/Plugin/OneBot/BotMap.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ZM\Plugin\OneBot; +use OneBot\Driver\Interfaces\WebSocketClientInterface; use OneBot\V12\Object\OneBotEvent; use ZM\Context\BotConnectContext; use ZM\Context\BotContext; @@ -77,6 +78,22 @@ class BotMap return true; } + /** + * 通过 ws client 注册机器人 + * + * @param int|string $bot_id 机器人 ID + * @param string $platform 机器人平台 + * @param bool $status 机器人状态 + * @param WebSocketClientInterface $client 机器人对应的 ws client + */ + public static function registerBotWithWSClient(string|int $bot_id, string $platform, bool $status, WebSocketClientInterface $client): bool + { + logger()->debug('正在注册机器人:' . "{$platform}:{$bot_id}, client fd:{$client->getFd()}"); + self::$bot_fds[$platform][strval($bot_id)] = [null, $client->getFd(), $client]; + self::$bot_status[$platform][strval($bot_id)] = $status; + return true; + } + /** * 获取所有机器人对应的 fd * @@ -117,6 +134,21 @@ class BotMap } } + public static function unregisterBotByWSClient(WebSocketClientInterface $client): void + { + $unreg_list = []; + foreach (self::$bot_fds as $platform => $bots) { + foreach ($bots as $bot_id => $bot_fd) { + if (isset($bot_fd[2]) && $bot_fd[2] === $client) { + $unreg_list[] = [$platform, $bot_id]; + } + } + } + foreach ($unreg_list as $item) { + self::unregisterBot($item[1], $item[0]); + } + } + public static function getBotContext(string|int $bot_id = '', string $platform = ''): BotContext { if (isset(self::$bot_ctx_cache[$platform][$bot_id])) { diff --git a/src/ZM/Plugin/OneBot/OneBot12Adapter.php b/src/ZM/Plugin/OneBot/OneBot12Adapter.php index 16617229..b5116bfc 100644 --- a/src/ZM/Plugin/OneBot/OneBot12Adapter.php +++ b/src/ZM/Plugin/OneBot/OneBot12Adapter.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace ZM\Plugin\OneBot; use Choir\Http\HttpFactory; +use DI\DependencyException; +use DI\NotFoundException; use OneBot\Driver\Coroutine\Adaptive; use OneBot\Driver\Event\StopException; use OneBot\Driver\Event\WebSocket\WebSocketCloseEvent; @@ -171,25 +173,30 @@ class OneBot12Adapter extends ZMPlugin /** * [CALLBACK] 处理 status_update 事件,更新 BotMap * - * @param OneBotEvent $event 机器人事件 + * @param OneBotEvent $event 机器人事件 + * @throws DependencyException + * @throws NotFoundException */ - public function handleStatusUpdate(OneBotEvent $event, WebSocketMessageEvent $message_event): void + public function handleStatusUpdate(OneBotEvent $event): void { $status = $event->get('status'); $old = BotMap::getBotFds(); if (($status['good'] ?? false) === true) { foreach (($status['bots'] ?? []) as $bot) { - BotMap::registerBotWithFd( - bot_id: $bot['self']['user_id'], - platform: $bot['self']['platform'], - status: $bot['good'] ?? false, - fd: $message_event->getFd(), - flag: $message_event->getSocketFlag() - ); + if (container()->has(WebSocketMessageEvent::class)) { + $message_event = container()->get(WebSocketMessageEvent::class); + BotMap::registerBotWithFd( + bot_id: $bot['self']['user_id'], + platform: $bot['self']['platform'], + status: $bot['good'] ?? false, + fd: $message_event->getFd(), + flag: $message_event->getSocketFlag() + ); + } if (isset($old[$bot['self']['platform']][$bot['self']['user_id']])) { unset($old[$bot['self']['platform']][$bot['self']['user_id']]); } - logger()->error("[{$bot['self']['platform']}.{$bot['self']['user_id']}] 已接入,状态:" . (($bot['good'] ?? false) ? 'OK' : 'Not OK')); + logger()->notice("[{$bot['self']['platform']}.{$bot['self']['user_id']}] 已接入,状态:" . (($bot['good'] ?? false) ? 'OK' : 'Not OK')); } } else { logger()->debug('该实现状态目前不是正常的,不处理 bots 列表');