"""命令监听处理器:匹配 #命令名+空格 格式的消息,转发到外部回调 URL。""" import re import aiohttp from ..config import COMMAND_CALLBACK_URL, COMMAND_LENGTH, COMMAND_PREFIX from ..response import error, ok def build_command_pattern() -> re.Pattern: """构建命令匹配正则:# + N个中文字 + 空格。""" return re.compile( rf"^{re.escape(COMMAND_PREFIX)}([\u4e00-\u9fff]{{{COMMAND_LENGTH}}})\s+(.+)", re.DOTALL, ) COMMAND_PATTERN = build_command_pattern() def parse_command(raw_message: str) -> dict | None: """解析消息,匹配命令模式。返回 {command, content, raw_message} 或 None。""" match = COMMAND_PATTERN.match(raw_message.strip()) if not match: return None return { "command": match.group(1), "content": match.group(2).strip(), "raw_message": raw_message.strip(), } async def send_command_callback(data: dict, logger) -> bool: """将命令数据 POST 到外部回调 URL。返回是否成功。""" if not COMMAND_CALLBACK_URL: logger.warning("COMMAND_CALLBACK_URL 未配置,跳过命令回调") return False try: async with aiohttp.ClientSession() as session: async with session.post( COMMAND_CALLBACK_URL, json=data, timeout=aiohttp.ClientTimeout(total=10), ) as resp: if resp.status >= 400: body = await resp.text() logger.error( "命令回调失败: status=%d url=%s body=%s", resp.status, COMMAND_CALLBACK_URL, body[:200], ) return False return True except Exception as exc: logger.error("命令回调异常: url=%s error=%s", COMMAND_CALLBACK_URL, exc) return False