✨ feat: 支持当消息只有@bot时,下一条发送人的消息直接唤醒机器人
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。
|
||||
"""
|
||||
|
||||
VERSION = "3.4.35"
|
||||
VERSION = "3.4.36"
|
||||
DB_PATH = "data/data_v3.db"
|
||||
|
||||
# 默认配置
|
||||
@@ -36,6 +36,7 @@ DEFAULT_CONFIG = {
|
||||
"content_cleanup_rule": "",
|
||||
},
|
||||
"no_permission_reply": True,
|
||||
"empty_mention_waiting": True,
|
||||
},
|
||||
"provider": [],
|
||||
"provider_settings": {
|
||||
@@ -257,6 +258,11 @@ CONFIG_METADATA_2 = {
|
||||
"type": "bool",
|
||||
"hint": "启用后,当用户没有权限执行某个操作时,机器人会回复一条消息。",
|
||||
},
|
||||
"empty_mention_waiting": {
|
||||
"description": "只 @ 机器人是否触发等待回复",
|
||||
"type": "bool",
|
||||
"hint": "启用后,当消息内容只有 @ 机器人时,会触发等待回复,在 60 秒内的该用户的任意一条消息均会唤醒机器人。这在某些平台不支持 @ 和语音/图片等消息同时发送时特别有用。",
|
||||
},
|
||||
"segmented_reply": {
|
||||
"description": "分段回复",
|
||||
"type": "object",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import abc
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from .astrbot_message import AstrBotMessage
|
||||
from .platform_metadata import PlatformMetadata
|
||||
@@ -196,7 +197,7 @@ class AstrMessageEvent(abc.ABC):
|
||||
"""
|
||||
发送消息到消息平台。
|
||||
"""
|
||||
await Metric.upload(msg_event_tick=1, adapter_name=self.platform_meta.name)
|
||||
asyncio.create_task(Metric.upload(msg_event_tick=1, adapter_name=self.platform_meta.name))
|
||||
self._has_send_oper = True
|
||||
|
||||
async def _pre_send(self):
|
||||
|
||||
@@ -141,7 +141,8 @@ class TelegramPlatformAdapter(Platform):
|
||||
+ plain_text[entity.offset + entity.length :]
|
||||
)
|
||||
|
||||
message.message.append(Plain(plain_text))
|
||||
if plain_text:
|
||||
message.message.append(Plain(plain_text))
|
||||
message.message_str = plain_text
|
||||
|
||||
if message.message_str == "/start":
|
||||
|
||||
@@ -139,13 +139,10 @@ class SessionWaiter:
|
||||
session.session_controller.stop(e)
|
||||
|
||||
|
||||
def session_waiter(
|
||||
session_id_param: str, timeout: int = 30, record_history_chains: bool = False
|
||||
):
|
||||
def session_waiter(timeout: int = 30, record_history_chains: bool = False):
|
||||
"""
|
||||
装饰器:自动将函数注册为 SessionWaiter 处理函数,并等待外部输入触发执行。
|
||||
|
||||
:param session_id_param: 用于从参数中获取 session_id 的参数名称
|
||||
:param timeout: 超时时间(秒)
|
||||
:param record_history_chain: 是否自动记录历史消息链。可以通过 controller.get_history_chains() 获取。深拷贝。
|
||||
"""
|
||||
@@ -153,9 +150,9 @@ def session_waiter(
|
||||
def decorator(func: Callable[[str], Awaitable[Any]]):
|
||||
@functools.wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
session_id = kwargs.get(session_id_param)
|
||||
session_id = kwargs.get("session_id", None)
|
||||
if not session_id:
|
||||
raise ValueError(f"缺少 session_id 参数 '{session_id_param}'")
|
||||
raise ValueError("缺少 session_id 参数")
|
||||
|
||||
waiter = SessionWaiter(session_id, record_history_chains)
|
||||
return await waiter.register_wait(func, timeout)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# What's Changed
|
||||
|
||||
1. ✨ 新增: 支持插件会话控制 API
|
||||
2. ✨ 新增: add template of LMStudio #691
|
||||
3. ⚡ 优化: Webchat 和 Gewechat 的图片、语音等主动消息发送 #710
|
||||
4. 🐛 修复: 404 error after installing plugins
|
||||
5. 🐛 修复: telegram cannot handle /start #620
|
||||
6. 🐛 修复: 修复插件在带了 __del__ 之后无法被禁用和重载的问题
|
||||
7. 🐛 修复: context.get_platform() error
|
||||
8. 🐛 修复: Telegram 适配器使用代理地址无法获取图片 #723
|
||||
@@ -267,10 +267,14 @@ UID: {user_id} 此 ID 可用于设置管理员。/op <UID> 授权管理员, /deo
|
||||
|
||||
@filter.permission_type(filter.PermissionType.ADMIN)
|
||||
@filter.command("op")
|
||||
async def op(self, event: AstrMessageEvent, admin_id: str=None):
|
||||
async def op(self, event: AstrMessageEvent, admin_id: str = None):
|
||||
"""授权管理员。op <admin_id>"""
|
||||
if admin_id is None:
|
||||
event.set_result(MessageEventResult().message("使用方法: /op <id> 授权管理员;/deop <id> 取消管理员。可通过 /sid 获取 ID。"))
|
||||
event.set_result(
|
||||
MessageEventResult().message(
|
||||
"使用方法: /op <id> 授权管理员;/deop <id> 取消管理员。可通过 /sid 获取 ID。"
|
||||
)
|
||||
)
|
||||
return
|
||||
self.context.get_config()["admins_id"].append(admin_id)
|
||||
self.context.get_config().save_config()
|
||||
@@ -291,10 +295,14 @@ UID: {user_id} 此 ID 可用于设置管理员。/op <UID> 授权管理员, /deo
|
||||
|
||||
@filter.permission_type(filter.PermissionType.ADMIN)
|
||||
@filter.command("wl")
|
||||
async def wl(self, event: AstrMessageEvent, sid: str=None):
|
||||
async def wl(self, event: AstrMessageEvent, sid: str = None):
|
||||
"""添加白名单。wl <sid>"""
|
||||
if sid is None:
|
||||
event.set_result(MessageEventResult().message("使用方法: /wl <id> 添加白名单;/dwl <id> 删除白名单。可通过 /sid 获取 ID。"))
|
||||
event.set_result(
|
||||
MessageEventResult().message(
|
||||
"使用方法: /wl <id> 添加白名单;/dwl <id> 删除白名单。可通过 /sid 获取 ID。"
|
||||
)
|
||||
)
|
||||
self.context.get_config()["platform_settings"]["id_whitelist"].append(sid)
|
||||
self.context.get_config().save_config()
|
||||
event.set_result(MessageEventResult().message("添加白名单成功。"))
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import astrbot.api.message_components as Comp
|
||||
import copy
|
||||
from astrbot.api import logger
|
||||
from astrbot.api.event import AstrMessageEvent, filter
|
||||
from astrbot.api.star import Context, Star, register
|
||||
from astrbot.core.utils.session_waiter import SessionWaiter, USER_SESSIONS
|
||||
from astrbot.core.utils.session_waiter import (
|
||||
SessionWaiter,
|
||||
USER_SESSIONS,
|
||||
session_waiter,
|
||||
SessionController,
|
||||
)
|
||||
from sys import maxsize
|
||||
|
||||
|
||||
@@ -17,9 +25,59 @@ class Waiter(Star):
|
||||
def __init__(self, context: Context):
|
||||
super().__init__(context)
|
||||
|
||||
self.empty_mention_waiting = self.context.get_config()["platform_settings"][
|
||||
"empty_mention_waiting"
|
||||
]
|
||||
self.wake_prefix = self.context.get_config()["wake_prefix"]
|
||||
|
||||
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize)
|
||||
async def handle_session_control_agent(self, event: AstrMessageEvent):
|
||||
session_id = event.unified_msg_origin
|
||||
"""会话控制代理"""
|
||||
session_id = event.get_sender_id()
|
||||
if session_id in USER_SESSIONS:
|
||||
await SessionWaiter.trigger(session_id, event)
|
||||
event.stop_event()
|
||||
|
||||
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize - 1)
|
||||
async def handle_empty_mention(self, event: AstrMessageEvent):
|
||||
"""实现了对只有一个 @ 的消息内容的处理"""
|
||||
try:
|
||||
messages = event.get_messages()
|
||||
if len(messages) == 1:
|
||||
if (
|
||||
isinstance(messages[0], Comp.At)
|
||||
and str(messages[0].qq) == str(event.get_self_id())
|
||||
and self.empty_mention_waiting
|
||||
) or (
|
||||
isinstance(messages[0], Comp.Plain)
|
||||
and messages[0].text.strip() in self.wake_prefix
|
||||
):
|
||||
yield event.plain_result("想要问什么呢?😄")
|
||||
|
||||
@session_waiter(60)
|
||||
async def empty_mention_waiter(
|
||||
controller: SessionController, event: AstrMessageEvent
|
||||
):
|
||||
logger.info("empty_mention_waiter")
|
||||
event.message_obj.message.insert(
|
||||
0, Comp.At(qq=event.get_self_id(), name=event.get_self_id())
|
||||
)
|
||||
new_event = copy.copy(event)
|
||||
self.context.get_event_queue().put_nowait(
|
||||
new_event
|
||||
) # 重新推入事件队列
|
||||
event.stop_event()
|
||||
controller.stop()
|
||||
|
||||
try:
|
||||
await empty_mention_waiter(
|
||||
event, session_id=event.get_sender_id()
|
||||
)
|
||||
except TimeoutError as _:
|
||||
yield event.plain_result("如果需要帮助,请再次 @ 我哦~")
|
||||
except Exception as e:
|
||||
yield event.plain_result("发生错误,请联系管理员: " + str(e))
|
||||
finally:
|
||||
event.stop_event()
|
||||
except Exception as e:
|
||||
logger.error("handle_empty_mention error: " + str(e))
|
||||
|
||||
Reference in New Issue
Block a user