fix adapter overflow

This commit is contained in:
sunxyw
2022-05-31 00:52:15 +08:00
parent e350edd41f
commit 79f5011d58
2 changed files with 72 additions and 43 deletions

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace ZM\Adapters; namespace ZM\Adapters;
use Swoole\WebSocket\Frame;
use ZM\Context\ContextInterface; use ZM\Context\ContextInterface;
interface AdapterInterface interface AdapterInterface
@@ -22,8 +21,7 @@ interface AdapterInterface
/** /**
* 处理传入请求 * 处理传入请求
* *
* @param Frame $frame WebSocket消息帧
* @param ContextInterface $context 上下文 * @param ContextInterface $context 上下文
*/ */
public function handleIncomingRequest(Frame $frame, ContextInterface $context): void; public function handleIncomingRequest(ContextInterface $context): void;
} }

View File

@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace ZM\Adapters; namespace ZM\Adapters;
use Swoole\WebSocket\Frame;
use ZM\Annotation\CQ\CQAfter; use ZM\Annotation\CQ\CQAfter;
use ZM\Annotation\CQ\CQAPIResponse; use ZM\Annotation\CQ\CQAPIResponse;
use ZM\Annotation\CQ\CQBefore; use ZM\Annotation\CQ\CQBefore;
@@ -41,68 +40,74 @@ class OneBot11Adapter implements AdapterInterface
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function handleIncomingRequest(Frame $frame, ContextInterface $context): void public function handleIncomingRequest(ContextInterface $context): void
{ {
$data = json_decode($frame->data, true); $data = json_decode($context->getFrame()->data, true);
// 将数据存入协程参数中 // 将数据存入协程参数中
set_coroutine_params(compact('data')); set_coroutine_params(compact('data'));
try { try {
// 事件类型不存在,代表为非法请求或 API 响应 logger()->debug('start handle incoming request');
if (!isset($data['post_type'])) {
if (isset($data['echo']) && CoMessage::resumeByWS()) {
EventDispatcher::interrupt();
}
$this->handleAPIResponse($data, $context);
return;
}
if ($data['post_type'] !== 'meta_event') { // 非元事件调用 pre-before 事件
$before_result = $this->handleBeforeEvent($data, 'pre'); if (!$this->isMetaEvent($data)) {
if ($before_result->store === 'block') { logger()->debug('pre-before event');
$pre_before_result = $this->handleBeforeEvent($data, 'pre');
if ($pre_before_result->store === 'block') {
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
} }
// 回调或事件处理 resume
if (CoMessage::resumeByWS()) { if (CoMessage::resumeByWS()) {
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
if ($data['post_type'] !== 'meta_event') { // 非元事件调用 after-before 事件
$before_result = $this->handleBeforeEvent($data, 'post'); if (!$this->isMetaEvent($data)) {
if ($before_result->store === 'block') { logger()->debug('post-before event');
$post_before_result = $this->handleBeforeEvent($data, 'post');
if ($post_before_result->store === 'block') {
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
} }
switch ($data['post_type']) { // 进入回调、事件分发流程
case 'message': if ($this->isEvent($data)) {
$this->handleMessageEvent($data, $context); // 事件分发
break; switch ($data['post_type']) {
case 'meta_event': case 'message':
$this->handleMetaEvent($data, $context); logger()->debug('message event {data}', compact('data'));
break; $this->handleMessageEvent($data, $context);
case 'notice': break;
$this->handleNoticeEvent($data, $context); case 'meta_event':
break; logger()->debug('meta event {data}', compact('data'));
case 'request': $this->handleMetaEvent($data, $context);
$this->handleRequestEvent($data, $context); break;
break; case 'notice':
} logger()->debug('notice event {data}', compact('data'));
$this->handleNoticeEvent($data, $context);
if ($data['post_type'] !== 'meta_event') { break;
$before_result = $this->handleAfterEvent($data); case 'request':
if ($before_result->store === 'block') { logger()->debug('request event {data}', compact('data'));
EventDispatcher::interrupt(); $this->handleRequestEvent($data, $context);
break;
} }
} elseif ($this->isAPIResponse($data)) {
logger()->debug('api response {data}', compact('data'));
$this->handleAPIResponse($data, $context);
} }
logger()->debug('event end {data}', compact('data'));
// 回调、事件处理完成
} catch (WaitTimeoutException $e) { } catch (WaitTimeoutException $e) {
$e->module->finalReply($e->getMessage()); $e->module->finalReply($e->getMessage());
} finally { } finally {
if (isset($data['post_type']) && $data['post_type'] !== 'meta_event') { // 非元事件调用 after 事件
$before_result = $this->handleAfterEvent($data); if (!$this->isMetaEvent($data)) {
if ($before_result->store === 'block') { logger()->debug('after event');
$after_result = $this->handleAfterEvent($data);
if ($after_result->store === 'block') {
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
} }
@@ -271,7 +276,7 @@ class OneBot11Adapter implements AdapterInterface
} else { } else {
$level = $event->level < 200; $level = $event->level < 200;
} }
return $level && ($event->cq_event === $data['post_type']); return $level && ($event->cq_event === ($data['post_type'] ?? ''));
}); });
// 设定返回值处理函数 // 设定返回值处理函数
$dispatcher->setReturnFunction(function ($result) { $dispatcher->setReturnFunction(function ($result) {
@@ -300,4 +305,30 @@ class OneBot11Adapter implements AdapterInterface
$dispatcher->dispatchEvents($data); $dispatcher->dispatchEvents($data);
return $dispatcher; return $dispatcher;
} }
/**
* 判断是否为 API 回调
*/
private function isAPIResponse(array $data): bool
{
// API 响应应带有 echo 字段
return !isset($data['post_type']) && isset($data['echo']);
}
/**
* 判断是否为事件
*/
private function isEvent(array $data): bool
{
// 所有事件都应带有 post_type 字段
return isset($data['post_type']);
}
/**
* 判断是否为元事件
*/
private function isMetaEvent(array $data): bool
{
return $this->isEvent($data) && $data['post_type'] === 'meta_event';
}
} }