b62b1f3870
Squashed: chore: merge master branch chore: merge from master branch chore: rename updateAllPlatformCompatibility to update_all_platform_compatibility for consistency Reviewed by: @Raven95676 @Soulter
186 lines
6.0 KiB
Python
186 lines
6.0 KiB
Python
from __future__ import annotations
|
|
import enum
|
|
import heapq
|
|
from dataclasses import dataclass, field
|
|
from typing import Awaitable, List, Dict, TypeVar, Generic
|
|
from .filter import HandlerFilter
|
|
from .star import star_map
|
|
|
|
T = TypeVar("T", bound="StarHandlerMetadata")
|
|
|
|
|
|
class StarHandlerRegistry(Generic[T]):
|
|
"""用于存储所有的 Star Handler"""
|
|
|
|
star_handlers_map: Dict[str, StarHandlerMetadata] = {}
|
|
"""用于快速查找。key 是 handler_full_name"""
|
|
_handlers = []
|
|
|
|
def append(self, handler: StarHandlerMetadata):
|
|
"""添加一个 Handler"""
|
|
if "priority" not in handler.extras_configs:
|
|
handler.extras_configs["priority"] = 0
|
|
|
|
heapq.heappush(self._handlers, (-handler.extras_configs["priority"], handler))
|
|
self.star_handlers_map[handler.handler_full_name] = handler
|
|
|
|
def _print_handlers(self):
|
|
"""打印所有的 Handler"""
|
|
for _, handler in self._handlers:
|
|
print(handler.handler_full_name)
|
|
|
|
def get_handlers_by_event_type(
|
|
self, event_type: EventType, only_activated=True, platform_id=None
|
|
) -> List[StarHandlerMetadata]:
|
|
"""通过事件类型获取 Handler
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
only_activated: 是否只返回已激活的插件的处理器
|
|
platform_id: 平台ID,如果提供此参数,将过滤掉在此平台不兼容的处理器
|
|
|
|
Returns:
|
|
List[StarHandlerMetadata]: 处理器列表
|
|
"""
|
|
handlers = []
|
|
for _, handler in self._handlers:
|
|
if handler.event_type != event_type:
|
|
continue
|
|
|
|
# 只激活的插件处理器
|
|
if only_activated:
|
|
plugin = star_map.get(handler.handler_module_path)
|
|
if not (plugin and plugin.activated):
|
|
continue
|
|
|
|
# 平台兼容性过滤
|
|
if platform_id and event_type != EventType.OnAstrBotLoadedEvent:
|
|
if not handler.is_enabled_for_platform(platform_id):
|
|
continue
|
|
|
|
handlers.append(handler)
|
|
|
|
return handlers
|
|
|
|
def get_handler_by_full_name(self, full_name: str) -> StarHandlerMetadata:
|
|
"""通过 Handler 的全名获取 Handler"""
|
|
return self.star_handlers_map.get(full_name, None)
|
|
|
|
def get_handlers_by_module_name(
|
|
self, module_name: str
|
|
) -> List[StarHandlerMetadata]:
|
|
"""通过模块名获取 Handler"""
|
|
return [
|
|
handler
|
|
for _, handler in self._handlers
|
|
if handler.handler_module_path == module_name
|
|
]
|
|
|
|
def clear(self):
|
|
"""清空所有的 Handler"""
|
|
self.star_handlers_map.clear()
|
|
self._handlers.clear()
|
|
|
|
def remove(self, handler: StarHandlerMetadata):
|
|
"""删除一个 Handler"""
|
|
# self._handlers.remove(handler)
|
|
for i, h in enumerate(self._handlers):
|
|
if h[1] == handler:
|
|
self._handlers.pop(i)
|
|
break
|
|
try:
|
|
del self.star_handlers_map[handler.handler_full_name]
|
|
except KeyError:
|
|
pass
|
|
|
|
def __iter__(self):
|
|
"""使 StarHandlerRegistry 支持迭代"""
|
|
return (handler for _, handler in self._handlers)
|
|
|
|
def __len__(self):
|
|
"""返回 Handler 的数量"""
|
|
return len(self._handlers)
|
|
|
|
|
|
star_handlers_registry = StarHandlerRegistry()
|
|
|
|
|
|
class EventType(enum.Enum):
|
|
"""表示一个 AstrBot 内部事件的类型。如适配器消息事件、LLM 请求事件、发送消息前的事件等
|
|
|
|
用于对 Handler 的职能分组。
|
|
"""
|
|
|
|
OnAstrBotLoadedEvent = enum.auto() # AstrBot 加载完成
|
|
|
|
AdapterMessageEvent = enum.auto() # 收到适配器发来的消息
|
|
OnLLMRequestEvent = enum.auto() # 收到 LLM 请求(可以是用户也可以是插件)
|
|
OnLLMResponseEvent = enum.auto() # LLM 响应后
|
|
OnDecoratingResultEvent = enum.auto() # 发送消息前
|
|
OnCallingFuncToolEvent = enum.auto() # 调用函数工具
|
|
OnAfterMessageSentEvent = enum.auto() # 发送消息后
|
|
|
|
|
|
@dataclass
|
|
class StarHandlerMetadata:
|
|
"""描述一个 Star 所注册的某一个 Handler。"""
|
|
|
|
event_type: EventType
|
|
"""Handler 的事件类型"""
|
|
|
|
handler_full_name: str
|
|
'''格式为 f"{handler.__module__}_{handler.__name__}"'''
|
|
|
|
handler_name: str
|
|
"""Handler 的名字,也就是方法名"""
|
|
|
|
handler_module_path: str
|
|
"""Handler 所在的模块路径。"""
|
|
|
|
handler: Awaitable
|
|
"""Handler 的函数对象,应当是一个异步函数"""
|
|
|
|
event_filters: List[HandlerFilter]
|
|
"""一个适配器消息事件过滤器,用于描述这个 Handler 能够处理、应该处理的适配器消息事件"""
|
|
|
|
desc: str = ""
|
|
"""Handler 的描述信息"""
|
|
|
|
extras_configs: dict = field(default_factory=dict)
|
|
"""插件注册的一些其他的信息, 如 priority 等"""
|
|
|
|
def __lt__(self, other: StarHandlerMetadata):
|
|
"""定义小于运算符以支持优先队列"""
|
|
return self.extras_configs.get("priority", 0) < other.extras_configs.get(
|
|
"priority", 0
|
|
)
|
|
|
|
def is_enabled_for_platform(self, platform_id: str) -> bool:
|
|
"""检查插件是否在指定平台启用
|
|
|
|
Args:
|
|
platform_id: 平台ID,这是从event.get_platform_id()获取的,用于唯一标识平台实例
|
|
|
|
Returns:
|
|
bool: 是否启用,True表示启用,False表示禁用
|
|
"""
|
|
plugin = star_map.get(self.handler_module_path)
|
|
|
|
# 如果插件元数据不存在,默认允许执行
|
|
if not plugin or not plugin.name:
|
|
return True
|
|
|
|
# 先检查插件是否被激活
|
|
if not plugin.activated:
|
|
return False
|
|
|
|
# 直接使用StarMetadata中缓存的supported_platforms判断平台兼容性
|
|
if (
|
|
hasattr(plugin, "supported_platforms")
|
|
and platform_id in plugin.supported_platforms
|
|
):
|
|
return plugin.supported_platforms[platform_id]
|
|
|
|
# 如果没有缓存数据,默认允许执行
|
|
return True
|