separate bot action method to BotActionTrait

This commit is contained in:
crazywhalecc
2022-12-30 16:13:25 +08:00
parent b86f51ab46
commit dfcb8a4550
5 changed files with 94 additions and 55 deletions

2
.gitignore vendored
View File

@@ -9,7 +9,7 @@
/site/ /site/
/plugins/ /plugins/
/doxy/ /doxy/
/walle/
# 框架审计文件 # 框架审计文件
audit.log audit.log

View File

@@ -4,22 +4,21 @@ declare(strict_types=1);
namespace ZM\Context; namespace ZM\Context;
use Choir\Http\HttpFactory;
use OneBot\Driver\Event\Http\HttpRequestEvent; use OneBot\Driver\Event\Http\HttpRequestEvent;
use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent; use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent;
use OneBot\Util\Utils;
use OneBot\V12\Object\Action; use OneBot\V12\Object\Action;
use OneBot\V12\Object\MessageSegment; use OneBot\V12\Object\MessageSegment;
use OneBot\V12\Object\OneBotEvent; use OneBot\V12\Object\OneBotEvent;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
use ZM\Annotation\AnnotationHandler; use ZM\Context\Trait\BotActionTrait;
use ZM\Annotation\OneBot\BotAction;
use ZM\Exception\OneBot12Exception; use ZM\Exception\OneBot12Exception;
use ZM\Utils\MessageUtil; use ZM\Utils\MessageUtil;
class BotContext implements ContextInterface class BotContext implements ContextInterface
{ {
use BotActionTrait;
private static array $echo_id_list = []; private static array $echo_id_list = [];
private array $self; private array $self;
@@ -28,9 +27,10 @@ class BotContext implements ContextInterface
private bool $replied = false; private bool $replied = false;
public function __construct(string $bot_id, string $platform) public function __construct(string $bot_id, string $platform, null|WebSocketMessageEvent|HttpRequestEvent $event = null)
{ {
$this->self = ['user_id' => $bot_id, 'platform' => $platform]; $this->self = ['user_id' => $bot_id, 'platform' => $platform];
$this->base_event = $event;
} }
public function getEvent(): OneBotEvent public function getEvent(): OneBotEvent
@@ -82,21 +82,9 @@ class BotContext implements ContextInterface
*/ */
public function getBot(string $bot_id, string $platform = ''): BotContext public function getBot(string $bot_id, string $platform = ''): BotContext
{ {
// TODO: 完善多机器人支持
return $this; return $this;
} }
/**
* @throws \Throwable
*/
public function sendMessage(\Stringable|array|MessageSegment|string $message, string $detail_type, array $params = [])
{
$message = MessageUtil::convertToArr($message);
$params['message'] = $message;
$params['detail_type'] = $detail_type;
return $this->sendAction(Utils::camelToSeparator(__FUNCTION__), $params, $this->self);
}
/** /**
* 设置该消息下解析出来的参数列表 * 设置该消息下解析出来的参数列表
* *
@@ -134,39 +122,4 @@ class BotContext implements ContextInterface
{ {
return self::$echo_id_list[$echo] ?? null; return self::$echo_id_list[$echo] ?? null;
} }
/**
* @throws \Throwable
*/
private function sendAction(string $action, array $params = [], ?array $self = null)
{
// 声明 Action 对象
$a = new Action($action, $params, ob_uuidgen(), $self);
self::$echo_id_list[$a->echo] = $a;
// 调用事件在回复之前的回调
$handler = new AnnotationHandler(BotAction::class);
container()->set(Action::class, $a);
$handler->setRuleCallback(fn (BotAction $act) => $act->action === '' || $act->action === $action && !$act->need_response);
$handler->handleAll($a);
// 被阻断时候,就不发送了
if ($handler->getStatus() === AnnotationHandler::STATUS_INTERRUPTED) {
return false;
}
// 调用机器人连接发送 Action
if (container()->has('ws.message.event')) {
/** @var WebSocketMessageEvent $ws */
$ws = container()->get('ws.message.event');
return $ws->send(json_encode($a->jsonSerialize()));
}
// 如果是 HTTP WebHook 的形式,那么直接调用 Response
if (container()->has('http.request.event')) {
/** @var HttpRequestEvent $event */
$event = container()->get('http.request.event');
$response = HttpFactory::createResponse(headers: ['Content-Type' => 'application/json'], body: json_encode([$a->jsonSerialize()]));
$event->withResponse($response);
return true;
}
throw new OneBot12Exception('No bot connection found.');
}
} }

