mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-23 16:45:35 +08:00
Merge pull request #133 from zhamao-robot/fix-adapter-overflow
修复 OneBot11Adapter 无限回调溢出及其他小补丁
This commit is contained in:
@@ -7,17 +7,17 @@ use Psr\Log\LogLevel;
|
|||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'level' => LogLevel::DEBUG,
|
'level' => LogLevel::INFO,
|
||||||
'logger' => static function (string $title = null): LoggerInterface {
|
'logger' => static function (string $prefix = null): LoggerInterface {
|
||||||
if ($title) {
|
if ($prefix) {
|
||||||
$title = strtoupper($title);
|
$prefix = strtoupper($prefix);
|
||||||
} else {
|
} else {
|
||||||
// 在 Master 中,worker_id 将不存在
|
// 在 Master 中,worker_id 将不存在
|
||||||
$title = app()->has('worker_id') ? '#' . app('worker_id') : 'MST';
|
$prefix = app()->has('worker_id') ? '#' . app('worker_id') : 'MST';
|
||||||
}
|
}
|
||||||
|
|
||||||
$logger = new ConsoleLogger(zm_config('logging.level'));
|
$logger = new ConsoleLogger(zm_config('logging.level'));
|
||||||
$logger::$format = "[%date%] [%level%] [{$title}] %body%";
|
$logger::$format = "[%date%] [%level%] [{$prefix}] %body%";
|
||||||
$logger::$date_format = 'Y-m-d H:i:s';
|
$logger::$date_format = 'Y-m-d H:i:s';
|
||||||
// 如果你喜欢旧版的日志格式,请取消下行注释
|
// 如果你喜欢旧版的日志格式,请取消下行注释
|
||||||
// $logger::$date_format = 'm-d H:i:s';
|
// $logger::$date_format = 'm-d H:i:s';
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use ZM\Annotation\Http\RequestMapping;
|
|||||||
use ZM\Annotation\Swoole\OnCloseEvent;
|
use ZM\Annotation\Swoole\OnCloseEvent;
|
||||||
use ZM\Annotation\Swoole\OnOpenEvent;
|
use ZM\Annotation\Swoole\OnOpenEvent;
|
||||||
use ZM\Annotation\Swoole\OnRequestEvent;
|
use ZM\Annotation\Swoole\OnRequestEvent;
|
||||||
use ZM\Annotation\Swoole\OnStart;
|
|
||||||
use ZM\API\CQ;
|
use ZM\API\CQ;
|
||||||
use ZM\API\OneBotV11;
|
use ZM\API\OneBotV11;
|
||||||
use ZM\API\TuringAPI;
|
use ZM\API\TuringAPI;
|
||||||
@@ -252,7 +251,7 @@ class Hello
|
|||||||
bot()->all()->allGroups()->sendGroupMsg(0, ctx()->getMessage());
|
bot()->all()->allGroups()->sendGroupMsg(0, ctx()->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* 欢迎来到容器时代
|
* 欢迎来到容器时代
|
||||||
*
|
*
|
||||||
* @param Context $context 通过依赖注入实现的
|
* @param Context $context 通过依赖注入实现的
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ContainerServicesProvider
|
|||||||
$container->instance('worker_id', Framework::$server->worker_id);
|
$container->instance('worker_id', Framework::$server->worker_id);
|
||||||
|
|
||||||
$container->singleton(AdapterInterface::class, OneBot11Adapter::class);
|
$container->singleton(AdapterInterface::class, OneBot11Adapter::class);
|
||||||
$container->singleton(LoggerInterface::class, ZMConfig::get('logging.logger'));
|
$container->instance(LoggerInterface::class, ZMConfig::get('logging.logger')());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ class ModuleUnpacker
|
|||||||
$prompt = !is_string($this->module['unpack']['global-config-override']) ? '请根据模块提供者提供的要求进行修改 global.php 中对应的配置项' : $this->module['unpack']['global-config-override'];
|
$prompt = !is_string($this->module['unpack']['global-config-override']) ? '请根据模块提供者提供的要求进行修改 global.php 中对应的配置项' : $this->module['unpack']['global-config-override'];
|
||||||
Console::warning('模块作者要求用户手动修改 global.php 配置文件中的项目:');
|
Console::warning('模块作者要求用户手动修改 global.php 配置文件中的项目:');
|
||||||
Console::warning('*' . $prompt);
|
Console::warning('*' . $prompt);
|
||||||
if (STDIN === false) {
|
if (STDIN === false) { // @phpstan-ignore-line
|
||||||
Console::warning('检测到终端无法输入,请手动修改 global.php 配置文件中的项目');
|
Console::warning('检测到终端无法输入,请手动修改 global.php 配置文件中的项目');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -788,10 +788,10 @@ function is_assoc_array(array $array): bool
|
|||||||
/**
|
/**
|
||||||
* 返回 Logger 实例
|
* 返回 Logger 实例
|
||||||
*/
|
*/
|
||||||
function logger(...$args): LoggerInterface
|
function logger(string $prefix = null): LoggerInterface
|
||||||
{
|
{
|
||||||
if (!app()->has(LoggerInterface::class)) {
|
if (!is_null($prefix) || !app()->has(LoggerInterface::class)) {
|
||||||
return zm_config('logging.logger')(...$args);
|
return zm_config('logging.logger')($prefix);
|
||||||
}
|
}
|
||||||
return resolve(LoggerInterface::class);
|
return resolve(LoggerInterface::class);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user