nonebot2/nonebot/permission.py

176 lines
4.9 KiB
Python
Raw Normal View History

r"""
2020-09-14 20:48:03 +08:00
权限
====
每个 ``Matcher`` 拥有一个 ``Permission`` 其中是 **异步** ``PermissionChecker`` 的集合只要有一个 ``PermissionChecker`` 检查结果为 ``True`` 时就会继续运行
\:\:\:tip 提示
``PermissionChecker`` 既可以是 async function 也可以是 sync function
\:\:\:
"""
2020-08-17 16:09:41 +08:00
import asyncio
from contextlib import AsyncExitStack
from typing import Any, Dict, List, Type, Union, Callable, NoReturn, Optional
2020-08-17 16:09:41 +08:00
from nonebot import params
from nonebot.handler import Handler
from nonebot.dependencies import Param
2021-11-14 18:51:23 +08:00
from nonebot.adapters import Bot, Event
2020-12-17 21:09:30 +08:00
from nonebot.typing import T_PermissionChecker
2020-12-06 02:30:19 +08:00
2020-08-17 16:09:41 +08:00
class Permission:
2021-05-30 11:07:27 +08:00
"""
:说明:
``Matcher`` 规则类当事件传递时 ``Matcher`` 运行前进行检查
:示例:
.. code-block:: python
Permission(async_function) | sync_function
# 等价于
from nonebot.utils import run_sync
Permission(async_function, run_sync(sync_function))
"""
2020-08-17 16:09:41 +08:00
__slots__ = ("checkers",)
HANDLER_PARAM_TYPES: List[Type[Param]] = [
params.BotParam, params.EventParam
]
def __init__(self,
*checkers: T_PermissionChecker,
dependency_overrides_provider: Optional[Any] = None) -> None:
2020-09-14 20:48:03 +08:00
"""
:参数:
2020-11-30 11:08:00 +08:00
* ``*checkers: T_PermissionChecker``: PermissionChecker
2020-09-14 20:48:03 +08:00
"""
self.checkers = set(
Handler(checker,
allow_types=self.HANDLER_PARAM_TYPES,
dependency_overrides_provider=dependency_overrides_provider)
for checker in checkers)
2020-09-14 20:48:03 +08:00
"""
:说明:
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
存储 ``PermissionChecker``
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
:类型:
2020-11-30 11:08:00 +08:00
* ``Set[Handler]``
2020-09-14 20:48:03 +08:00
"""
2020-08-17 16:09:41 +08:00
async def __call__(
self,
bot: Bot,
event: Event,
stack: Optional[AsyncExitStack] = None,
dependency_cache: Optional[Dict[Callable[..., Any],
Any]] = None) -> bool:
2020-09-14 20:48:03 +08:00
"""
:说明:
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
检查是否满足某个权限
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
:参数:
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
* ``bot: Bot``: Bot 对象
* ``event: Event``: Event 对象
* ``stack: Optional[AsyncExitStack]``: 异步上下文栈
* ``dependency_cache: Optional[Dict[Callable[..., Any], Any]]``: 依赖缓存
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
:返回:
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
- ``bool``
"""
2020-08-17 16:09:41 +08:00
if not self.checkers:
return True
results = await asyncio.gather(
checker(bot=bot,
event=event,
_stack=stack,
_dependency_cache=dependency_cache)
for checker in self.checkers)
2020-08-17 16:09:41 +08:00
return any(results)
def __and__(self, other) -> NoReturn:
raise RuntimeError("And operation between Permissions is not allowed.")
2020-09-27 18:05:13 +08:00
def __or__(
self, other: Optional[Union["Permission",
2020-12-17 21:09:30 +08:00
T_PermissionChecker]]) -> "Permission":
2020-09-27 18:05:13 +08:00
if other is None:
return self
elif isinstance(other, Permission):
return Permission(*self.checkers, *other.checkers)
2020-08-17 16:09:41 +08:00
else:
return Permission(*self.checkers, other)
2020-08-17 16:09:41 +08:00
2021-11-14 18:51:23 +08:00
async def _message(bot: Bot, event: Event) -> bool:
2020-12-09 19:57:49 +08:00
return event.get_type() == "message"
2020-08-17 16:09:41 +08:00
2021-11-14 18:51:23 +08:00
async def _notice(bot: Bot, event: Event) -> bool:
2020-12-09 19:57:49 +08:00
return event.get_type() == "notice"
2020-08-17 16:09:41 +08:00
2021-11-14 18:51:23 +08:00
async def _request(bot: Bot, event: Event) -> bool:
2020-12-09 19:57:49 +08:00
return event.get_type() == "request"
2020-08-17 16:09:41 +08:00
2021-11-14 18:51:23 +08:00
async def _metaevent(bot: Bot, event: Event) -> bool:
2020-12-09 19:57:49 +08:00
return event.get_type() == "meta_event"
2020-08-17 16:09:41 +08:00
MESSAGE = Permission(_message)
2020-09-14 20:48:03 +08:00
"""
- **说明**: 匹配任意 ``message`` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 message type Matcher
"""
2020-08-17 16:09:41 +08:00
NOTICE = Permission(_notice)
2020-09-14 20:48:03 +08:00
"""
- **说明**: 匹配任意 ``notice`` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 notice type Matcher
"""
2020-08-17 16:09:41 +08:00
REQUEST = Permission(_request)
2020-09-14 20:48:03 +08:00
"""
- **说明**: 匹配任意 ``request`` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 request type Matcher
"""
2020-08-17 16:09:41 +08:00
METAEVENT = Permission(_metaevent)
2020-09-14 20:48:03 +08:00
"""
- **说明**: 匹配任意 ``meta_event`` 类型事件仅在需要同时捕获不同类型事件时使用优先使用 meta_event type Matcher
"""
2020-08-17 16:09:41 +08:00
def USER(*user: str, perm: Optional[Permission] = None):
2020-09-14 20:48:03 +08:00
"""
:说明:
2020-11-30 11:08:00 +08:00
``event`` ``session_id`` 在白名单内且满足 perm
2020-11-30 11:08:00 +08:00
2020-09-14 20:48:03 +08:00
:参数:
2020-11-30 11:08:00 +08:00
2020-12-09 19:57:49 +08:00
* ``*user: str``: 白名单
* ``perm: Optional[Permission]``: 需要同时满足的权限
2020-09-14 20:48:03 +08:00
"""
2020-08-17 16:09:41 +08:00
2021-11-14 18:51:23 +08:00
async def _user(bot: Bot, event: Event) -> bool:
2021-09-27 00:19:30 +08:00
return bool(event.get_session_id() in user and
(perm is None or await perm(bot, event)))
2020-08-17 16:09:41 +08:00
return Permission(_user)
2021-11-14 18:51:23 +08:00
async def _superuser(bot: Bot, event: Event) -> bool:
return (event.get_type() == "message" and
event.get_user_id() in bot.config.superusers)
2020-12-10 02:13:25 +08:00
SUPERUSER = Permission(_superuser)
"""
- **说明**: 匹配任意超级用户消息类型事件
"""