2022-01-19 16:16:56 +08:00
|
|
|
|
"""本模块是 {ref}`nonebot.matcher.Matcher.permission` 的类型定义。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
|
2022-01-19 16:16:56 +08:00
|
|
|
|
每个 {ref}`nonebot.matcher.Matcher` 拥有一个 {ref}`nonebot.permission.Permission` ,
|
|
|
|
|
其中是 `PermissionChecker` 的集合,只要有一个 `PermissionChecker` 检查结果为 `True` 时就会继续运行。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
|
2022-01-16 11:30:09 +08:00
|
|
|
|
FrontMatter:
|
|
|
|
|
sidebar_position: 6
|
|
|
|
|
description: nonebot.permission 模块
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
import asyncio
|
2021-11-21 12:36:44 +08:00
|
|
|
|
from contextlib import AsyncExitStack
|
2021-12-23 17:50:59 +08:00
|
|
|
|
from typing import Any, Set, Tuple, Union, NoReturn, Optional, Coroutine
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
2021-11-14 18:51:23 +08:00
|
|
|
|
from nonebot.adapters import Bot, Event
|
2021-12-12 18:19:08 +08:00
|
|
|
|
from nonebot.dependencies import Dependent
|
2021-12-01 19:21:31 +08:00
|
|
|
|
from nonebot.exception import SkippedException
|
2022-01-19 16:16:56 +08:00
|
|
|
|
from nonebot.typing import T_DependencyCache, T_PermissionChecker
|
2021-12-23 17:50:59 +08:00
|
|
|
|
from nonebot.params import (
|
|
|
|
|
BotParam,
|
|
|
|
|
EventType,
|
|
|
|
|
EventParam,
|
|
|
|
|
DependParam,
|
|
|
|
|
DefaultParam,
|
|
|
|
|
)
|
2020-12-06 02:30:19 +08:00
|
|
|
|
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
2021-12-06 22:19:05 +08:00
|
|
|
|
async def _run_coro_with_catch(coro: Coroutine[Any, Any, Any]):
|
|
|
|
|
try:
|
|
|
|
|
return await coro
|
|
|
|
|
except SkippedException:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
2020-08-17 16:09:41 +08:00
|
|
|
|
class Permission:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""{ref}`nonebot.matcher.Matcher` 权限类。
|
|
|
|
|
|
|
|
|
|
当事件传递时,在 {ref}`nonebot.matcher.Matcher` 运行前进行检查。
|
|
|
|
|
|
|
|
|
|
参数:
|
|
|
|
|
checkers: PermissionChecker
|
2021-05-30 11:07:27 +08:00
|
|
|
|
|
2022-01-12 18:53:30 +08:00
|
|
|
|
用法:
|
|
|
|
|
```python
|
2021-05-30 11:07:27 +08:00
|
|
|
|
Permission(async_function) | sync_function
|
|
|
|
|
# 等价于
|
2022-01-19 16:16:56 +08:00
|
|
|
|
Permission(async_function, sync_function)
|
2022-01-12 18:53:30 +08:00
|
|
|
|
```
|
2021-05-30 11:07:27 +08:00
|
|
|
|
"""
|
2021-11-22 23:21:26 +08:00
|
|
|
|
|
2020-08-17 16:09:41 +08:00
|
|
|
|
__slots__ = ("checkers",)
|
|
|
|
|
|
2021-12-12 18:19:08 +08:00
|
|
|
|
HANDLER_PARAM_TYPES = [
|
2021-12-23 17:50:59 +08:00
|
|
|
|
DependParam,
|
|
|
|
|
BotParam,
|
|
|
|
|
EventParam,
|
|
|
|
|
DefaultParam,
|
2021-12-12 18:19:08 +08:00
|
|
|
|
]
|
2021-11-21 12:36:44 +08:00
|
|
|
|
|
2021-12-12 18:19:08 +08:00
|
|
|
|
def __init__(self, *checkers: Union[T_PermissionChecker, Dependent[bool]]) -> None:
|
|
|
|
|
self.checkers: Set[Dependent[bool]] = set(
|
2021-11-22 23:21:26 +08:00
|
|
|
|
checker
|
2021-12-12 18:19:08 +08:00
|
|
|
|
if isinstance(checker, Dependent)
|
|
|
|
|
else Dependent[bool].parse(
|
|
|
|
|
call=checker, allow_types=self.HANDLER_PARAM_TYPES
|
|
|
|
|
)
|
2021-11-22 23:21:26 +08:00
|
|
|
|
for checker in checkers
|
|
|
|
|
)
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""存储 `PermissionChecker`"""
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
2021-11-21 12:36:44 +08:00
|
|
|
|
async def __call__(
|
|
|
|
|
self,
|
|
|
|
|
bot: Bot,
|
|
|
|
|
event: Event,
|
|
|
|
|
stack: Optional[AsyncExitStack] = None,
|
2021-12-16 23:22:25 +08:00
|
|
|
|
dependency_cache: Optional[T_DependencyCache] = None,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
) -> bool:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查是否满足某个权限
|
2020-11-30 11:08:00 +08:00
|
|
|
|
|
2022-01-12 18:31:12 +08:00
|
|
|
|
参数:
|
2022-01-12 19:10:29 +08:00
|
|
|
|
bot: Bot 对象
|
|
|
|
|
event: Event 对象
|
|
|
|
|
stack: 异步上下文栈
|
|
|
|
|
dependency_cache: 依赖缓存
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2020-08-17 16:09:41 +08:00
|
|
|
|
if not self.checkers:
|
|
|
|
|
return True
|
|
|
|
|
results = await asyncio.gather(
|
2021-11-22 23:21:26 +08:00
|
|
|
|
*(
|
2021-12-06 22:19:05 +08:00
|
|
|
|
_run_coro_with_catch(
|
|
|
|
|
checker(
|
|
|
|
|
bot=bot,
|
|
|
|
|
event=event,
|
2021-12-12 18:19:08 +08:00
|
|
|
|
stack=stack,
|
|
|
|
|
dependency_cache=dependency_cache,
|
2021-12-06 22:19:05 +08:00
|
|
|
|
)
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
|
|
|
|
for checker in self.checkers
|
2021-12-01 19:21:31 +08:00
|
|
|
|
),
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
2021-12-06 22:19:05 +08:00
|
|
|
|
return any(results)
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
def __and__(self, other) -> NoReturn:
|
|
|
|
|
raise RuntimeError("And operation between Permissions is not allowed.")
|
|
|
|
|
|
2020-09-27 18:05:13 +08:00
|
|
|
|
def __or__(
|
2021-11-22 23:21:26 +08:00
|
|
|
|
self, other: Optional[Union["Permission", T_PermissionChecker]]
|
|
|
|
|
) -> "Permission":
|
2020-09-27 18:05:13 +08:00
|
|
|
|
if other is None:
|
|
|
|
|
return self
|
|
|
|
|
elif isinstance(other, Permission):
|
2021-11-21 12:36:44 +08:00
|
|
|
|
return Permission(*self.checkers, *other.checkers)
|
2020-08-17 16:09:41 +08:00
|
|
|
|
else:
|
2021-11-21 12:36:44 +08:00
|
|
|
|
return Permission(*self.checkers, other)
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class Message:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查是否为消息事件"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ()
|
|
|
|
|
|
2021-12-23 17:50:59 +08:00
|
|
|
|
async def __call__(self, type: str = EventType()) -> bool:
|
|
|
|
|
return type == "message"
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class Notice:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查是否为通知事件"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ()
|
|
|
|
|
|
2021-12-23 17:50:59 +08:00
|
|
|
|
async def __call__(self, type: str = EventType()) -> bool:
|
|
|
|
|
return type == "notice"
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class Request:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查是否为请求事件"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ()
|
|
|
|
|
|
2021-12-23 17:50:59 +08:00
|
|
|
|
async def __call__(self, type: str = EventType()) -> bool:
|
|
|
|
|
return type == "request"
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class MetaEvent:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查是否为元事件"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ()
|
|
|
|
|
|
2021-12-23 17:50:59 +08:00
|
|
|
|
async def __call__(self, type: str = EventType()) -> bool:
|
|
|
|
|
return type == "meta_event"
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-19 16:16:56 +08:00
|
|
|
|
MESSAGE: Permission = Permission(Message())
|
|
|
|
|
"""匹配任意 `message` 类型事件
|
|
|
|
|
|
|
|
|
|
仅在需要同时捕获不同类型事件时使用,优先使用 message type 的 Matcher。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2022-01-19 16:16:56 +08:00
|
|
|
|
NOTICE: Permission = Permission(Notice())
|
|
|
|
|
"""匹配任意 `notice` 类型事件
|
|
|
|
|
|
|
|
|
|
仅在需要同时捕获不同类型事件时使用,优先使用 notice type 的 Matcher。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2022-01-19 16:16:56 +08:00
|
|
|
|
REQUEST: Permission = Permission(Request())
|
|
|
|
|
"""匹配任意 `request` 类型事件
|
|
|
|
|
|
|
|
|
|
仅在需要同时捕获不同类型事件时使用,优先使用 request type 的 Matcher。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2022-01-19 16:16:56 +08:00
|
|
|
|
METAEVENT: Permission = Permission(MetaEvent())
|
|
|
|
|
"""匹配任意 `meta_event` 类型事件
|
|
|
|
|
|
|
|
|
|
仅在需要同时捕获不同类型事件时使用,优先使用 meta_event type 的 Matcher。
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class User:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查当前事件是否属于指定会话
|
|
|
|
|
|
|
|
|
|
参数:
|
|
|
|
|
users: 会话 ID 元组
|
|
|
|
|
perm: 需同时满足的权限
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ("users", "perm")
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
def __init__(
|
|
|
|
|
self, users: Tuple[str, ...], perm: Optional[Permission] = None
|
|
|
|
|
) -> None:
|
|
|
|
|
self.users = users
|
|
|
|
|
self.perm = perm
|
|
|
|
|
|
|
|
|
|
async def __call__(self, bot: Bot, event: Event) -> bool:
|
|
|
|
|
return bool(
|
|
|
|
|
event.get_session_id() in self.users
|
|
|
|
|
and (self.perm is None or await self.perm(bot, event))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def USER(*users: str, perm: Optional[Permission] = None):
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""匹配当前事件属于指定会话
|
2020-11-30 11:08:00 +08:00
|
|
|
|
|
2022-01-12 18:31:12 +08:00
|
|
|
|
参数:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
user: 会话白名单
|
|
|
|
|
perm: 需要同时满足的权限
|
2020-09-14 20:48:03 +08:00
|
|
|
|
"""
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
return Permission(User(users, perm))
|
2020-08-17 16:09:41 +08:00
|
|
|
|
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
class SuperUser:
|
2022-01-19 16:16:56 +08:00
|
|
|
|
"""检查当前事件是否是消息事件且属于超级管理员"""
|
|
|
|
|
|
|
|
|
|
__slots__ = ()
|
|
|
|
|
|
2021-12-06 10:10:51 +08:00
|
|
|
|
async def __call__(self, bot: Bot, event: Event) -> bool:
|
2021-12-26 18:46:54 +08:00
|
|
|
|
return event.get_type() == "message" and (
|
|
|
|
|
f"{bot.adapter.get_name().split(maxsplit=1)[0].lower()}:{event.get_user_id()}"
|
|
|
|
|
in bot.config.superusers
|
|
|
|
|
or event.get_user_id() in bot.config.superusers # 兼容旧配置
|
2021-12-06 10:10:51 +08:00
|
|
|
|
)
|
2020-12-10 02:13:25 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-19 16:16:56 +08:00
|
|
|
|
SUPERUSER: Permission = Permission(SuperUser())
|
|
|
|
|
"""匹配任意超级用户消息类型事件"""
|
|
|
|
|
|
|
|
|
|
__autodoc__ = {"Permission.__call__": True}
|