diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index da72ca0c..673e2d0c 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -88,21 +88,13 @@ module.exports = context => ({ title: "nonebot 模块", path: "nonebot" }, - { - title: "nonebot.typing 模块", - path: "typing" - }, { title: "nonebot.config 模块", path: "config" }, { - title: "nonebot.sched 模块", - path: "sched" - }, - { - title: "nonebot.log 模块", - path: "log" + title: "nonebot.matcher 模块", + path: "matcher" }, { title: "nonebot.rule 模块", @@ -112,10 +104,22 @@ module.exports = context => ({ title: "nonebot.permission 模块", path: "permission" }, + { + title: "nonebot.sched 模块", + path: "sched" + }, + { + title: "nonebot.log 模块", + path: "log" + }, { title: "nonebot.utils 模块", path: "utils" }, + { + title: "nonebot.typing 模块", + path: "typing" + }, { title: "nonebot.exception 模块", path: "exception" diff --git a/docs/api/README.md b/docs/api/README.md index 1c8acf1b..252513d8 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -7,16 +7,10 @@ * [nonebot](nonebot.html) - * [nonebot.typing](typing.html) - - * [nonebot.config](config.html) - * [nonebot.sched](sched.html) - - - * [nonebot.log](log.html) + * [nonebot.matcher](matcher.html) * [nonebot.rule](rule.html) @@ -25,10 +19,22 @@ * [nonebot.permission](permission.html) + * [nonebot.sched](sched.html) + + + * [nonebot.log](log.html) + + * [nonebot.utils](utils.html) + * [nonebot.typing](typing.html) + + * [nonebot.exception](exception.html) + * [nonebot.adapters](adapters/) + + * [nonebot.adapters.cqhttp](adapters/cqhttp.html) diff --git a/docs/api/adapters/cqhttp.md b/docs/api/adapters/cqhttp.md index 53fa04f9..aae78f86 100644 --- a/docs/api/adapters/cqhttp.md +++ b/docs/api/adapters/cqhttp.md @@ -323,10 +323,10 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent) ### _property_ `sub_type` -* 类型: `str` +* 类型: `Optional[str]` -* 说明: 事件类型 +* 说明: 事件子类型 ### _property_ `user_id` diff --git a/docs/api/matcher.md b/docs/api/matcher.md new file mode 100644 index 00000000..d0f5199d --- /dev/null +++ b/docs/api/matcher.md @@ -0,0 +1,328 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.matcher 模块 + +## 事件响应器 + +该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。 + + +## `matchers` + + +* **类型** + + `Dict[int, List[Type[Matcher]]]` + + + +* **说明** + + 用于存储当前所有的事件响应器 + + + +## _class_ `Matcher` + +基类:`object` + +事件响应器类 + + +### `module` + + +* **类型** + + `Optional[str]` + + + +* **说明** + + 事件响应器所在模块名称 + + + +### `type` + + +* **类型** + + `str` + + + +* **说明** + + 事件响应器类型 + + + +### `rule` + + +* **类型** + + `Rule` + + + +* **说明** + + 事件响应器匹配规则 + + + +### `permission` + + +* **类型** + + `Permission` + + + +* **说明** + + 事件响应器触发权限 + + + +### `priority` + + +* **类型** + + `int` + + + +* **说明** + + 事件响应器优先级 + + + +### `block` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否阻止事件传播 + + + +### `temp` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否为临时 + + + +### `expire_time` + + +* **类型** + + `Optional[datetime]` + + + +* **说明** + + 事件响应器过期时间点 + + + +### `_default_state` + + +* **类型** + + `dict` + + + +* **说明** + + 事件响应器默认状态 + + + +### `_default_parser` + + +* **类型** + + `Optional[ArgsParser]` + + + +* **说明** + + 事件响应器默认参数解析函数 + + + +### `handlers` + + +* **类型** + + `List[Handler]` + + + +* **说明** + + 事件响应器拥有的事件处理函数列表 + + + +### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 创建一个新的事件响应器,并存储至 [matchers](#matchers) + + + +* **参数** + + + * `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意 + + + * `rule: Optional[Rule]`: 匹配规则 + + + * `permission: Optional[Permission]`: 权限 + + + * `handlers: Optional[List[Handler]]`: 事件处理函数列表 + + + * `temp: bool`: 是否为临时事件响应器,即触发一次后删除 + + + * `priority: int`: 响应优先级 + + + * `block: bool`: 是否阻止事件向更低优先级的响应器传播 + + + * `module: Optional[str]`: 事件响应器所在模块名称 + + + * `default_state: Optional[dict]`: 默认状态 `state` + + + * `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除 + + + +* **返回** + + + * `Type[Matcher]`: 新的事件响应器类 + + + +### _async classmethod_ `check_perm(bot, event)` + + +* **说明** + + 检查是否满足触发权限 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + +* **返回** + + + * `bool`: 是否满足权限 + + + +### _async classmethod_ `check_rule(bot, event, state)` + + +* **说明** + + 检查是否满足匹配规则 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + * `state: dict`: 当前状态 + + + +* **返回** + + + * `bool`: 是否满足匹配规则 + + + +### _classmethod_ `args_parser(func)` + + +* **说明** + + 用于装饰一个函数来更改当前事件响应器的默认参数解析函数 + + + +* **参数** + + + * `func: ArgsParser`: 参数解析函数 + + + +### _classmethod_ `handle()` + +直接处理消息事件 + + +### _classmethod_ `receive()` + +接收一条新消息并处理 diff --git a/docs/api/rule.md b/docs/api/rule.md index 269abc57..2054d04b 100644 --- a/docs/api/rule.md +++ b/docs/api/rule.md @@ -7,10 +7,10 @@ sidebarDepth: 0 ## 规则 -每个 `Matcher` 拥有一个 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 +每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 :::tip 提示 -`RuleChecker` 既可以是 async function 也可以是 sync function +`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function ::: @@ -120,3 +120,83 @@ Rule(async_function, run_sync(sync_function)) * `msg: str`: 消息结尾字符串 + + + +## `keyword(msg)` + + +* **说明** + + 匹配消息关键词 + + + +* **参数** + + + * `msg: str`: 关键词 + + + +## `command(command)` + + +* **说明** + + 命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。 + + + +* **参数** + + + * `command: Tuples[str, ...]`: 命令内容 + + + +* **示例** + + 使用默认 `command_start`, `command_sep` 配置 + + 命令 `("test",)` 可以匹配:`/test` 开头的消息 + 命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息 + + +:::tip 提示 +命令内容与后续消息间无需空格! +::: + + +## `regex(regex, flags=0)` + + +* **说明** + + 根据正则表达式进行匹配 + + + +* **参数** + + + * `regex: str`: 正则表达式 + + + * `flags: Union[int, re.RegexFlag]`: 正则标志 + + + +## `to_me()` + + +* **说明** + + 通过 `event.to_me` 判断消息是否是发送给机器人 + + + +* **参数** + + + * 无 diff --git a/docs_build/README.rst b/docs_build/README.rst index 97f45a20..9ce6ced7 100644 --- a/docs_build/README.rst +++ b/docs_build/README.rst @@ -3,12 +3,14 @@ NoneBot Api Reference :模块索引: - `nonebot `_ - - `nonebot.typing `_ - `nonebot.config `_ - - `nonebot.sched `_ - - `nonebot.log `_ + - `nonebot.matcher `_ - `nonebot.rule `_ - `nonebot.permission `_ + - `nonebot.sched `_ + - `nonebot.log `_ - `nonebot.utils `_ + - `nonebot.typing `_ - `nonebot.exception `_ + - `nonebot.adapters `_ - `nonebot.adapters.cqhttp `_ diff --git a/docs_build/adapters/README.rst b/docs_build/adapters/README.rst index a8707ba0..e6e0d24e 100644 --- a/docs_build/adapters/README.rst +++ b/docs_build/adapters/README.rst @@ -4,7 +4,7 @@ sidebarDepth: 0 --- NoneBot.adapters 模块 -================= +===================== .. automodule:: nonebot.adapters :members: diff --git a/docs_build/adapters/cqhttp.rst b/docs_build/adapters/cqhttp.rst index ddf78105..3e63952b 100644 --- a/docs_build/adapters/cqhttp.rst +++ b/docs_build/adapters/cqhttp.rst @@ -4,7 +4,7 @@ sidebarDepth: 0 --- NoneBot.adapters.cqhttp 模块 -================= +============================ .. automodule:: nonebot.adapters.cqhttp :members: diff --git a/docs_build/matcher.rst b/docs_build/matcher.rst new file mode 100644 index 00000000..ef45dfe8 --- /dev/null +++ b/docs_build/matcher.rst @@ -0,0 +1,12 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +NoneBot.matcher 模块 +==================== + +.. automodule:: nonebot.matcher + :members: + :private-members: + :show-inheritance: diff --git a/docs_build/permission.rst b/docs_build/permission.rst index 15144a62..783a65f5 100644 --- a/docs_build/permission.rst +++ b/docs_build/permission.rst @@ -4,7 +4,7 @@ sidebarDepth: 0 --- NoneBot.permission 模块 -==================== +======================= .. automodule:: nonebot.permission :members: diff --git a/nonebot/adapters/__init__.py b/nonebot/adapters/__init__.py index a76dcc33..d4635181 100644 --- a/nonebot/adapters/__init__.py +++ b/nonebot/adapters/__init__.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ 协议适配基类 -=========== +============ 各协议请继承以下基类,并使用 ``driver.register_adapter`` 注册适配器 """ diff --git a/nonebot/matcher.py b/nonebot/matcher.py index c184fb5b..ab2f99d4 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -1,5 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +事件响应器 +========== + +该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。 +""" from nonebot.log import logger import typing @@ -18,7 +24,7 @@ from nonebot.exception import PausedException, RejectedException, FinishedExcept matchers: Dict[int, List[Type["Matcher"]]] = defaultdict(list) """ :类型: ``Dict[int, List[Type[Matcher]]]`` -:说明: 用于存储当前所有的 ``Matcher`` +:说明: 用于存储当前所有的事件响应器 """ current_bot: ContextVar = ContextVar("current_bot") current_event: ContextVar = ContextVar("current_event") @@ -36,22 +42,65 @@ class MatcherMeta(type): class Matcher(metaclass=MatcherMeta): - """`Matcher`类 - """ + """事件响应器类""" module: Optional[str] = None + """ + :类型: ``Optional[str]`` + :说明: 事件响应器所在模块名称 + """ type: str = "" + """ + :类型: ``str`` + :说明: 事件响应器类型 + """ rule: Rule = Rule() + """ + :类型: ``Rule`` + :说明: 事件响应器匹配规则 + """ permission: Permission = Permission() + """ + :类型: ``Permission`` + :说明: 事件响应器触发权限 + """ handlers: List[Handler] = [] - temp: bool = False - expire_time: Optional[datetime] = None + """ + :类型: ``List[Handler]`` + :说明: 事件响应器拥有的事件处理函数列表 + """ priority: int = 1 + """ + :类型: ``int`` + :说明: 事件响应器优先级 + """ block: bool = False + """ + :类型: ``bool`` + :说明: 事件响应器是否阻止事件传播 + """ + temp: bool = False + """ + :类型: ``bool`` + :说明: 事件响应器是否为临时 + """ + expire_time: Optional[datetime] = None + """ + :类型: ``Optional[datetime]`` + :说明: 事件响应器过期时间点 + """ _default_state: dict = {} + """ + :类型: ``dict`` + :说明: 事件响应器默认状态 + """ _default_parser: Optional[ArgsParser] = None + """ + :类型: ``Optional[ArgsParser]`` + :说明: 事件响应器默认参数解析函数 + """ def __init__(self): """实例化 Matcher 以便运行 @@ -69,9 +118,9 @@ class Matcher(metaclass=MatcherMeta): @classmethod def new(cls, type_: str = "", - rule: Rule = Rule(), - permission: Permission = Permission(), - handlers: Optional[list] = None, + rule: Optional[Rule] = None, + permission: Optional[Permission] = None, + handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, @@ -79,18 +128,30 @@ class Matcher(metaclass=MatcherMeta): module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None) -> Type["Matcher"]: - """创建新的 Matcher - - Returns: - Type["Matcher"]: 新的 Matcher 类 + """ + :说明: + 创建一个新的事件响应器,并存储至 `matchers <#matchers>`_ + :参数: + * ``type_: str``: 事件响应器类型,与 ``event.type`` 一致时触发,空字符串表示任意 + * ``rule: Optional[Rule]``: 匹配规则 + * ``permission: Optional[Permission]``: 权限 + * ``handlers: Optional[List[Handler]]``: 事件处理函数列表 + * ``temp: bool``: 是否为临时事件响应器,即触发一次后删除 + * ``priority: int``: 响应优先级 + * ``block: bool``: 是否阻止事件向更低优先级的响应器传播 + * ``module: Optional[str]``: 事件响应器所在模块名称 + * ``default_state: Optional[dict]``: 默认状态 ``state`` + * ``expire_time: Optional[datetime]``: 事件响应器最终有效时间点,过时即被删除 + :返回: + - ``Type[Matcher]``: 新的事件响应器类 """ NewMatcher = type( "Matcher", (Matcher,), { "module": module, "type": type_, - "rule": rule, - "permission": permission, + "rule": rule or Rule(), + "permission": permission or Permission(), "handlers": handlers or [], "temp": temp, "expire_time": expire_time, @@ -105,23 +166,40 @@ class Matcher(metaclass=MatcherMeta): @classmethod async def check_perm(cls, bot: Bot, event: Event) -> bool: + """ + :说明: + 检查是否满足触发权限 + :参数: + * ``bot: Bot``: Bot 对象 + * ``event: Event``: 上报事件 + :返回: + - ``bool``: 是否满足权限 + """ return await cls.permission(bot, event) @classmethod async def check_rule(cls, bot: Bot, event: Event, state: dict) -> bool: - """检查 Matcher 的 Rule 是否成立 - - Args: - event (Event): 消息事件 - - Returns: - bool: 条件成立与否 + """ + :说明: + 检查是否满足匹配规则 + :参数: + * ``bot: Bot``: Bot 对象 + * ``event: Event``: 上报事件 + * ``state: dict``: 当前状态 + :返回: + - ``bool``: 是否满足匹配规则 """ return (event.type == (cls.type or event.type) and await cls.rule(bot, event, state)) @classmethod def args_parser(cls, func: ArgsParser) -> ArgsParser: + """ + :说明: + 用于装饰一个函数来更改当前事件响应器的默认参数解析函数 + :参数: + * ``func: ArgsParser``: 参数解析函数 + """ cls._default_parser = func return func diff --git a/nonebot/rule.py b/nonebot/rule.py index 7d57b33e..b12d4ae1 100644 --- a/nonebot/rule.py +++ b/nonebot/rule.py @@ -4,10 +4,10 @@ 规则 ==== -每个 ``Matcher`` 拥有一个 ``Rule`` ,其中是 **异步** ``RuleChecker`` 的集合,只有当所有 ``RuleChecker`` 检查结果为 ``True`` 时继续运行。 +每个事件响应器 ``Matcher`` 拥有一个匹配规则 ``Rule`` ,其中是 **异步** ``RuleChecker`` 的集合,只有当所有 ``RuleChecker`` 检查结果为 ``True`` 时继续运行。 \:\:\:tip 提示 -``RuleChecker`` 既可以是 async function 也可以是 sync function +``RuleChecker`` 既可以是 async function 也可以是 sync function,但在最终会被 ``nonebot.utils.run_sync`` 转换为 async function \:\:\: """ @@ -185,6 +185,12 @@ def endswith(msg: str) -> Rule: def keyword(msg: str) -> Rule: + """ + :说明: + 匹配消息关键词 + :参数: + * ``msg: str``: 关键词 + """ async def _keyword(bot: Bot, event: Event, state: dict) -> bool: return bool(event.plain_text and msg in event.plain_text) @@ -193,6 +199,22 @@ def keyword(msg: str) -> Rule: def command(command: Tuple[str, ...]) -> Rule: + """ + :说明: + 命令形式匹配,根据配置里提供的 ``command_start``, ``command_sep`` 判断消息是否为命令。 + :参数: + * ``command: Tuples[str, ...]``: 命令内容 + :示例: + 使用默认 ``command_start``, ``command_sep`` 配置 + + 命令 ``("test",)`` 可以匹配:``/test`` 开头的消息 + 命令 ``("test", "sub")`` 可以匹配”``/test.sub`` 开头的消息 + + \:\:\:tip 提示 + 命令内容与后续消息间无需空格! + \:\:\: + """ + config = get_driver().config command_start = config.command_start command_sep = config.command_sep @@ -210,6 +232,14 @@ def command(command: Tuple[str, ...]) -> Rule: def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: + """ + :说明: + 根据正则表达式进行匹配 + :参数: + * ``regex: str``: 正则表达式 + * ``flags: Union[int, re.RegexFlag]``: 正则标志 + """ + pattern = re.compile(regex, flags) async def _regex(bot: Bot, event: Event, state: dict) -> bool: @@ -219,6 +249,12 @@ def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: def to_me() -> Rule: + """ + :说明: + 通过 ``event.to_me`` 判断消息是否是发送给机器人 + :参数: + * 无 + """ async def _to_me(bot: Bot, event: Event, state: dict) -> bool: return bool(event.to_me)