From 127772756d7ba2b8213972b57541a0f5bd39e4c1 Mon Sep 17 00:00:00 2001 From: Wbucket <2595141012@stu.hqu.edu.cn> Date: Fri, 6 Nov 2026 23:24:13 +0800 Subject: [PATCH] feat:doc --- main.py | 44 +++++++++++++++++++++++++++++-------- service/timer.py | 46 +++++++++++++++++++++++++++++++++++++++ tool/pattern.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 service/timer.py create mode 100644 tool/pattern.py diff --git a/main.py b/main.py index 819a756..c7acd1a 100644 --- a/main.py +++ b/main.py @@ -1,25 +1,51 @@ from astrbot.api.event import filter, AstrMessageEvent, MessageEventResult + from astrbot.api.star import Context, Star, register from astrbot.api import logger -from astrbot.api.provider import ProviderRequest +from astrbot.api.provider import (ProviderRequest,LLMResponse ) +from astrbot.core.agent.message import TextPart +from .service.timer import TimerService -@register("helloworld", "YourName", "一个简单的 Hello World 插件", "1.0.0") + +@register("wait_msg", "Wbucket", "一个简单的 llm等待回复插件", "0.0.1") class MyPlugin(Star): def __init__(self, context: Context): super().__init__(context) + self.Timer = TimerService(self) + async def initialize(self): """可选择实现异步的插件初始化方法,当实例化该插件类之后会自动调用该方法。""" - # 注册指令的装饰器。指令名为 helloworld。注册成功后,发送 `/helloworld` 就会触发这个指令,并回复 `你好, {user_name}!` + # 注册指令的装饰器 @filter.on_llm_request() - async def helloworld(self, event: AstrMessageEvent,req : ProviderRequest): + async def content_inject(self, event: AstrMessageEvent,req : ProviderRequest): """这是一个 hello world 指令""" # 这是 handler 的描述,将会被解析方便用户了解插件内容。建议填写。 - logger.info("系统提示词:",req.system_prompt) - - @filter.event_message_type(filter.EventMessageType.PRIVATE_MESSAGE) - async def awa(self,event:AstrMessageEvent): - yield event.plain_result(event.get_message_str()) + # logger.info("系统提示词:"+req.system_prompt) + req.extra_user_content_parts.append(TextPart( + text=( + "-----wt使用----" + "在回复内容中加入n模板输入想要等待的时间,n=等待秒数\n" + "最短10s最长30min(1800s),不添加则正常回复(只有对方回复你才会被唤醒)\n" + "例如'15'-->等待15秒后再次唤醒.\n" + "使用场景:希望对方在多久之后能回你,或者希望这个话题能在短期内继续而不是因为对方的不回复就夭折\n" + "例如如下场景:\n" + "--\n" + "assistant:'你觉得咸粽子好吃还是甜粽子好吃?40'\n" + "(系统时间:四十秒后,系统定时唤醒)\n" + "user:'40s过去了,对方无回应'\n" + "assistant:'你怎么不理我40'\n" + "(系统时间:二十秒后,用户回复,定时任务取消)\n" + "user:'抱歉啊刚看到,我觉得咸的好吃awa'\n" + "每主动发出消息建议带上wt标签,标签必须闭合且只包裹你要等待的秒数。\n" + "如果话题完结了,不想再无意义被唤醒,或者回复完毕别人的问题还没被追问的时候则不必再加。自己看着决定即可。\n" + "-------" + ) + )) + @filter.on_decorating_result() + async def pattern_extract(self,event:AstrMessageEvent): + self.Timer.parse(event) + async def terminate(self): """可选择实现异步的插件销毁方法,当插件被卸载/停用时会调用。""" diff --git a/service/timer.py b/service/timer.py new file mode 100644 index 0000000..0414c92 --- /dev/null +++ b/service/timer.py @@ -0,0 +1,46 @@ +from astrbot.api.event import AstrMessageEvent +from astrbot.api.provider import LLMResponse +from astrbot.api import logger +from astrbot.core.message.message_event_result import MessageChain,Plain +from ..tool.pattern import Pattern +from astrbot.api.star import Star +import asyncio + +class TimerService: + def __init__(self,star:Star) -> None: + self.star = star + pass + + # 解析模板并进行定时 + def parse(self,event:AstrMessageEvent): + res = event.get_result() + if not res: + logger.info("[wait_msg]:解析失败:没拿到消息链") + return + + Second:int|None = None + logger.info("[wait_msg]:开始解析模板") + + for index,i in enumerate(res.chain) : + logger.info(f"获得消息链类型:{i.type}内容:{i}") + if not isinstance(i,Plain) or not i.type == "Plain": + continue + dump = Pattern(i.text) + i.text = dump.string + Second = dump.count + # 改变信息 + res.chain[index] = i + + event.set_result(res) + if not Second is None: + self.timer(event,Second) + return + + + # 定时: + def timer(self,event:AstrMessageEvent,Sec:int): + asyncio.create_task(self.timer_task()) + + async def timer_task(self): + await asyncio.sleep(1) + logger.warning("awa现在过去一秒了哦") \ No newline at end of file diff --git a/tool/pattern.py b/tool/pattern.py new file mode 100644 index 0000000..6e6526a --- /dev/null +++ b/tool/pattern.py @@ -0,0 +1,56 @@ +import re +from astrbot.api import logger + +# 输入内容,获取过滤后的字符串与定时秒数 +class Pattern: + _pattern = r'((?!wt).)*' + + _MAX_SEC = 1800 + _MIN_SEC = 10 + # 定义最大与最小的范围,固定输入的规范 + def __init__(self,o_str:str) -> None: + logger.debug(f"模板消息:{o_str}") + res = self.extract(o_str) + self.count:int|None = res['second'] + self.string:str = res["content"] + + + def sec_range(self,i)->int: + if i > Pattern._MAX_SEC: + return Pattern._MAX_SEC + if i < Pattern._MIN_SEC : + return Pattern._MIN_SEC + return i + + + def load(self,pattern_str:str)->int|None: + content = pattern_str.strip().removeprefix("").removesuffix("").strip() + + try: + num = int(content) + return self.sec_range(num) + except: + logger.warning ("模板内容错误:{}".format(content)) + return None + + def extract(self,o_str:str): + # 多次匹配防止重复模板 + timerSec :None|int = None + res=re.finditer(Pattern._pattern,o_str) + for i in res : + # 对结果和源字符串处理 + o_str = o_str.replace(i.group(),"",1) + num = self.load(i.group()) + logger.info("获得模板:{0}".format(i.group())) + + if num and not timerSec: + timerSec = num + #消除不完整/非法模板 + o_str= o_str.replace("","") + o_str=o_str.replace("","") + logger.info(f"过滤后消息:{o_str}") + + return { + "content":o_str, + "second":timerSec + }