View File

@@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace ZM\Context\Trait;
use Choir\Http\HttpFactory;
use OneBot\Driver\Event\Http\HttpRequestEvent;
use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent;
use OneBot\Util\Utils;
use OneBot\V12\Object\Action;
use OneBot\V12\Object\ActionResponse;
use OneBot\V12\Object\MessageSegment;
use ZM\Annotation\AnnotationHandler;
use ZM\Annotation\OneBot\BotAction;
use ZM\Exception\OneBot12Exception;
use ZM\Utils\MessageUtil;
trait BotActionTrait
{
private null|WebSocketMessageEvent|HttpRequestEvent $base_event;
/**
* @throws \Throwable
*/
public function sendMessage(\Stringable|array|MessageSegment|string $message, string $detail_type, array $params = []): ActionResponse|bool
{
$message = MessageUtil::convertToArr($message);
$params['message'] = $message;
$params['detail_type'] = $detail_type;
return $this->sendAction(Utils::camelToSeparator(__FUNCTION__), $params, $this->self);
}
/**
* 发送机器人动作
*
* @throws \Throwable
*/
public function sendAction(string $action, array $params = [], ?array $self = null): bool|ActionResponse
{
// 声明 Action 对象
$a = new Action($action, $params, ob_uuidgen(), $self);
self::$echo_id_list[$a->echo] = $a;
// 调用事件在回复之前的回调
$handler = new AnnotationHandler(BotAction::class);
container()->set(Action::class, $a);
$handler->setRuleCallback(fn (BotAction $act) => $act->action === '' || $act->action === $action && !$act->need_response);
$handler->handleAll($a);
// 被阻断时候,就不发送了
if ($handler->getStatus() === AnnotationHandler::STATUS_INTERRUPTED) {
return false;
}
// 调用机器人连接发送 Action
if ($this->base_event instanceof WebSocketMessageEvent) {
$result = $this->base_event->send(json_encode($a->jsonSerialize()));
}
if (!isset($result) && container()->has('ws.message.event')) {
$result = container()->get('ws.message.event')->send(json_encode($a->jsonSerialize()));
}
// 如果是 HTTP WebHook 的形式,那么直接调用 Response
if (!isset($result) && $this->base_event instanceof HttpRequestEvent) {
$response = HttpFactory::createResponse(headers: ['Content-Type' => 'application/json'], body: json_encode([$a->jsonSerialize()]));
$this->base_event->withResponse($response);
$result = true;
}
if (!isset($result) && container()->has('http.request.event')) {
$response = HttpFactory::createResponse(headers: ['Content-Type' => 'application/json'], body: json_encode([$a->jsonSerialize()]));
container()->get('http.request.event')->withResponse($response);
$result = true;
}
if (isset($result)) {
return $result;
}
/* TODO: 协程支持
if (($result ?? false) === true && ($co = Adaptive::getCoroutine()) !== null) {
return $result ?? false;
}*/
throw new OneBot12Exception('No bot connection found.');
}
}

View File

@@ -8,7 +8,9 @@ class ZMUtil
{ {
/** /**
* 获取 composer.json 并转为数组进行读取使用 * 获取 composer.json 并转为数组进行读取使用
* @param null|string $path 路径 *
* @param null|string $path 路径
* @throws \JsonException
*/ */
public static function getComposerMetadata(?string $path = null): ?array public static function getComposerMetadata(?string $path = null): ?array
{ {

View File

@@ -12,11 +12,14 @@ use ZM\Plugin\ZMPlugin;
class ZMApplication extends ZMPlugin class ZMApplication extends ZMPlugin
{ {
/** @var null|ZMApplication 存储单例类的变量 */ /** @var null|ZMApplication 存储单例类的变量 */
private static ?ZMApplication $obj; private static ?ZMApplication $obj = null;
/** @var array 存储要传入的args */ /** @var array 存储要传入的args */
private array $args = []; private array $args = [];
/**
* @throws SingletonViolationException
*/
public function __construct(mixed $dir = null) public function __construct(mixed $dir = null)
{ {
if (self::$obj !== null) { if (self::$obj !== null) {