From 63fda21cf745d0bfc7e3c72f3d525910f299cf3d Mon Sep 17 00:00:00 2001 From: RF-Tar-Railt Date: Tue, 28 Jan 2025 13:27:02 +0800 Subject: [PATCH] :sparkles: several event for command --- arclet/entari/command/provider.py | 49 ++++++++++++++++++++++++++----- arclet/entari/event/command.py | 43 ++++++++++++++++++++++++++- arclet/entari/session.py | 17 +++++++---- pdm.lock | 6 ++-- 4 files changed, 98 insertions(+), 17 deletions(-) diff --git a/arclet/entari/command/provider.py b/arclet/entari/command/provider.py index de73701..3c02f3f 100644 --- a/arclet/entari/command/provider.py +++ b/arclet/entari/command/provider.py @@ -3,7 +3,8 @@ from arclet.alconna import Alconna, Arparma, Duplication, Empty, output_manager from arclet.alconna.builtin import generate_duplication -from arclet.letoderea import STOP, Contexts, Param, Propagator, Provider +from arclet.alconna.exceptions import SpecialOptionTriggered +from arclet.letoderea import STOP, Contexts, Param, Propagator, Provider, post from arclet.letoderea.exceptions import ProviderUnsatisfied from arclet.letoderea.provider import ProviderFactory from nepattern.util import CUnionType @@ -11,6 +12,8 @@ from tarina.generic import get_origin from ..config import EntariConfig +from ..event.base import Reply +from ..event.command import CommandOutput, CommandParse, CommandReceive from ..message import MessageChain from ..session import Session from .model import CommandResult, Match, Query @@ -58,25 +61,55 @@ class AlconnaSuppiler(Propagator): def __init__(self, cmd: Alconna): self.cmd = cmd - async def supply(self, message: MessageChain, session: Optional[Session] = None): + async def before_supply( + self, message: MessageChain, session: Optional[Session] = None, reply: Optional[Reply] = None + ): + if session and (recv := await post(CommandReceive(session, self.cmd, message, reply))): + message = recv.value.copy() + return {"_message": message} + + async def supply(self, ctx: Contexts): + _message: MessageChain = ctx.pop("_message") with output_manager.capture(self.cmd.name) as cap: output_manager.set_action(lambda x: x, self.cmd.name) try: - _res = self.cmd.parse(message) + _res = self.cmd.parse(_message) except Exception as e: - _res = Arparma(self.cmd._hash, message, False, error_info=e) + _res = Arparma(self.cmd._hash, _message, False, error_info=e) may_help_text: Optional[str] = cap.get("output", None) + return {"_result": CommandResult(self.cmd, _res, may_help_text)} + + async def after_supply(self, ctx: Contexts, session: Optional[Session] = None): + alc_result: CommandResult = ctx.pop("_result") + _res = alc_result.result + if session and (pres := await post(CommandParse(session, self.cmd, _res))): + if isinstance(pres.value, Arparma): + _res = pres.value + elif not pres.value: + return STOP if _res.matched: - return {"alc_result": CommandResult(self.cmd, _res, may_help_text)} - if may_help_text: + return {"alc_result": CommandResult(self.cmd, _res, alc_result.output)} + if alc_result.output: if session: - await session.send(MessageChain(may_help_text)) + _t = str(_res.error_info) if isinstance(_res.error_info, SpecialOptionTriggered) else "error" + if ores := await post(CommandOutput(session, self.cmd, _t, alc_result.output)): + if not ores.value: + return STOP + elif ores.value is True: + msg = MessageChain(alc_result.output) + else: + msg = MessageChain(ores.value) + else: + msg = MessageChain(alc_result.output) + await session.send(msg) return STOP - return {"alc_result": CommandResult(self.cmd, _res, may_help_text)} + return {"alc_result": alc_result} return STOP def compose(self): + yield self.before_supply, True, 65 yield self.supply, True, 70 + yield self.after_supply, True, 75 class AlconnaProvider(Provider[Any]): diff --git a/arclet/entari/event/command.py b/arclet/entari/event/command.py index 61885c2..8052f8e 100644 --- a/arclet/entari/event/command.py +++ b/arclet/entari/event/command.py @@ -1,9 +1,12 @@ from dataclasses import dataclass -from typing import Union +from typing import Optional, Union +from arclet.alconna import Alconna, Arparma from arclet.letoderea import Contexts, Provider, make_event from ..message import MessageChain +from ..session import Session +from .base import Reply @dataclass @@ -22,3 +25,41 @@ async def __call__(self, context: Contexts): return context.get("command") __result_type__: "type[str | MessageChain]" = Union[str, MessageChain] + + +@dataclass +@make_event(name="entari.event/command/output") +class CommandOutput: + """依据输出信息的类型,将字符串转换为消息对象以便发送。""" + + session: Session + command: Alconna + type: str + content: str + + __result_type__: "type[bool | str | MessageChain]" = Union[bool, str, MessageChain] + + +@dataclass +@make_event(name="entari.event/command/before_parse") +class CommandReceive: + """尝试解析命令时调用""" + + session: Session + command: Alconna + content: MessageChain + reply: Optional[Reply] = None + + __result_type__: "type[MessageChain]" = MessageChain + + +@dataclass +@make_event(name="entari.event/command/after_parse") +class CommandParse: + """解析完命令后调用""" + + session: Session + command: Alconna + result: Arparma + + __result_type__: "type[Arparma | bool]" = Union[Arparma, bool] diff --git a/arclet/entari/session.py b/arclet/entari/session.py index 86b8834..b7fcbbc 100644 --- a/arclet/entari/session.py +++ b/arclet/entari/session.py @@ -70,12 +70,13 @@ async def message_create( if source: sess = Session(self.account, source) sess.elements = msg - res = await es.post(SendRequest(self.account, channel_id, msg, sess)) - if res and res.value: - value = res.value - if value is True: + if res := await es.post(SendRequest(self.account, channel_id, msg, sess)): + if not res.value: return [] - msg = value + elif res.value is True: + pass + else: + msg = res.value send = str(msg) res = await self.call_api( Api.MESSAGE_CREATE, @@ -140,6 +141,12 @@ async def waiter(content: MessageChain, session: Session[MessageEvent]): def stop(self) -> NoReturn: raise HandlerStop() + @property + def quote(self): + if isinstance(self.event, MessageEvent): + return self.event.quote + return None + @property def user(self) -> User: if not self.event.user: diff --git a/pdm.lock b/pdm.lock index 848cd13..0044334 100644 --- a/pdm.lock +++ b/pdm.lock @@ -180,7 +180,7 @@ files = [ [[package]] name = "arclet-letoderea" -version = "0.15.0" +version = "0.15.1" requires_python = ">=3.9" summary = "A high-performance, simple-structured event system, relies on asyncio" groups = ["default"] @@ -188,8 +188,8 @@ dependencies = [ "tarina>=0.6.7", ] files = [ - {file = "arclet_letoderea-0.15.0-py3-none-any.whl", hash = "sha256:ce74f602ac0fd6573c0cd686078ae60878e2f4a97e2eda582c351af4ab5b9a4b"}, - {file = "arclet_letoderea-0.15.0.tar.gz", hash = "sha256:33141d60aa147c700ab20d0b620ae49d22f1a3b06f19e32d4d0f01b4b8851156"}, + {file = "arclet_letoderea-0.15.1-py3-none-any.whl", hash = "sha256:29bf647a0669147271e36bdc826dbe42a36034b6a2d150499bb0c28084837304"}, + {file = "arclet_letoderea-0.15.1.tar.gz", hash = "sha256:508ff9a510bc8e3deb8c7990f252bc67861daf3b9ee9be267919beeac03c00fd"}, ] [[package]]