Files
abot/base/plugin_common/message_plugin_interface.py

134 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Dict, Any, Tuple, Optional, List
from base.plugin_common.plugin_interface import PluginInterface
from wechat_ipad import WechatAPIClient
from utils.robot_cmd.robot_command import Feature
class MessagePluginInterface(PluginInterface):
"""消息处理插件接口"""
@staticmethod
def normalize_message_dispatch_mode(raw_mode: Any) -> str:
"""把插件声明的消息分发模式标准化为 `sync` 或 `background`。
设计说明:
1. `sync` 表示沿用当前主链路同步执行,插件会占用当前消息处理协程直到完成;
2. `background` 表示命中后立即转入后台任务池,主消息链路尽快释放,不再占用前台并发槽位;
3. 这里集中做别名兼容,后续插件只需要写 `background/async/queue` 这类语义值即可。
"""
mode = str(raw_mode or "").strip().lower()
if mode in {"background", "async", "queued", "queue", "detached"}:
return "background"
return "sync"
@property
def command_prefix(self) -> Optional[str]:
"""命令前缀,如 '/'"""
return None
@property
def commands(self) -> List[str]:
"""支持的命令列表"""
return []
@property
def feature_key(self) -> Optional[str]:
"""插件对应的功能权限键名"""
return None
@property
def feature_description(self) -> Optional[str]:
"""插件对应的功能权限描述"""
return None
def register_feature(self) -> Optional[Feature]:
"""注册插件功能权限
Returns:
Feature: 注册的功能权限枚举如果不需要权限则返回None
"""
if self.feature_key and self.feature_description:
return Feature.register_feature(self.feature_key, self.feature_description)
return None
# 需要完成jobs 的业务所以完成bot注入
def set_bot(self, bot: WechatAPIClient) -> None:
self.bot: WechatAPIClient = bot
def can_process(self, message: Dict[str, Any]) -> bool:
"""
检查插件是否可以处理该消息
Args:
message: 消息字典,包含消息的各种属性
Returns:
是否可以处理
"""
# 默认实现:检查是否是命令
if self.command_prefix and self.commands:
content = message.get("content", "")
if content.startswith(self.command_prefix):
command = content[len(self.command_prefix):].split()[0]
return command in self.commands
return False
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""
处理消息
Args:
message: 消息字典,包含消息的各种属性,以及发送消息所需的对象
- wcf: WcfAPI对象可用于发送消息
- message_util: 消息工具类,提供更高级的消息处理功能
Returns:
(是否已处理, 处理结果)
"""
raise NotImplementedError("子类必须实现此方法")
def get_message_dispatch_mode(self, message: Dict[str, Any]) -> str:
"""返回当前消息应采用的执行模式。
默认行为:
1. 优先读取插件自身 `config.toml` 里的 `[runtime] message_dispatch_mode`
2. 若未配置,则回退为 `sync`,保持历史行为不变;
3. 长任务插件如果需要“按命令动态切换前后台”,可以在子类中覆盖本方法。
"""
plugin_config = getattr(self, "_config", {}) or {}
runtime_config = plugin_config.get("runtime", {}) if isinstance(plugin_config, dict) else {}
runtime_config = runtime_config if isinstance(runtime_config, dict) else {}
raw_mode = runtime_config.get("message_dispatch_mode") or runtime_config.get("dispatch_mode") or "sync"
return self.normalize_message_dispatch_mode(raw_mode)
# ---------------- 插件定时调度能力(可选实现) ----------------
def get_schedule_actions(self) -> List[Dict[str, Any]]:
"""返回插件支持的可调度动作定义列表。
每项示例:
{
"action_key": "daily_push",
"name": "每日推送",
"description": "给目标群发送每日内容",
"trigger_type": "at_times",
"trigger_config": {"time_list": ["09:00"]},
"target_scope": "all_enabled_groups",
"target_config": {},
"payload": {},
"default_enabled": False
}
"""
return []
async def run_scheduled_action(self, action_key: str, context: Dict[str, Any]) -> Dict[str, Any]:
"""执行调度动作(插件可覆盖)。
Returns:
dict: {"success": bool, "summary": str, "detail": dict}
"""
return {
"success": False,
"summary": f"插件未实现调度动作: {action_key}",
"detail": {"action_key": action_key},
}