aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/HydroRollCore/rule.py
diff options
context:
space:
mode:
author简律纯 <i@jyunko.cn>2023-07-30 13:46:16 +0800
committer简律纯 <i@jyunko.cn>2023-07-30 13:46:16 +0800
commit0b71a030e3cc5cf9f02491e0839bebebc5723ec6 (patch)
tree24e7398722cb4861fa966b9849609a14b4a6bb72 /HydroRollCore/rule.py
parent4d6945488f6ddc052b02eeef3075faf00a9481d7 (diff)
downloadinfini-0b71a030e3cc5cf9f02491e0839bebebc5723ec6.tar.gz
infini-0b71a030e3cc5cf9f02491e0839bebebc5723ec6.zip
feat: 添加泛型
Diffstat (limited to 'HydroRollCore/rule.py')
-rw-r--r--HydroRollCore/rule.py141
1 files changed, 111 insertions, 30 deletions
diff --git a/HydroRollCore/rule.py b/HydroRollCore/rule.py
index bdc24369..8a72c8c6 100644
--- a/HydroRollCore/rule.py
+++ b/HydroRollCore/rule.py
@@ -1,30 +1,111 @@
-import os
-import importlib.util
-
-__all__ = ["Rule"]
-
-class Rule:
- def __init__(self, folder_path):
- self.folder_path = folder_path
-
- def load_modules(self):
- # 获取指定文件夹下的所有文件和文件夹
- file_list = os.listdir(self.folder_path)
- module_list = []
-
- # 遍历文件列表
- for file_name in file_list:
- file_path = os.path.join(self.folder_path, file_name)
-
- # 判断是否为Python文件或者包
- if file_name.startswith('_') or not file_name.endswith(".py"):
- continue
-
- # 尝试加载模块
- module_name = os.path.splitext(file_name)[0]
- spec = importlib.util.spec_from_file_location(module_name, file_path)
- module = importlib.util.module_from_spec(spec)
- spec.loader.exec_module(module)
- module_list.append(module)
-
- return module_list
+"""iamai 插件。
+
+所有 iamai 插件的基类。所有用户编写的插件必须继承自 `Plugin` 类。
+"""
+from enum import Enum
+from abc import ABC, abstractmethod
+from typing import TYPE_CHECKING, Type, Generic, NoReturn, Optional
+
+from hydrorollcore.config import ConfigModel
+from hydrorollcore.utils import is_config_class
+from hydrorollcore.typing import T_Event, T_State, T_Config
+from hydrorollcore.exceptions import SkipException, StopException
+
+if TYPE_CHECKING:
+ from iamai.bot import Bot
+
+__all__ = ["Rule", "RuleLoadType"]
+
+
+class RuleLoadType(Enum):
+ """插件加载类型。"""
+
+ DIR = "dir"
+ NAME = "name"
+ FILE = "file"
+ CLASS = "class"
+
+
+class Rule(ABC, Generic[T_Event, T_State, T_Config]):
+ """所有 iamai 插件的基类。
+
+ Attributes:
+ event: 当前正在被此插件处理的事件。
+ priority: 插件的优先级,数字越小表示优先级越高,默认为 0。
+ block: 插件执行结束后是否阻止事件的传播。True 表示阻止。
+ __plugin_load_type__: 插件加载类型,由 iamai 自动设置,反映了此插件是如何被加载的。
+ __plugin_file_path__: 当插件加载类型为 `PluginLoadType.CLASS` 时为 `None`,
+ 否则为定义插件在的 Python 模块的位置。
+ """
+
+ event: T_Event
+ priority: int = 0
+ block: bool = False
+ Config: Type[ConfigModel]
+
+ __plugin_load_type__: PluginLoadType
+ __plugin_file_path__: Optional[str]
+
+ def __init__(self, event: T_Event):
+ self.event = event
+
+ if not hasattr(self, "priority"):
+ self.priority = 0
+ if not hasattr(self, "block"):
+ self.block = False
+
+ self.get = self.bot.get
+
+ self.__post_init__()
+
+ def __post_init__(self):
+ """用于初始化后处理,被 `__init__()` 方法调用。"""
+ pass
+
+ @property
+ def name(self) -> str:
+ """插件类名称。"""
+ return self.__class__.__name__
+
+ @property
+ def bot(self) -> "Bot":
+ """机器人对象。"""
+ return self.event.adapter.bot
+
+ @property
+ def config(self) -> Optional[T_Config]:
+ """插件配置。"""
+ config_class: ConfigModel = getattr(self, "Config", None)
+ if is_config_class(config_class):
+ return getattr(self.bot.config.plugin, config_class.__config_name__, None)
+ return None
+
+ def stop(self) -> NoReturn:
+ """停止当前事件传播。"""
+ raise StopException()
+
+ def skip(self) -> NoReturn:
+ """跳过自身继续当前事件传播。"""
+ raise SkipException()
+
+ @property
+ def state(self) -> T_State:
+ """插件状态。"""
+ return self.bot.plugin_state[self.name]
+
+ @state.setter
+ def state(self, value: T_State):
+ self.bot.plugin_state[self.name] = value
+
+ @abstractmethod
+ async def handle(self) -> None:
+ """处理事件的方法。当 `rule()` 方法返回 `True` 时 iamai 会调用此方法。每个插件必须实现此方法。"""
+ raise NotImplementedError
+
+ @abstractmethod
+ async def rule(self) -> bool:
+ """匹配事件的方法。事件处理时,会按照插件的优先级依次调用此方法,当此方法返回 `True` 时将事件交由此插件处理。每个插件必须实现此方法。
+
+ 注意:不建议直接在此方法内实现对事件的处理,事件的具体处理请交由 `handle()` 方法。
+ """
+ raise NotImplementedError \ No newline at end of file