mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-02-25 20:10:28 +08:00
commit
1952d93324
@ -213,5 +213,5 @@ async def _start_scheduler():
|
|||||||
|
|
||||||
|
|
||||||
from nonebot.plugin import on_message, on_notice, on_request, on_metaevent
|
from nonebot.plugin import on_message, on_notice, on_request, on_metaevent
|
||||||
from nonebot.plugin import on_startswith, on_endswith, on_command, on_regex
|
from nonebot.plugin import on_startswith, on_endswith, on_command, on_regex, CommandGroup
|
||||||
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins
|
from nonebot.plugin import load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins
|
||||||
|
@ -278,3 +278,172 @@ class Matcher(metaclass=MatcherMeta):
|
|||||||
logger.info(f"Matcher {self} running complete")
|
logger.info(f"Matcher {self} running complete")
|
||||||
current_bot.reset(b_t)
|
current_bot.reset(b_t)
|
||||||
current_event.reset(e_t)
|
current_event.reset(e_t)
|
||||||
|
|
||||||
|
|
||||||
|
class MatcherGroup:
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
type_: str = "",
|
||||||
|
rule: Rule = Rule(),
|
||||||
|
permission: Permission = Permission(),
|
||||||
|
handlers: Optional[list] = None,
|
||||||
|
temp: bool = False,
|
||||||
|
priority: int = 1,
|
||||||
|
block: bool = False,
|
||||||
|
*,
|
||||||
|
module: Optional[str] = None,
|
||||||
|
default_state: Optional[dict] = None,
|
||||||
|
expire_time: Optional[datetime] = None):
|
||||||
|
self.matchers: List[Type[Matcher]] = []
|
||||||
|
|
||||||
|
self.type = type_
|
||||||
|
self.rule = rule
|
||||||
|
self.permission = permission
|
||||||
|
self.handlers = handlers
|
||||||
|
self.temp = temp
|
||||||
|
self.priority = priority
|
||||||
|
self.block = block
|
||||||
|
self.module = module
|
||||||
|
self.default_state = default_state
|
||||||
|
self.expire_time = expire_time
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return (
|
||||||
|
f"<MatcherGroup from {self.module or 'unknow'}, type={self.type}, "
|
||||||
|
f"priority={self.priority}, temp={self.temp}>")
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
|
def new(self,
|
||||||
|
type_: str = "",
|
||||||
|
rule: Rule = Rule(),
|
||||||
|
permission: Permission = Permission(),
|
||||||
|
handlers: Optional[list] = None,
|
||||||
|
temp: bool = False,
|
||||||
|
priority: int = 1,
|
||||||
|
block: bool = False,
|
||||||
|
*,
|
||||||
|
module: Optional[str] = None,
|
||||||
|
default_state: Optional[dict] = None,
|
||||||
|
expire_time: Optional[datetime] = None) -> Type[Matcher]:
|
||||||
|
matcher = Matcher.new(type_=type_ or self.type,
|
||||||
|
rule=self.rule & rule,
|
||||||
|
permission=permission or self.permission,
|
||||||
|
handlers=handlers or self.handlers,
|
||||||
|
temp=temp or self.temp,
|
||||||
|
priority=priority or self.priority,
|
||||||
|
block=block or self.block,
|
||||||
|
module=module or self.module,
|
||||||
|
default_state=default_state or self.default_state,
|
||||||
|
expire_time=expire_time or self.expire_time)
|
||||||
|
self.matchers.append(matcher)
|
||||||
|
return matcher
|
||||||
|
|
||||||
|
def args_parser(self, func: ArgsParser) -> ArgsParser:
|
||||||
|
for matcher in self.matchers:
|
||||||
|
matcher.args_parser(func)
|
||||||
|
return func
|
||||||
|
|
||||||
|
def handle(self) -> Callable[[Handler], Handler]:
|
||||||
|
"""直接处理消息事件"""
|
||||||
|
|
||||||
|
def _decorator(func: Handler) -> Handler:
|
||||||
|
self.handlers.append(func)
|
||||||
|
return func
|
||||||
|
|
||||||
|
return _decorator
|
||||||
|
|
||||||
|
def receive(self) -> Callable[[Handler], Handler]:
|
||||||
|
"""接收一条新消息并处理"""
|
||||||
|
|
||||||
|
async def _receive(bot: Bot, event: Event, state: dict) -> NoReturn:
|
||||||
|
raise PausedException
|
||||||
|
|
||||||
|
if self.handlers:
|
||||||
|
# 已有前置handlers则接受一条新的消息,否则视为接收初始消息
|
||||||
|
self.handlers.append(_receive)
|
||||||
|
|
||||||
|
def _decorator(func: Handler) -> Handler:
|
||||||
|
if not self.handlers or self.handlers[-1] is not func:
|
||||||
|
self.handlers.append(func)
|
||||||
|
|
||||||
|
return func
|
||||||
|
|
||||||
|
return _decorator
|
||||||
|
|
||||||
|
def got(
|
||||||
|
self,
|
||||||
|
key: str,
|
||||||
|
prompt: Optional[str] = None,
|
||||||
|
args_parser: Optional[ArgsParser] = None
|
||||||
|
) -> Callable[[Handler], Handler]:
|
||||||
|
|
||||||
|
async def _key_getter(bot: Bot, event: Event, state: dict):
|
||||||
|
state["_current_key"] = key
|
||||||
|
if key not in state:
|
||||||
|
if prompt:
|
||||||
|
await bot.send(event=event, message=prompt)
|
||||||
|
raise PausedException
|
||||||
|
else:
|
||||||
|
state["_skip_key"] = True
|
||||||
|
|
||||||
|
async def _key_parser(bot: Bot, event: Event, state: dict):
|
||||||
|
if key in state and state.get("_skip_key"):
|
||||||
|
del state["_skip_key"]
|
||||||
|
return
|
||||||
|
parser = args_parser or self._default_parser
|
||||||
|
if parser:
|
||||||
|
await parser(bot, event, state)
|
||||||
|
else:
|
||||||
|
state[state["_current_key"]] = str(event.message)
|
||||||
|
|
||||||
|
self.handlers.append(_key_getter)
|
||||||
|
self.handlers.append(_key_parser)
|
||||||
|
|
||||||
|
def _decorator(func: Handler) -> Handler:
|
||||||
|
if not hasattr(self.handlers[-1], "__wrapped__"):
|
||||||
|
parser = self.handlers.pop()
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
async def wrapper(bot: Bot, event: Event, state: dict):
|
||||||
|
await parser(bot, event, state)
|
||||||
|
await func(bot, event, state)
|
||||||
|
if "_current_key" in state:
|
||||||
|
del state["_current_key"]
|
||||||
|
|
||||||
|
self.handlers.append(wrapper)
|
||||||
|
|
||||||
|
return func
|
||||||
|
|
||||||
|
return _decorator
|
||||||
|
|
||||||
|
async def finish(
|
||||||
|
self,
|
||||||
|
prompt: Optional[Union[str, Message,
|
||||||
|
MessageSegment]] = None) -> NoReturn:
|
||||||
|
bot: Bot = current_bot.get()
|
||||||
|
event: Event = current_event.get()
|
||||||
|
if prompt:
|
||||||
|
await bot.send(event=event, message=prompt)
|
||||||
|
raise FinishedException
|
||||||
|
|
||||||
|
async def pause(
|
||||||
|
self,
|
||||||
|
prompt: Optional[Union[str, Message,
|
||||||
|
MessageSegment]] = None) -> NoReturn:
|
||||||
|
bot: Bot = current_bot.get()
|
||||||
|
event: Event = current_event.get()
|
||||||
|
if prompt:
|
||||||
|
await bot.send(event=event, message=prompt)
|
||||||
|
raise PausedException
|
||||||
|
|
||||||
|
async def reject(
|
||||||
|
self,
|
||||||
|
prompt: Optional[Union[str, Message,
|
||||||
|
MessageSegment]] = None) -> NoReturn:
|
||||||
|
bot: Bot = current_bot.get()
|
||||||
|
event: Event = current_event.get()
|
||||||
|
if prompt:
|
||||||
|
await bot.send(event=event, message=prompt)
|
||||||
|
raise RejectedException
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from nonebot.utils import run_sync
|
from nonebot.utils import run_sync
|
||||||
from nonebot.typing import Bot, Event, Union, NoReturn, Callable, Awaitable, PermissionChecker
|
from nonebot.typing import Bot, Event, Union, NoReturn, Optional, Callable, Awaitable, PermissionChecker
|
||||||
|
|
||||||
|
|
||||||
class Permission:
|
class Permission:
|
||||||
@ -53,10 +53,13 @@ class Permission:
|
|||||||
def __and__(self, other) -> NoReturn:
|
def __and__(self, other) -> NoReturn:
|
||||||
raise RuntimeError("And operation between Permissions is not allowed.")
|
raise RuntimeError("And operation between Permissions is not allowed.")
|
||||||
|
|
||||||
def __or__(self, other: Union["Permission",
|
def __or__(
|
||||||
PermissionChecker]) -> "Permission":
|
self, other: Optional[Union["Permission",
|
||||||
|
PermissionChecker]]) -> "Permission":
|
||||||
checkers = self.checkers.copy()
|
checkers = self.checkers.copy()
|
||||||
if isinstance(other, Permission):
|
if other is None:
|
||||||
|
return self
|
||||||
|
elif isinstance(other, Permission):
|
||||||
checkers |= other.checkers
|
checkers |= other.checkers
|
||||||
elif asyncio.iscoroutinefunction(other):
|
elif asyncio.iscoroutinefunction(other):
|
||||||
checkers.add(other) # type: ignore
|
checkers.add(other) # type: ignore
|
||||||
|
@ -9,9 +9,9 @@ from dataclasses import dataclass
|
|||||||
from importlib._bootstrap import _load
|
from importlib._bootstrap import _load
|
||||||
|
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.matcher import Matcher
|
|
||||||
from nonebot.permission import Permission
|
from nonebot.permission import Permission
|
||||||
from nonebot.typing import Handler, RuleChecker
|
from nonebot.typing import Handler, RuleChecker
|
||||||
|
from nonebot.matcher import Matcher, MatcherGroup
|
||||||
from nonebot.rule import Rule, startswith, endswith, command, regex
|
from nonebot.rule import Rule, startswith, endswith, command, regex
|
||||||
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
from nonebot.typing import Set, List, Dict, Type, Tuple, Union, Optional, ModuleType
|
||||||
|
|
||||||
@ -27,8 +27,8 @@ class Plugin(object):
|
|||||||
matcher: Set[Type[Matcher]]
|
matcher: Set[Type[Matcher]]
|
||||||
|
|
||||||
|
|
||||||
def on(rule: Union[Rule, RuleChecker] = Rule(),
|
def on(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
permission: Permission = Permission(),
|
permission: Optional[Permission] = None,
|
||||||
*,
|
*,
|
||||||
handlers: Optional[List[Handler]] = None,
|
handlers: Optional[List[Handler]] = None,
|
||||||
temp: bool = False,
|
temp: bool = False,
|
||||||
@ -37,7 +37,7 @@ def on(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
state: Optional[dict] = None) -> Type[Matcher]:
|
state: Optional[dict] = None) -> Type[Matcher]:
|
||||||
matcher = Matcher.new("",
|
matcher = Matcher.new("",
|
||||||
Rule() & rule,
|
Rule() & rule,
|
||||||
permission,
|
permission or Permission(),
|
||||||
temp=temp,
|
temp=temp,
|
||||||
priority=priority,
|
priority=priority,
|
||||||
block=block,
|
block=block,
|
||||||
@ -47,7 +47,7 @@ def on(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(),
|
def on_metaevent(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
*,
|
*,
|
||||||
handlers: Optional[List[Handler]] = None,
|
handlers: Optional[List[Handler]] = None,
|
||||||
temp: bool = False,
|
temp: bool = False,
|
||||||
@ -66,8 +66,8 @@ def on_metaevent(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
def on_message(rule: Union[Rule, RuleChecker] = Rule(),
|
def on_message(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
permission: Permission = Permission(),
|
permission: Optional[Permission] = None,
|
||||||
*,
|
*,
|
||||||
handlers: Optional[List[Handler]] = None,
|
handlers: Optional[List[Handler]] = None,
|
||||||
temp: bool = False,
|
temp: bool = False,
|
||||||
@ -76,7 +76,7 @@ def on_message(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
state: Optional[dict] = None) -> Type[Matcher]:
|
state: Optional[dict] = None) -> Type[Matcher]:
|
||||||
matcher = Matcher.new("message",
|
matcher = Matcher.new("message",
|
||||||
Rule() & rule,
|
Rule() & rule,
|
||||||
permission,
|
permission or Permission(),
|
||||||
temp=temp,
|
temp=temp,
|
||||||
priority=priority,
|
priority=priority,
|
||||||
block=block,
|
block=block,
|
||||||
@ -86,7 +86,7 @@ def on_message(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
def on_notice(rule: Union[Rule, RuleChecker] = Rule(),
|
def on_notice(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
*,
|
*,
|
||||||
handlers: Optional[List[Handler]] = None,
|
handlers: Optional[List[Handler]] = None,
|
||||||
temp: bool = False,
|
temp: bool = False,
|
||||||
@ -105,7 +105,7 @@ def on_notice(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
return matcher
|
return matcher
|
||||||
|
|
||||||
|
|
||||||
def on_request(rule: Union[Rule, RuleChecker] = Rule(),
|
def on_request(rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
*,
|
*,
|
||||||
handlers: Optional[List[Handler]] = None,
|
handlers: Optional[List[Handler]] = None,
|
||||||
temp: bool = False,
|
temp: bool = False,
|
||||||
@ -125,27 +125,23 @@ def on_request(rule: Union[Rule, RuleChecker] = Rule(),
|
|||||||
|
|
||||||
|
|
||||||
def on_startswith(msg: str,
|
def on_startswith(msg: str,
|
||||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
rule: Optional[Optional[Union[Rule, RuleChecker]]] = None,
|
||||||
permission: Permission = Permission(),
|
|
||||||
**kwargs) -> Type[Matcher]:
|
**kwargs) -> Type[Matcher]:
|
||||||
return on_message(startswith(msg) &
|
return on_message(startswith(msg) & rule, **kwargs) if rule else on_message(
|
||||||
rule, permission, **kwargs) if rule else on_message(
|
startswith(msg), **kwargs)
|
||||||
startswith(msg), permission, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def on_endswith(msg: str,
|
def on_endswith(msg: str,
|
||||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
rule: Optional[Optional[Union[Rule, RuleChecker]]] = None,
|
||||||
permission: Permission = Permission(),
|
|
||||||
**kwargs) -> Type[Matcher]:
|
**kwargs) -> Type[Matcher]:
|
||||||
return on_message(endswith(msg) &
|
return on_message(endswith(msg) & rule, **kwargs) if rule else on_message(
|
||||||
rule, permission, **kwargs) if rule else on_message(
|
startswith(msg), **kwargs)
|
||||||
startswith(msg), permission, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def on_command(cmd: Union[str, Tuple[str, ...]],
|
def on_command(cmd: Union[str, Tuple[str, ...]],
|
||||||
|
alias: Set[Union[str, Tuple[str, ...]]] = None,
|
||||||
rule: Optional[Union[Rule, RuleChecker]] = None,
|
rule: Optional[Union[Rule, RuleChecker]] = None,
|
||||||
permission: Permission = Permission(),
|
**kwargs) -> Union[Type[Matcher], MatcherGroup]:
|
||||||
**kwargs) -> Type[Matcher]:
|
|
||||||
if isinstance(cmd, str):
|
if isinstance(cmd, str):
|
||||||
cmd = (cmd,)
|
cmd = (cmd,)
|
||||||
|
|
||||||
@ -157,20 +153,28 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
|
|||||||
handlers = kwargs.pop("handlers", [])
|
handlers = kwargs.pop("handlers", [])
|
||||||
handlers.insert(0, _strip_cmd)
|
handlers.insert(0, _strip_cmd)
|
||||||
|
|
||||||
return on_message(
|
if alias:
|
||||||
command(cmd) &
|
alias = set(map(lambda x: (x,) if isinstance(x, str) else x, alias))
|
||||||
rule, permission, handlers=handlers, **kwargs) if rule else on_message(
|
group = MatcherGroup("message",
|
||||||
command(cmd), permission, handlers=handlers, **kwargs)
|
Rule() & rule,
|
||||||
|
handlers=handlers,
|
||||||
|
**kwargs)
|
||||||
|
for cmd_ in [cmd, *alias]:
|
||||||
|
group.new(rule=command(cmd_))
|
||||||
|
return group
|
||||||
|
else:
|
||||||
|
return on_message(command(cmd) & rule, handlers=handlers, **
|
||||||
|
kwargs) if rule else on_message(
|
||||||
|
command(cmd), handlers=handlers, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def on_regex(pattern: str,
|
def on_regex(pattern: str,
|
||||||
flags: Union[int, re.RegexFlag] = 0,
|
flags: Union[int, re.RegexFlag] = 0,
|
||||||
rule: Optional[Rule] = None,
|
rule: Optional[Rule] = None,
|
||||||
permission: Permission = Permission(),
|
|
||||||
**kwargs) -> Type[Matcher]:
|
**kwargs) -> Type[Matcher]:
|
||||||
return on_message(regex(pattern, flags) &
|
return on_message(regex(pattern, flags) &
|
||||||
rule, permission, **kwargs) if rule else on_message(
|
rule, **kwargs) if rule else on_message(
|
||||||
regex(pattern, flags), permission, **kwargs)
|
regex(pattern, flags), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def load_plugin(module_path: str) -> Optional[Plugin]:
|
def load_plugin(module_path: str) -> Optional[Plugin]:
|
||||||
@ -234,3 +238,21 @@ def load_builtin_plugins():
|
|||||||
|
|
||||||
def get_loaded_plugins() -> Set[Plugin]:
|
def get_loaded_plugins() -> Set[Plugin]:
|
||||||
return set(plugins.values())
|
return set(plugins.values())
|
||||||
|
|
||||||
|
|
||||||
|
class CommandGroup:
|
||||||
|
|
||||||
|
def __init__(self, name: Union[str, Tuple[str, ...]], **kwargs):
|
||||||
|
self.basename = (name,) if isinstance(name, str) else name
|
||||||
|
if "aliases" in kwargs:
|
||||||
|
del kwargs["aliases"]
|
||||||
|
self.base_kwargs = kwargs
|
||||||
|
|
||||||
|
def command(self, name: Union[str, Tuple[str, ...]],
|
||||||
|
**kwargs) -> Union[Type[Matcher], MatcherGroup]:
|
||||||
|
sub_name = (name,) if isinstance(name, str) else name
|
||||||
|
name = self.basename + sub_name
|
||||||
|
|
||||||
|
final_kwargs = self.base_kwargs.copy()
|
||||||
|
final_kwargs.update(kwargs)
|
||||||
|
return on_command(name, **final_kwargs)
|
||||||
|
@ -20,7 +20,7 @@ from pygtrie import CharTrie
|
|||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.utils import run_sync
|
from nonebot.utils import run_sync
|
||||||
from nonebot.typing import Bot, Any, Dict, Event, Union, Tuple, NoReturn, Callable, Awaitable, RuleChecker
|
from nonebot.typing import Bot, Any, Dict, Event, Union, Tuple, NoReturn, Optional, Callable, Awaitable, RuleChecker
|
||||||
|
|
||||||
|
|
||||||
class Rule:
|
class Rule:
|
||||||
@ -68,9 +68,11 @@ class Rule:
|
|||||||
*map(lambda c: c(bot, event, state), self.checkers))
|
*map(lambda c: c(bot, event, state), self.checkers))
|
||||||
return all(results)
|
return all(results)
|
||||||
|
|
||||||
def __and__(self, other: Union["Rule", RuleChecker]) -> "Rule":
|
def __and__(self, other: Optional[Union["Rule", RuleChecker]]) -> "Rule":
|
||||||
checkers = self.checkers.copy()
|
checkers = self.checkers.copy()
|
||||||
if isinstance(other, Rule):
|
if other is None:
|
||||||
|
return self
|
||||||
|
elif isinstance(other, Rule):
|
||||||
checkers |= other.checkers
|
checkers |= other.checkers
|
||||||
elif asyncio.iscoroutinefunction(other):
|
elif asyncio.iscoroutinefunction(other):
|
||||||
checkers.add(other) # type: ignore
|
checkers.add(other) # type: ignore
|
||||||
|
Loading…
x
Reference in New Issue
Block a user