diff --git a/config/global.php b/config/global.php index 603f5be2..6002f367 100644 --- a/config/global.php +++ b/config/global.php @@ -123,7 +123,8 @@ $config['onebot'] = [ 'status' => true, 'single_bot_mode' => false, 'message_level' => 99, - 'message_convert_string' => true + 'message_convert_string' => true, + 'message_command_policy' => 'interrupt', ]; /** 一个远程简易终端,使用nc直接连接即可,但是不建议开放host为0.0.0.0(远程连接) */ diff --git a/docs/guide/basic-config.md b/docs/guide/basic-config.md index f3387956..f514e8e4 100644 --- a/docs/guide/basic-config.md +++ b/docs/guide/basic-config.md @@ -114,6 +114,7 @@ | `single_bot_mode` | 是否开启单机器人模式 | false | | `message_level` | 机器人的 WebSocket 事件在 Swoole 原生事件 `@OnMessageEvent` 中的等级(越高说明越被优先处理) | 99 | | `message_convert_string` | 是否将数组格式的消息转换为字符串以保证与旧版本的兼容性 | true | +| `message_command_policy` | CQCommand命令匹配后执行流程,`interrupt` 为不执行后续 CQMessage,`continue` 为继续 | `interrupt` | ### 子表 remote_terminal diff --git a/src/ZM/ConsoleApplication.php b/src/ZM/ConsoleApplication.php index 9e30719d..5c46be48 100644 --- a/src/ZM/ConsoleApplication.php +++ b/src/ZM/ConsoleApplication.php @@ -30,8 +30,8 @@ class ConsoleApplication extends Application { private static $obj = null; - const VERSION_ID = 428; - const VERSION = "2.6.1"; + const VERSION_ID = 429; + const VERSION = "2.6.2"; /** * @throws InitException diff --git a/src/ZM/Module/QQBot.php b/src/ZM/Module/QQBot.php index 2450ed05..cf05cfb2 100644 --- a/src/ZM/Module/QQBot.php +++ b/src/ZM/Module/QQBot.php @@ -4,6 +4,7 @@ namespace ZM\Module; use Exception; +use ZM\Annotation\CQ\CQAfter; use ZM\Annotation\CQ\CQAPIResponse; use ZM\Annotation\CQ\CQBefore; use ZM\Annotation\CQ\CQCommand; @@ -11,6 +12,7 @@ use ZM\Annotation\CQ\CQMessage; use ZM\Annotation\CQ\CQMetaEvent; use ZM\Annotation\CQ\CQNotice; use ZM\Annotation\CQ\CQRequest; +use ZM\Config\ZMConfig; use ZM\Event\EventDispatcher; use ZM\Exception\InterruptException; use ZM\Exception\WaitTimeoutException; @@ -59,9 +61,25 @@ class QQBot } if (isset($data["post_type"])) $this->dispatchEvents($data); else $this->dispatchAPIResponse($data); + + if (($data["post_type"] ?? "meta_event") != "meta_event") { + $r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志 + if ($r->store === "block") EventDispatcher::interrupt(); + } } /** @noinspection PhpRedundantCatchClauseInspection */ catch (WaitTimeoutException $e) { + if (($data["post_type"] ?? "meta_event") != "meta_event") { + $r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志 + if ($r->store === "block") EventDispatcher::interrupt(); + } $e->module->finalReply($e->getMessage()); + } catch (InterruptException $e) { + if (($data["post_type"] ?? "meta_event") != "meta_event") { + $r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志 + if ($r->store === "block") EventDispatcher::interrupt(); + } + throw $e; } + // 这里修复CQAfter不能使用的问题,我竟然一直没写,绝了 } /** @@ -108,7 +126,18 @@ class QQBot if (!empty($s->match)) ctx()->setCache("match", $s->match); $dispatcher->dispatchEvent($s->object, null); if (is_string($dispatcher->store)) ctx()->reply($dispatcher->store); - if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt(); + if (ctx()->getCache("has_reply") === true) { + $policy = ZMConfig::get("global", "onebot")['message_command_policy'] ?? 'interrupt'; + switch ($policy) { + case 'interrupt': + EventDispatcher::interrupt(); + break; + case 'continue': + break; + default: + throw new Exception("未知的消息命令策略:" . $policy); + } + } } //分发CQMessage事件 @@ -158,6 +187,16 @@ class QQBot } } + private function dispatchAfterEvents($data): EventDispatcher { + $after = new EventDispatcher(CQAfter::class); + $after->setRuleFunction(function ($v) use ($data) { + return $v->cq_event == $data["post_type"]; + }); + zm_dump("开始触发!", $data); + $after->dispatchEvents($data); + return $after; + } + /** * @param $req * @throws Exception