add startswith endswith ignorecase option #312

This commit is contained in:
yanyongyu 2021-04-04 12:19:03 +08:00
parent c402b7599f
commit 0d467d9275
3 changed files with 129 additions and 111 deletions

View File

@ -290,6 +290,7 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
def on_startswith(msg: str, def on_startswith(msg: str,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None, rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
ignorecase: bool = False,
**kwargs) -> Type[Matcher]: **kwargs) -> Type[Matcher]:
""" """
:说明: :说明:
@ -300,6 +301,7 @@ def on_startswith(msg: str,
* ``msg: str``: 指定消息开头内容 * ``msg: str``: 指定消息开头内容
* ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则 * ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则
* ``ignorecase: bool``: 是否忽略大小写
* ``permission: Optional[Permission]``: 事件响应权限 * ``permission: Optional[Permission]``: 事件响应权限
* ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表 * ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表
* ``temp: bool``: 是否为临时事件响应器仅执行一次 * ``temp: bool``: 是否为临时事件响应器仅执行一次
@ -312,11 +314,12 @@ def on_startswith(msg: str,
- ``Type[Matcher]`` - ``Type[Matcher]``
""" """
return on_message(startswith(msg) & rule, **kwargs) return on_message(startswith(msg, ignorecase) & rule, **kwargs)
def on_endswith(msg: str, def on_endswith(msg: str,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None, rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
ignorecase: bool = False,
**kwargs) -> Type[Matcher]: **kwargs) -> Type[Matcher]:
""" """
:说明: :说明:
@ -327,6 +330,7 @@ def on_endswith(msg: str,
* ``msg: str``: 指定消息结尾内容 * ``msg: str``: 指定消息结尾内容
* ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则 * ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则
* ``ignorecase: bool``: 是否忽略大小写
* ``permission: Optional[Permission]``: 事件响应权限 * ``permission: Optional[Permission]``: 事件响应权限
* ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表 * ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表
* ``temp: bool``: 是否为临时事件响应器仅执行一次 * ``temp: bool``: 是否为临时事件响应器仅执行一次
@ -339,7 +343,7 @@ def on_endswith(msg: str,
- ``Type[Matcher]`` - ``Type[Matcher]``
""" """
return on_message(endswith(msg) & rule, **kwargs) return on_message(endswith(msg, ignorecase) & rule, **kwargs)
def on_keyword(keywords: Set[str], def on_keyword(keywords: Set[str],
@ -552,7 +556,7 @@ class CommandGroup:
:参数: :参数:
* ``cmd: Union[str, Tuple[str, ...]]``: 命令前缀 * ``cmd: Union[str, Tuple[str, ...]]``: 命令前缀
* ``**kwargs``: 其他传递给 ``on_command`` 的参数将会覆盖命令组默认值 * ``**kwargs``: 其他传递给 ``on_shell_command`` 的参数将会覆盖命令组默认值
:返回: :返回:
@ -637,6 +641,7 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy() final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs) final_kwargs.update(kwargs)
final_kwargs.pop("type", None) final_kwargs.pop("type", None)
final_kwargs.pop("permission", None)
matcher = on_metaevent(**final_kwargs) matcher = on_metaevent(**final_kwargs)
self.matchers.append(matcher) self.matchers.append(matcher)
return matcher return matcher
@ -732,6 +737,7 @@ class MatcherGroup:
:参数: :参数:
* ``msg: str``: 指定消息开头内容 * ``msg: str``: 指定消息开头内容
* ``ignorecase: bool``: 是否忽略大小写
* ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则 * ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则
* ``permission: Optional[Permission]``: 事件响应权限 * ``permission: Optional[Permission]``: 事件响应权限
* ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表 * ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表
@ -761,6 +767,7 @@ class MatcherGroup:
:参数: :参数:
* ``msg: str``: 指定消息结尾内容 * ``msg: str``: 指定消息结尾内容
* ``ignorecase: bool``: 是否忽略大小写
* ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则 * ``rule: Optional[Union[Rule, T_RuleChecker]]``: 事件响应规则
* ``permission: Optional[Permission]``: 事件响应权限 * ``permission: Optional[Permission]``: 事件响应权限
* ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表 * ``handlers: Optional[List[Union[T_Handler, Handler]]]``: 事件处理函数列表

View File

@ -1,7 +1,7 @@
import re import re
from types import ModuleType from types import ModuleType
from contextvars import ContextVar from dataclasses import dataclass
from typing import Any, Set, List, Dict, Type, Tuple, Union, Optional from typing import Set, List, Dict, Type, Tuple, Union, Optional, TYPE_CHECKING
from nonebot.matcher import Matcher from nonebot.matcher import Matcher
from nonebot.handler import Handler from nonebot.handler import Handler
@ -9,32 +9,28 @@ from nonebot.permission import Permission
from nonebot.rule import Rule, ArgumentParser from nonebot.rule import Rule, ArgumentParser
from nonebot.typing import T_State, T_StateFactory, T_Handler, T_RuleChecker from nonebot.typing import T_State, T_StateFactory, T_Handler, T_RuleChecker
from .export import Export, export
from .manager import PluginManager
plugins: Dict[str, "Plugin"] = ... plugins: Dict[str, "Plugin"] = ...
PLUGIN_NAMESPACE: str = ...
_export: ContextVar["Export"] = ...
_tmp_matchers: ContextVar[Set[Type[Matcher]]] = ...
class Export(dict):
def __call__(self, func, **kwargs):
...
def __setattr__(self, name, value):
...
def __getattr__(self, name):
...
@dataclass(eq=False)
class Plugin(object): class Plugin(object):
name: str name: str
module: ModuleType module: ModuleType
matcher: Set[Type[Matcher]]
export: Export @property
def export(self) -> Export:
...
@property
def matcher(self) -> Set[Type[Matcher]]:
...
def on(type: str = ..., def on(type: str = "",
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
*, *,
@ -96,6 +92,7 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = ...,
def on_startswith( def on_startswith(
msg: str, msg: str,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
ignorecase: bool = ...,
*, *,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
@ -109,6 +106,7 @@ def on_startswith(
def on_endswith(msg: str, def on_endswith(msg: str,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
ignorecase: bool = ...,
*, *,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
@ -121,7 +119,7 @@ def on_endswith(msg: str,
def on_keyword(keywords: Set[str], def on_keyword(keywords: Set[str],
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
*, *,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
@ -147,16 +145,24 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
... ...
def on_shell_command(cmd: Union[str, Tuple[str, ...]], def on_shell_command(
rule: Optional[Union[Rule, T_RuleChecker]] = None, cmd: Union[str, Tuple[str, ...]],
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None, rule: Optional[Union[Rule, T_RuleChecker]] = ...,
parser: Optional[ArgumentParser] = None, aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
**kwargs) -> Type[Matcher]: parser: Optional[ArgumentParser] = ...,
*,
permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ...,
priority: int = ...,
block: bool = ...,
state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
def on_regex(pattern: str, def on_regex(pattern: str,
flags: Union[int, re.RegexFlag] = 0, flags: Union[int, re.RegexFlag] = ...,
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
*, *,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
@ -169,67 +175,26 @@ def on_regex(pattern: str,
... ...
def load_plugin(module_path: str) -> Optional[Plugin]:
...
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
...
def load_all_plugins(module_path: Set[str],
plugin_dir: Set[str]) -> Set[Plugin]:
...
def load_from_json(file_path: str, encoding: str = ...) -> Set[Plugin]:
...
def load_from_toml(file_path: str, encoding: str = ...) -> Set[Plugin]:
...
def load_builtin_plugins(name: str = ...):
...
def get_plugin(name: str) -> Optional[Plugin]:
...
def get_loaded_plugins() -> Set[Plugin]:
...
def export() -> Export:
...
def require(name: str) -> Export:
...
class CommandGroup: class CommandGroup:
def __init__(self, def __init__(self,
cmd: Union[str, Tuple[str, ...]], cmd: Union[str, Tuple[str, ...]],
*,
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
*,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ..., temp: bool = ...,
priority: int = ..., priority: int = ...,
block: bool = ..., block: bool = ...,
state: Optional[T_State] = ...): state: Optional[T_State] = ...,
self.basecmd: Tuple[str, ...] = ... state_factory: Optional[T_StateFactory] = ...):
self.base_kwargs: Dict[str, Any] = ... ...
def command(self, def command(self,
cmd: Union[str, Tuple[str, ...]], cmd: Union[str, Tuple[str, ...]],
*, *,
aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ..., temp: bool = ...,
@ -244,7 +209,7 @@ class CommandGroup:
cmd: Union[str, Tuple[str, ...]], cmd: Union[str, Tuple[str, ...]],
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ..., aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
parser: Optional[ArgumentParser] = ..., parser: Optional[ArgumentParser] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
@ -267,7 +232,8 @@ class MatcherGroup:
temp: bool = ..., temp: bool = ...,
priority: int = ..., priority: int = ...,
block: bool = ..., block: bool = ...,
state: Optional[T_State] = ...): state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...):
... ...
def on(self, def on(self,
@ -286,49 +252,49 @@ class MatcherGroup:
def on_metaevent( def on_metaevent(
self, self,
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = None, rule: Optional[Union[Rule, T_RuleChecker]] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = None, handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = False, temp: bool = ...,
priority: int = 1, priority: int = ...,
block: bool = False, block: bool = ...,
state: Optional[T_State] = None, state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]: state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
def on_message( def on_message(
self, self,
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = None, rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = None, permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = None, handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = False, temp: bool = ...,
priority: int = 1, priority: int = ...,
block: bool = True, block: bool = ...,
state: Optional[T_State] = None, state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]: state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
def on_notice( def on_notice(
self, self,
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = None, rule: Optional[Union[Rule, T_RuleChecker]] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = None, handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = False, temp: bool = ...,
priority: int = 1, priority: int = ...,
block: bool = False, block: bool = ...,
state: Optional[T_State] = None, state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]: state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
def on_request( def on_request(
self, self,
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = None, rule: Optional[Union[Rule, T_RuleChecker]] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = None, handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = False, temp: bool = ...,
priority: int = 1, priority: int = ...,
block: bool = False, block: bool = ...,
state: Optional[T_State] = None, state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]: state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
@ -336,7 +302,8 @@ class MatcherGroup:
self, self,
msg: str, msg: str,
*, *,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., ignorecase: bool = ...,
rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ..., temp: bool = ...,
@ -350,7 +317,8 @@ class MatcherGroup:
self, self,
msg: str, msg: str,
*, *,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., ignorecase: bool = ...,
rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ..., temp: bool = ...,
@ -364,7 +332,7 @@ class MatcherGroup:
self, self,
keywords: Set[str], keywords: Set[str],
*, *,
rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ..., handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ..., temp: bool = ...,
@ -408,7 +376,7 @@ class MatcherGroup:
def on_regex( def on_regex(
self, self,
pattern: str, pattern: str,
flags: Union[int, re.RegexFlag] = 0, flags: Union[int, re.RegexFlag] = ...,
*, *,
rule: Optional[Union[Rule, T_RuleChecker]] = ..., rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ..., permission: Optional[Permission] = ...,
@ -419,3 +387,40 @@ class MatcherGroup:
state: Optional[T_State] = ..., state: Optional[T_State] = ...,
state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]: state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
... ...
def load_plugin(module_path: str) -> Optional[Plugin]:
...
def load_plugins(*plugin_dir: str) -> Set[Plugin]:
...
def load_all_plugins(module_path: Set[str],
plugin_dir: Set[str]) -> Set[Plugin]:
...
def load_from_json(file_path: str, encoding: str = ...) -> Set[Plugin]:
...
def load_from_toml(file_path: str, encoding: str = ...) -> Set[Plugin]:
...
def load_builtin_plugins(name: str = ...) -> Optional[Plugin]:
...
def get_plugin(name: str) -> Optional[Plugin]:
...
def get_loaded_plugins() -> Set[Plugin]:
...
def require(name: str) -> Optional[Export]:
...

View File

@ -175,7 +175,7 @@ class TrieRule:
}) })
def startswith(msg: str) -> Rule: def startswith(msg: str, ignorecase: bool = False) -> Rule:
""" """
:说明: :说明:
@ -186,16 +186,19 @@ def startswith(msg: str) -> Rule:
* ``msg: str``: 消息开头字符串 * ``msg: str``: 消息开头字符串
""" """
pattern = re.compile(f"^{re.escape(msg)}",
re.IGNORECASE if ignorecase else 0)
async def _startswith(bot: "Bot", event: "Event", state: T_State) -> bool: async def _startswith(bot: "Bot", event: "Event", state: T_State) -> bool:
if event.get_type() != "message": if event.get_type() != "message":
return False return False
text = event.get_plaintext() text = event.get_plaintext()
return text.startswith(msg) return bool(pattern.match(text))
return Rule(_startswith) return Rule(_startswith)
def endswith(msg: str) -> Rule: def endswith(msg: str, ignorecase: bool = False) -> Rule:
""" """
:说明: :说明:
@ -205,11 +208,14 @@ def endswith(msg: str) -> Rule:
* ``msg: str``: 消息结尾字符串 * ``msg: str``: 消息结尾字符串
""" """
pattern = re.compile(f"{re.escape(msg)}$",
re.IGNORECASE if ignorecase else 0)
async def _endswith(bot: "Bot", event: "Event", state: T_State) -> bool: async def _endswith(bot: "Bot", event: "Event", state: T_State) -> bool:
if event.get_type() != "message": if event.get_type() != "message":
return False return False
return event.get_plaintext().endswith(msg) text = event.get_plaintext()
return bool(pattern.match(text))
return Rule(_endswith) return Rule(_endswith)