diff --git a/docs/api/adapters/cqhttp.md b/docs/api/adapters/cqhttp.md deleted file mode 100644 index 7c73f1a7..00000000 --- a/docs/api/adapters/cqhttp.md +++ /dev/null @@ -1,686 +0,0 @@ ---- -contentSidebar: true -sidebarDepth: 0 ---- - -# NoneBot.adapters.cqhttp 模块 - -## CQHTTP (OneBot) v11 协议适配 - -协议详情请看: [CQHTTP](https://github.com/howmanybots/onebot/blob/master/README.md) | [OneBot](https://github.com/howmanybots/onebot/blob/master/README.md) - -# NoneBot.adapters.cqhttp.config 模块 - - -## _class_ `Config` - -CQHTTP 配置类 - - -* **配置项** - - - * `access_token` / `cqhttp_access_token`: CQHTTP 协议授权令牌 - - - * `secret` / `cqhttp_secret`: CQHTTP HTTP 上报数据签名口令 - - - * `ws_urls` / `cqhttp_ws_urls`: CQHTTP 正向 Websocket 连接 Bot ID、目标 URL 字典 - - -# NoneBot.adapters.cqhttp.utils 模块 - - -## `escape(s, *, escape_comma=True)` - - -* **说明** - - 对字符串进行 CQ 码转义。 - - - -* **参数** - - - * `s: str`: 需要转义的字符串 - - - * `escape_comma: bool`: 是否转义逗号(`,`)。 - - - -## `unescape(s)` - - -* **说明** - - 对字符串进行 CQ 码去转义。 - - - -* **参数** - - - * `s: str`: 需要转义的字符串 - - -# NoneBot.adapters.cqhttp.exception 模块 - - -## _exception_ `ActionFailed` - -基类:[`nonebot.exception.ActionFailed`](../exception.md#nonebot.exception.ActionFailed), `nonebot.adapters.cqhttp.exception.CQHTTPAdapterException` - - -* **说明** - - API 请求返回错误信息。 - - - -* **参数** - - - * `retcode: Optional[int]`: 错误码 - - - -## _exception_ `NetworkError` - -基类:[`nonebot.exception.NetworkError`](../exception.md#nonebot.exception.NetworkError), `nonebot.adapters.cqhttp.exception.CQHTTPAdapterException` - - -* **说明** - - 网络错误。 - - - -* **参数** - - - * `retcode: Optional[int]`: 错误码 - - -# NoneBot.adapters.cqhttp.bot 模块 - - -## _async_ `_check_reply(bot, event)` - - -* **说明** - - 检查消息中存在的回复,去除并赋值 `event.reply`, `event.to_me` - - - -* **参数** - - - * `bot: Bot`: Bot 对象 - - - * `event: Event`: Event 对象 - - - -## `_check_at_me(bot, event)` - - -* **说明** - - 检查消息开头或结尾是否存在 @机器人,去除并赋值 `event.to_me` - - - -* **参数** - - - * `bot: Bot`: Bot 对象 - - - * `event: Event`: Event 对象 - - - -## `_check_nickname(bot, event)` - - -* **说明** - - 检查消息开头是否存在昵称,去除并赋值 `event.to_me` - - - -* **参数** - - - * `bot: Bot`: Bot 对象 - - - * `event: Event`: Event 对象 - - - -## `_handle_api_result(result)` - - -* **说明** - - 处理 API 请求返回值。 - - - -* **参数** - - - * `result: Optional[Dict[str, Any]]`: API 返回数据 - - - -* **返回** - - - * `Any`: API 调用返回数据 - - - -* **异常** - - - * `ActionFailed`: API 调用失败 - - - -## _class_ `Bot` - -基类:[`nonebot.adapters._bot.Bot`](README.md#nonebot.adapters._bot.Bot) - -CQHTTP 协议 Bot 适配。继承属性参考 [BaseBot](./#class-basebot) 。 - - -### _property_ `type` - - -* 返回: `"cqhttp"` - - -### _async classmethod_ `check_permission(driver, request)` - - -* **说明** - - CQHTTP (OneBot) 协议鉴权。参考 [鉴权](https://github.com/howmanybots/onebot/blob/master/v11/specs/communication/authorization.md) - - - -### _async_ `handle_message(message)` - - -* **说明** - - 调用 [_check_reply](#async-check-reply-bot-event), [_check_at_me](#check-at-me-bot-event), [_check_nickname](#check-nickname-bot-event) 处理事件并转换为 [Event](#class-event) - - - -### _async_ `call_api(api, **data)` - - -* **说明** - - 调用 CQHTTP 协议 API - - - -* **参数** - - - * `api: str`: API 名称 - - - * `**data: Any`: API 参数 - - - -* **返回** - - - * `Any`: API 调用返回数据 - - - -* **异常** - - - * `NetworkError`: 网络错误 - - - * `ActionFailed`: API 调用失败 - - - -### _async_ `send(event, message, at_sender=False, **kwargs)` - - -* **说明** - - 根据 `event` 向触发事件的主体发送消息。 - - - -* **参数** - - - * `event: Event`: Event 对象 - - - * `message: Union[str, Message, MessageSegment]`: 要发送的消息 - - - * `at_sender: bool`: 是否 @ 事件主体 - - - * `**kwargs`: 覆盖默认参数 - - - -* **返回** - - - * `Any`: API 调用返回数据 - - - -* **异常** - - - * `ValueError`: 缺少 `user_id`, `group_id` - - - * `NetworkError`: 网络错误 - - - * `ActionFailed`: API 调用失败 - - -# NoneBot.adapters.cqhttp.message 模块 - - -## _class_ `MessageSegment` - -基类:[`nonebot.adapters._message.MessageSegment`](README.md#nonebot.adapters._message.MessageSegment)[`Message`] - -CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。 - - -### _classmethod_ `get_message_class()` - - -### `is_text()` - - -### _static_ `anonymous(ignore_failure=None)` - - -### _static_ `at(user_id)` - - -### _static_ `contact(type_, id)` - - -### _static_ `contact_group(group_id)` - - -### _static_ `contact_user(user_id)` - - -### _static_ `dice()` - - -### _static_ `face(id_)` - - -### _static_ `forward(id_)` - - -### _static_ `image(file, type_=None, cache=True, proxy=True, timeout=None)` - - -### _static_ `json(data)` - - -### _static_ `location(latitude, longitude, title=None, content=None)` - - -### _static_ `music(type_, id_)` - - -### _static_ `music_custom(url, audio, title, content=None, img_url=None)` - - -### _static_ `node(id_)` - - -### _static_ `node_custom(user_id, nickname, content)` - - -### _static_ `poke(type_, id_)` - - -### _static_ `record(file, magic=None, cache=None, proxy=None, timeout=None)` - - -### _static_ `reply(id_)` - - -### _static_ `rps()` - - -### _static_ `shake()` - - -### _static_ `share(url='', title='', content=None, image=None)` - - -### _static_ `text(text)` - - -### _static_ `video(file, cache=None, proxy=None, timeout=None)` - - -### _static_ `xml(data)` - - -### `type` - - -* 类型: `str` - - -* 说明: 消息段类型 - - -### `data` - - -* 类型: `Dict[str, Union[str, list]]` - - -* 说明: 消息段数据 - - -## _class_ `Message` - -基类:[`nonebot.adapters._message.Message`](README.md#nonebot.adapters._message.Message)[`nonebot.adapters.cqhttp.message.MessageSegment`] - -CQHTTP 协议 Message 适配。 - - -### _classmethod_ `get_segment_class()` - - -### `extract_plain_text()` - -# NoneBot.adapters.cqhttp.permission 模块 - - -## `PRIVATE` - - -* **说明**: 匹配任意私聊消息类型事件 - - -## `PRIVATE_FRIEND` - - -* **说明**: 匹配任意好友私聊消息类型事件 - - -## `PRIVATE_GROUP` - - -* **说明**: 匹配任意群临时私聊消息类型事件 - - -## `PRIVATE_OTHER` - - -* **说明**: 匹配任意其他私聊消息类型事件 - - -## `GROUP` - - -* **说明**: 匹配任意群聊消息类型事件 - - -## `GROUP_MEMBER` - - -* **说明**: 匹配任意群员群聊消息类型事件 - -:::warning 警告 -该权限通过 event.sender 进行判断且不包含管理员以及群主! -::: - - -## `GROUP_ADMIN` - - -* **说明**: 匹配任意群管理员群聊消息类型事件 - - -## `GROUP_OWNER` - - -* **说明**: 匹配任意群主群聊消息类型事件 - -# NoneBot.adapters.cqhttp.event 模块 - - -## _class_ `Event` - -基类:[`nonebot.adapters._event.Event`](README.md#nonebot.adapters._event.Event) - -CQHTTP 协议事件,字段与 CQHTTP 一致。各事件字段参考 [CQHTTP 文档](https://github.com/howmanybots/onebot/blob/master/README.md) - - -## _class_ `MessageEvent` - -基类:`nonebot.adapters.cqhttp.event.Event` - -消息事件 - - -### `to_me` - - -* **说明** - - 消息是否与机器人有关 - - - -* **类型** - - `bool` - - - -### `reply` - - -* **说明** - - 消息中提取的回复消息,内容为 `get_msg` API 返回结果 - - - -* **类型** - - `Optional[Reply]` - - - -## _class_ `PrivateMessageEvent` - -基类:`nonebot.adapters.cqhttp.event.MessageEvent` - -私聊消息 - - -## _class_ `GroupMessageEvent` - -基类:`nonebot.adapters.cqhttp.event.MessageEvent` - -群消息 - - -## _class_ `NoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.Event` - -通知事件 - - -## _class_ `GroupUploadNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群文件上传事件 - - -## _class_ `GroupAdminNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群管理员变动 - - -## _class_ `GroupDecreaseNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群成员减少事件 - - -## _class_ `GroupIncreaseNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群成员增加事件 - - -## _class_ `GroupBanNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群禁言事件 - - -## _class_ `FriendAddNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -好友添加事件 - - -## _class_ `GroupRecallNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -群消息撤回事件 - - -## _class_ `FriendRecallNoticeEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -好友消息撤回事件 - - -## _class_ `NotifyEvent` - -基类:`nonebot.adapters.cqhttp.event.NoticeEvent` - -提醒事件 - - -## _class_ `PokeNotifyEvent` - -基类:`nonebot.adapters.cqhttp.event.NotifyEvent` - -戳一戳提醒事件 - - -## _class_ `LuckyKingNotifyEvent` - -基类:`nonebot.adapters.cqhttp.event.NotifyEvent` - -群红包运气王提醒事件 - - -## _class_ `HonorNotifyEvent` - -基类:`nonebot.adapters.cqhttp.event.NotifyEvent` - -群荣誉变更提醒事件 - - -## _class_ `RequestEvent` - -基类:`nonebot.adapters.cqhttp.event.Event` - -请求事件 - - -## _class_ `FriendRequestEvent` - -基类:`nonebot.adapters.cqhttp.event.RequestEvent` - -加好友请求事件 - - -## _class_ `GroupRequestEvent` - -基类:`nonebot.adapters.cqhttp.event.RequestEvent` - -加群请求/邀请事件 - - -## _class_ `MetaEvent` - -基类:`nonebot.adapters.cqhttp.event.Event` - -元事件 - - -## _class_ `LifecycleMetaEvent` - -基类:`nonebot.adapters.cqhttp.event.MetaEvent` - -生命周期元事件 - - -## _class_ `HeartbeatMetaEvent` - -基类:`nonebot.adapters.cqhttp.event.MetaEvent` - -心跳元事件 - - -## `get_event_model(event_name)` - - -* **说明** - - 根据事件名获取对应 `Event Model` 及 `FallBack Event Model` 列表 - - - -* **返回** - - - * `List[Type[Event]]` diff --git a/docs_build/adapters/cqhttp.rst b/docs_build/adapters/cqhttp.rst deleted file mode 100644 index d49c5c66..00000000 --- a/docs_build/adapters/cqhttp.rst +++ /dev/null @@ -1,60 +0,0 @@ -\-\-\- -contentSidebar: true -sidebarDepth: 0 -\-\-\- - -NoneBot.adapters.cqhttp 模块 -============================= - -.. automodule:: nonebot.adapters.cqhttp - -NoneBot.adapters.cqhttp.config 模块 -=================================== - -.. automodule:: nonebot.adapters.cqhttp.config - :members: - -NoneBot.adapters.cqhttp.utils 模块 -=================================== - -.. automodule:: nonebot.adapters.cqhttp.utils - :members: - :show-inheritance: - -NoneBot.adapters.cqhttp.exception 模块 -======================================= - -.. automodule:: nonebot.adapters.cqhttp.exception - :members: - :show-inheritance: - -NoneBot.adapters.cqhttp.bot 模块 -================================= - -.. automodule:: nonebot.adapters.cqhttp.bot - :members: - :private-members: - :show-inheritance: - -NoneBot.adapters.cqhttp.message 模块 -===================================== - -.. automodule:: nonebot.adapters.cqhttp.message - :members: - :undoc-members: - :show-inheritance: - -NoneBot.adapters.cqhttp.permission 模块 -======================================== - -.. automodule:: nonebot.adapters.cqhttp.permission - :members: - :show-inheritance: - -NoneBot.adapters.cqhttp.event 模块 -=================================== - -.. automodule:: nonebot.adapters.cqhttp.event - :members: - :private-members: - :show-inheritance: diff --git a/nonebot/plugins/echo.py b/nonebot/plugins/echo.py index 42e99cc3..a070fc11 100644 --- a/nonebot/plugins/echo.py +++ b/nonebot/plugins/echo.py @@ -1,32 +1,10 @@ -from functools import reduce - from nonebot.rule import to_me +from nonebot.adapters import Event from nonebot.plugin import on_command -from nonebot.permission import SUPERUSER -from nonebot.adapters.cqhttp import ( - Message, - MessageEvent, - MessageSegment, - unescape, -) - -say = on_command("say", to_me(), permission=SUPERUSER) - - -@say.handle() -async def say_unescape(event: MessageEvent): - def _unescape(message: Message, segment: MessageSegment): - if segment.is_text(): - return message.append(unescape(str(segment))) - return message.append(segment) - - message = reduce(_unescape, event.get_message(), Message()) # type: ignore - await say.send(message=message) - echo = on_command("echo", to_me()) @echo.handle() -async def echo_escape(event: MessageEvent): +async def echo_escape(event: Event): await echo.send(message=event.get_message()) diff --git a/packages/nonebot-adapter-cqhttp/README.md b/packages/nonebot-adapter-cqhttp/README.md deleted file mode 100644 index 5191dcbb..00000000 --- a/packages/nonebot-adapter-cqhttp/README.md +++ /dev/null @@ -1,11 +0,0 @@ -

- nonebot -

- -
- -# NoneBot-Adapter-CQHTTP - -_✨ OneBot(CQHTTP) 协议适配 ✨_ - -
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/__init__.py b/packages/nonebot-adapter-cqhttp/nonebot/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/__init__.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/__init__.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/__init__.py deleted file mode 100644 index 74ac3c47..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -CQHTTP (OneBot) v11 协议适配 -============================ - -协议详情请看: `CQHTTP`_ | `OneBot`_ - -.. _CQHTTP: - https://github.com/howmanybots/onebot/blob/master/README.md -.. _OneBot: - https://github.com/howmanybots/onebot/blob/master/README.md -""" - -from .event import * -from .permission import * -from .bot import Bot as Bot -from .utils import log as log -from .utils import escape as escape -from .message import Message as Message -from .utils import unescape as unescape -from .exception import ActionFailed as ActionFailed -from .exception import NetworkError as NetworkError -from .message import MessageSegment as MessageSegment -from .exception import ApiNotAvailable as ApiNotAvailable -from .exception import CQHTTPAdapterException as CQHTTPAdapterException diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py deleted file mode 100644 index be88edce..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py +++ /dev/null @@ -1,489 +0,0 @@ -import re -import sys -import hmac -import json -import asyncio -from typing import TYPE_CHECKING, Any, Dict, Tuple, Union, Optional - -import httpx - -from nonebot.log import logger -from nonebot.typing import overrides -from nonebot.message import handle_event -from nonebot.adapters import Bot as BaseBot -from nonebot.utils import DataclassEncoder, escape_tag -from nonebot.drivers import ( - Driver, - WebSocket, - HTTPRequest, - HTTPResponse, - ForwardDriver, - HTTPConnection, - WebSocketSetup, -) - -from .utils import log, escape -from .config import Config as CQHTTPConfig -from .message import Message, MessageSegment -from .event import Event, Reply, MessageEvent, get_event_model -from .exception import ActionFailed, NetworkError, ApiNotAvailable - -if TYPE_CHECKING: - from nonebot.config import Config - - -def get_auth_bearer(access_token: Optional[str] = None) -> Optional[str]: - if not access_token: - return None - scheme, _, param = access_token.partition(" ") - if scheme.lower() not in ["bearer", "token"]: - return None - return param - - -async def _check_reply(bot: "Bot", event: "Event"): - """ - :说明: - - 检查消息中存在的回复,去除并赋值 ``event.reply``, ``event.to_me`` - - :参数: - - * ``bot: Bot``: Bot 对象 - * ``event: Event``: Event 对象 - """ - if not isinstance(event, MessageEvent): - return - - try: - index = list(map(lambda x: x.type == "reply", event.message)).index(True) - except ValueError: - return - msg_seg = event.message[index] - try: - event.reply = Reply.parse_obj(await bot.get_msg(message_id=msg_seg.data["id"])) - except Exception as e: - log("WARNING", f"Error when getting message reply info: {repr(e)}", e) - return - # ensure string comparation - if str(event.reply.sender.user_id) == str(event.self_id): - event.to_me = True - del event.message[index] - if len(event.message) > index and event.message[index].type == "at": - del event.message[index] - if len(event.message) > index and event.message[index].type == "text": - event.message[index].data["text"] = event.message[index].data["text"].lstrip() - if not event.message[index].data["text"]: - del event.message[index] - if not event.message: - event.message.append(MessageSegment.text("")) - - -def _check_at_me(bot: "Bot", event: "Event"): - """ - :说明: - - 检查消息开头或结尾是否存在 @机器人,去除并赋值 ``event.to_me`` - - :参数: - - * ``bot: Bot``: Bot 对象 - * ``event: Event``: Event 对象 - """ - if not isinstance(event, MessageEvent): - return - - # ensure message not empty - if not event.message: - event.message.append(MessageSegment.text("")) - - if event.message_type == "private": - event.to_me = True - else: - - def _is_at_me_seg(segment: MessageSegment): - return segment.type == "at" and str(segment.data.get("qq", "")) == str( - event.self_id - ) - - # check the first segment - if _is_at_me_seg(event.message[0]): - event.to_me = True - event.message.pop(0) - if event.message and event.message[0].type == "text": - event.message[0].data["text"] = event.message[0].data["text"].lstrip() - if not event.message[0].data["text"]: - del event.message[0] - if event.message and _is_at_me_seg(event.message[0]): - event.message.pop(0) - if event.message and event.message[0].type == "text": - event.message[0].data["text"] = ( - event.message[0].data["text"].lstrip() - ) - if not event.message[0].data["text"]: - del event.message[0] - - if not event.to_me: - # check the last segment - i = -1 - last_msg_seg = event.message[i] - if ( - last_msg_seg.type == "text" - and not last_msg_seg.data["text"].strip() - and len(event.message) >= 2 - ): - i -= 1 - last_msg_seg = event.message[i] - - if _is_at_me_seg(last_msg_seg): - event.to_me = True - del event.message[i:] - - if not event.message: - event.message.append(MessageSegment.text("")) - - -def _check_nickname(bot: "Bot", event: "Event"): - """ - :说明: - - 检查消息开头是否存在昵称,去除并赋值 ``event.to_me`` - - :参数: - - * ``bot: Bot``: Bot 对象 - * ``event: Event``: Event 对象 - """ - if not isinstance(event, MessageEvent): - return - - first_msg_seg = event.message[0] - if first_msg_seg.type != "text": - return - - first_text = first_msg_seg.data["text"] - - nicknames = set(filter(lambda n: n, bot.config.nickname)) - if nicknames: - # check if the user is calling me with my nickname - nickname_regex = "|".join(nicknames) - m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text, re.IGNORECASE) - if m: - nickname = m.group(1) - log("DEBUG", f"User is calling me {nickname}") - event.to_me = True - first_msg_seg.data["text"] = first_text[m.end() :] - - -def _handle_api_result(result: Optional[Dict[str, Any]]) -> Any: - """ - :说明: - - 处理 API 请求返回值。 - - :参数: - - * ``result: Optional[Dict[str, Any]]``: API 返回数据 - - :返回: - - - ``Any``: API 调用返回数据 - - :异常: - - - ``ActionFailed``: API 调用失败 - """ - if isinstance(result, dict): - if result.get("status") == "failed": - raise ActionFailed(**result) - return result.get("data") - - -class ResultStore: - _seq = 1 - _futures: Dict[int, asyncio.Future] = {} - - @classmethod - def get_seq(cls) -> int: - s = cls._seq - cls._seq = (cls._seq + 1) % sys.maxsize - return s - - @classmethod - def add_result(cls, result: Dict[str, Any]): - if isinstance(result.get("echo"), dict) and isinstance( - result["echo"].get("seq"), int - ): - future = cls._futures.get(result["echo"]["seq"]) - if future: - future.set_result(result) - - @classmethod - async def fetch(cls, seq: int, timeout: Optional[float]) -> Dict[str, Any]: - future = asyncio.get_event_loop().create_future() - cls._futures[seq] = future - try: - return await asyncio.wait_for(future, timeout) - except asyncio.TimeoutError: - raise NetworkError("WebSocket API call timeout") from None - finally: - del cls._futures[seq] - - -class Bot(BaseBot): - """ - CQHTTP 协议 Bot 适配。继承属性参考 `BaseBot <./#class-basebot>`_ 。 - """ - - cqhttp_config: CQHTTPConfig - - @property - @overrides(BaseBot) - def type(self) -> str: - """ - - 返回: ``"cqhttp"`` - """ - return "cqhttp" - - @classmethod - def register(cls, driver: Driver, config: "Config"): - super().register(driver, config) - cls.cqhttp_config = CQHTTPConfig(**config.dict()) - if not isinstance(driver, ForwardDriver) and cls.cqhttp_config.ws_urls: - logger.warning( - f"Current driver {cls.config.driver} don't support forward connections" - ) - elif isinstance(driver, ForwardDriver) and cls.cqhttp_config.ws_urls: - for self_id, url in cls.cqhttp_config.ws_urls.items(): - try: - headers = ( - {"authorization": f"Bearer {cls.cqhttp_config.access_token}"} - if cls.cqhttp_config.access_token - else {} - ) - driver.setup_websocket( - WebSocketSetup("cqhttp", self_id, url, headers=headers) - ) - except Exception as e: - logger.opt(colors=True, exception=e).error( - f"Bad url {escape_tag(url)} for bot {escape_tag(self_id)} " - "in cqhttp forward websocket" - ) - - @classmethod - @overrides(BaseBot) - async def check_permission( - cls, driver: Driver, request: HTTPConnection - ) -> Tuple[Optional[str], HTTPResponse]: - """ - :说明: - - CQHTTP (OneBot) 协议鉴权。参考 `鉴权 `_ - """ - x_self_id = request.headers.get("x-self-id") - x_signature = request.headers.get("x-signature") - token = get_auth_bearer(request.headers.get("authorization")) - cqhttp_config = CQHTTPConfig(**driver.config.dict()) - - # 检查self_id - if not x_self_id: - log("WARNING", "Missing X-Self-ID Header") - return None, HTTPResponse(400, b"Missing X-Self-ID Header") - - # 检查签名 - secret = cqhttp_config.secret - if secret and isinstance(request, HTTPRequest): - if not x_signature: - log("WARNING", "Missing Signature Header") - return None, HTTPResponse(401, b"Missing Signature") - sig = hmac.new(secret.encode("utf-8"), request.body, "sha1").hexdigest() - if x_signature != "sha1=" + sig: - log("WARNING", "Signature Header is invalid") - return None, HTTPResponse(403, b"Signature is invalid") - - access_token = cqhttp_config.access_token - if access_token and access_token != token and isinstance(request, WebSocket): - log( - "WARNING", - "Authorization Header is invalid" - if token - else "Missing Authorization Header", - ) - return None, HTTPResponse( - 403, - b"Authorization Header is invalid" - if token - else b"Missing Authorization Header", - ) - return str(x_self_id), HTTPResponse(204, b"") - - @overrides(BaseBot) - async def handle_message(self, message: bytes): - """ - :说明: - - 调用 `_check_reply <#async-check-reply-bot-event>`_, `_check_at_me <#check-at-me-bot-event>`_, `_check_nickname <#check-nickname-bot-event>`_ 处理事件并转换为 `Event <#class-event>`_ - """ - data: dict = json.loads(message) - - if not data: - return - - if "post_type" not in data: - ResultStore.add_result(data) - return - - try: - post_type = data["post_type"] - detail_type = data.get(f"{post_type}_type") - detail_type = f".{detail_type}" if detail_type else "" - sub_type = data.get("sub_type") - sub_type = f".{sub_type}" if sub_type else "" - models = get_event_model(post_type + detail_type + sub_type) - for model in models: - try: - event = model.parse_obj(data) - break - except Exception as e: - log("DEBUG", "Event Parser Error", e) - else: - event = Event.parse_obj(data) - - # Check whether user is calling me - await _check_reply(self, event) - _check_at_me(self, event) - _check_nickname(self, event) - - await handle_event(self, event) - except Exception as e: - logger.opt(colors=True, exception=e).error( - f"Failed to handle event. Raw: {escape_tag(str(data))}" - ) - - @overrides(BaseBot) - async def _call_api(self, api: str, **data) -> Any: - log("DEBUG", f"Calling API {api}") - if isinstance(self.request, WebSocket): - seq = ResultStore.get_seq() - json_data = json.dumps( - {"action": api, "params": data, "echo": {"seq": seq}}, - cls=DataclassEncoder, - ) - await self.request.send(json_data) - return _handle_api_result( - await ResultStore.fetch(seq, self.config.api_timeout) - ) - - elif isinstance(self.request, HTTPRequest): - api_root = self.config.api_root.get(self.self_id) - if not api_root: - raise ApiNotAvailable - elif not api_root.endswith("/"): - api_root += "/" - - headers = {"Content-Type": "application/json"} - if self.cqhttp_config.access_token is not None: - headers["Authorization"] = "Bearer " + self.cqhttp_config.access_token - - try: - async with httpx.AsyncClient( - headers=headers, follow_redirects=True - ) as client: - response = await client.post( - api_root + api, - content=json.dumps(data, cls=DataclassEncoder), - timeout=self.config.api_timeout, - ) - - if 200 <= response.status_code < 300: - result = response.json() - return _handle_api_result(result) - raise NetworkError( - f"HTTP request received unexpected " - f"status code: {response.status_code}" - ) - except httpx.InvalidURL: - raise NetworkError("API root url invalid") - except httpx.HTTPError: - raise NetworkError("HTTP request failed") - - @overrides(BaseBot) - async def call_api(self, api: str, **data) -> Any: - """ - :说明: - - 调用 CQHTTP 协议 API - - :参数: - - * ``api: str``: API 名称 - * ``**data: Any``: API 参数 - - :返回: - - - ``Any``: API 调用返回数据 - - :异常: - - - ``NetworkError``: 网络错误 - - ``ActionFailed``: API 调用失败 - """ - return await super().call_api(api, **data) - - @overrides(BaseBot) - async def send( - self, - event: Event, - message: Union[str, Message, MessageSegment], - at_sender: bool = False, - **kwargs, - ) -> Any: - """ - :说明: - - 根据 ``event`` 向触发事件的主体发送消息。 - - :参数: - - * ``event: Event``: Event 对象 - * ``message: Union[str, Message, MessageSegment]``: 要发送的消息 - * ``at_sender: bool``: 是否 @ 事件主体 - * ``**kwargs``: 覆盖默认参数 - - :返回: - - - ``Any``: API 调用返回数据 - - :异常: - - - ``ValueError``: 缺少 ``user_id``, ``group_id`` - - ``NetworkError``: 网络错误 - - ``ActionFailed``: API 调用失败 - """ - message = ( - escape(message, escape_comma=False) if isinstance(message, str) else message - ) - msg = message if isinstance(message, Message) else Message(message) - - at_sender = at_sender and bool(getattr(event, "user_id", None)) - - params = {} - if getattr(event, "user_id", None): - params["user_id"] = getattr(event, "user_id") - if getattr(event, "group_id", None): - params["group_id"] = getattr(event, "group_id") - params.update(kwargs) - - if "message_type" not in params: - if params.get("group_id", None): - params["message_type"] = "group" - elif params.get("user_id", None): - params["message_type"] = "private" - else: - raise ValueError("Cannot guess message type to reply!") - - if at_sender and params["message_type"] != "private": - params["message"] = MessageSegment.at(params["user_id"]) + " " + msg - else: - params["message"] = msg - return await self.send_msg(**params) diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi deleted file mode 100644 index 39ad4122..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi +++ /dev/null @@ -1,726 +0,0 @@ -import asyncio -from typing import Any, Dict, List, Union, Optional - -from nonebot.config import Config -from nonebot.adapters import Bot as BaseBot -from nonebot.drivers import Driver, WebSocket - -from .event import Event -from .message import Message, MessageSegment - -def get_auth_bearer(access_token: Optional[str] = ...) -> Optional[str]: - ... - - -async def _check_reply(bot: "Bot", event: Event): - ... - - -def _check_at_me(bot: "Bot", event: Event): - ... - - -def _check_nickname(bot: "Bot", event: Event): - ... - - -def _handle_api_result(result: Optional[Dict[str, Any]]) -> Any: - ... - - -class ResultStore: - _seq: int = ... - _futures: Dict[int, asyncio.Future] = ... - - @classmethod - def get_seq(cls) -> int: - ... - - @classmethod - def add_result(cls, result: Dict[str, Any]): - ... - - @classmethod - async def fetch(cls, seq: int, timeout: Optional[float]) -> Dict[str, Any]: - ... - - -class Bot(BaseBot): - - def __init__(self, - driver: Driver, - connection_type: str, - config: Config, - self_id: str, - *, - websocket: WebSocket = None): - ... - - def type(self) -> str: - ... - - @classmethod - async def check_permission(cls, driver: Driver, connection_type: str, - headers: dict, body: Optional[dict]) -> str: - ... - - async def handle_message(self, message: dict): - ... - - async def call_api(self, api: str, *, **data) -> Any: - ... - - async def send(self, event: Event, message: Union[str, Message, - MessageSegment], - **kwargs) -> Any: - ... - - async def send_private_msg( - self, - *, - user_id: int, - message: Union[str, Message], - auto_escape: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 发送私聊消息。 - - :参数: - - * ``user_id``: 对方 QQ 号 - * ``message``: 要发送的内容 - * ``auto_escape``: 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 ``message`` 字段是字符串时有效 - - """ - ... - - async def send_group_msg( - self, - *, - group_id: int, - message: Union[str, Message], - auto_escape: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 发送群消息。 - - :参数: - - * ``group_id``: 群号 - * ``message``: 要发送的内容 - * ``auto_escape``: 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 ``message`` 字段是字符串时有效 - - """ - ... - - async def send_msg( - self, - *, - message_type: Optional[str] = ..., - user_id: Optional[int] = ..., - group_id: Optional[int] = ..., - message: Union[str, Message], - auto_escape: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 发送消息。 - - :参数: - - * ``message_type``: 消息类型,支持 ``private``、``group``,分别对应私聊、群组、讨论组,如不传入,则根据传入的 ``*_id`` 参数判断 - * ``user_id``: 对方 QQ 号(消息类型为 ``private`` 时需要) - * ``group_id``: 群号(消息类型为 ``group`` 时需要) - * ``message``: 要发送的内容 - * ``auto_escape``: 消息内容是否作为纯文本发送(即不解析 CQ 码),只在 ``message`` 字段是字符串时有效 - - """ - ... - - async def delete_msg( - self, - *, - message_id: int, - ) -> None: - """ - :说明: - - 撤回消息。 - - :参数: - - * ``message_id``: 消息 ID - - """ - ... - - async def get_msg( - self, - *, - message_id: int, - ) -> Dict[str, Any]: - """ - :说明: - - 获取消息。 - - :参数: - - * ``message_id``: 消息 ID - - """ - ... - - async def get_forward_msg( - self, - *, - id: str, - ) -> None: - """ - :说明: - - 获取合并转发消息。 - - :参数: - - * ``id``: 合并转发 ID - - """ - ... - - async def send_like( - self, - *, - user_id: int, - times: int = ..., - ) -> None: - """ - :说明: - - 发送好友赞。 - - :参数: - - * ``user_id``: 对方 QQ 号 - * ``times``: 赞的次数,每个好友每天最多 10 次 - - """ - ... - - async def set_group_kick( - self, - *, - group_id: int, - user_id: int, - reject_add_request: bool = ..., - ) -> None: - """ - :说明: - - 群组踢人。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: 要踢的 QQ 号 - * ``reject_add_request``: 拒绝此人的加群请求 - - """ - ... - - async def set_group_ban( - self, - *, - group_id: int, - user_id: int, - duration: int = ..., - ) -> None: - """ - :说明: - - 群组单人禁言。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: 要禁言的 QQ 号 - * ``duration``: 禁言时长,单位秒,``0`` 表示取消禁言 - - """ - ... - - async def set_group_anonymous_ban( - self, - *, - group_id: int, - anonymous: Optional[Dict[str, Any]] = ..., - anonymous_flag: Optional[str] = ..., - duration: int = ..., - ) -> None: - """ - :说明: - - 群组匿名用户禁言。 - - :参数: - - * ``group_id``: 群号 - * ``anonymous``: 可选,要禁言的匿名用户对象(群消息上报的 ``anonymous`` 字段) - * ``anonymous_flag``: 可选,要禁言的匿名用户的 flag(需从群消息上报的数据中获得) - * ``duration``: 禁言时长,单位秒,无法取消匿名用户禁言 - - """ - ... - - async def set_group_whole_ban( - self, - *, - group_id: int, - enable: bool = ..., - ) -> None: - """ - :说明: - - 群组全员禁言。 - - :参数: - - * ``group_id``: 群号 - * ``enable``: 是否禁言 - - """ - ... - - async def set_group_admin( - self, - *, - group_id: int, - user_id: int, - enable: bool = ..., - ) -> None: - """ - :说明: - - 群组设置管理员。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: 要设置管理员的 QQ 号 - * ``enable``: ``True`` 为设置,``False`` 为取消 - - """ - ... - - async def set_group_anonymous( - self, - *, - group_id: int, - enable: bool = ..., - ) -> None: - """ - :说明: - - 群组匿名。 - - :参数: - - * ``group_id``: 群号 - * ``enable``: 是否允许匿名聊天 - - """ - ... - - async def set_group_card( - self, - *, - group_id: int, - user_id: int, - card: str = ..., - ) -> None: - """ - :说明: - - 设置群名片(群备注)。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: 要设置的 QQ 号 - * ``card``: 群名片内容,不填或空字符串表示删除群名片 - - """ - ... - - async def set_group_name( - self, - *, - group_id: int, - group_name: str, - ) -> None: - """ - :说明: - - 设置群名。 - - :参数: - - * ``group_id``: 群号 - * ``group_name``: 新群名 - - """ - ... - - async def set_group_leave( - self, - *, - group_id: int, - is_dismiss: bool = ..., - ) -> None: - """ - :说明: - - 退出群组。 - - :参数: - - * ``group_id``: 群号 - * ``is_dismiss``: 是否解散,如果登录号是群主,则仅在此项为 True 时能够解散 - - """ - ... - - async def set_group_special_title( - self, - *, - group_id: int, - user_id: int, - special_title: str = ..., - duration: int = ..., - ) -> None: - """ - :说明: - - 设置群组专属头衔。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: 要设置的 QQ 号 - * ``special_title``: 专属头衔,不填或空字符串表示删除专属头衔 - * ``duration``: 专属头衔有效期,单位秒,-1 表示永久,不过此项似乎没有效果,可能是只有某些特殊的时间长度有效,有待测试 - - """ - ... - - async def set_friend_add_request( - self, - *, - flag: str, - approve: bool = ..., - remark: str = ..., - ) -> None: - """ - :说明: - - 处理加好友请求。 - - :参数: - - * ``flag``: 加好友请求的 flag(需从上报的数据中获得) - * ``approve``: 是否同意请求 - * ``remark``: 添加后的好友备注(仅在同意时有效) - - """ - ... - - async def set_group_add_request( - self, - *, - flag: str, - sub_type: str, - approve: bool = ..., - reason: str = ..., - ) -> None: - """ - :说明: - - 处理加群请求/邀请。 - - :参数: - - * ``flag``: 加群请求的 flag(需从上报的数据中获得) - * ``sub_type``: ``add`` 或 ``invite``,请求类型(需要和上报消息中的 ``sub_type`` 字段相符) - * ``approve``: 是否同意请求/邀请 - * ``reason``: 拒绝理由(仅在拒绝时有效) - - """ - ... - - async def get_login_info(self) -> Dict[str, Any]: - """ - :说明: - - 获取登录号信息。 - - """ - ... - - async def get_stranger_info( - self, - *, - user_id: int, - no_cache: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取陌生人信息。 - - :参数: - - * ``user_id``: QQ 号 - * ``no_cache``: 是否不使用缓存(使用缓存可能更新不及时,但响应更快) - - """ - ... - - async def get_friend_list(self) -> List[Dict[str, Any]]: - """ - :说明: - - 获取好友列表。 - - """ - ... - - async def get_group_info( - self, - *, - group_id: int, - no_cache: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取群信息。 - - :参数: - - * ``group_id``: 群号 - * ``no_cache``: 是否不使用缓存(使用缓存可能更新不及时,但响应更快) - - """ - ... - - async def get_group_list(self) -> List[Dict[str, Any]]: - """ - :说明: - - 获取群列表。 - - """ - ... - - async def get_group_member_info( - self, - *, - group_id: int, - user_id: int, - no_cache: bool = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取群成员信息。 - - :参数: - - * ``group_id``: 群号 - * ``user_id``: QQ 号 - * ``no_cache``: 是否不使用缓存(使用缓存可能更新不及时,但响应更快) - - """ - ... - - async def get_group_member_list( - self, - *, - group_id: int, - ) -> List[Dict[str, Any]]: - """ - :说明: - - 获取群成员列表。 - - :参数: - - * ``group_id``: 群号 - - """ - ... - - async def get_group_honor_info( - self, - *, - group_id: int, - type: str = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取群荣誉信息。 - - :参数: - - * ``group_id``: 群号 - * ``type``: 要获取的群荣誉类型,可传入 ``talkative`` ``performer`` ``legend`` ``strong_newbie`` ``emotion`` 以分别获取单个类型的群荣誉数据,或传入 ``all`` 获取所有数据 - - """ - ... - - async def get_cookies( - self, - *, - domain: str = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取 Cookies。 - - :参数: - - * ``domain``: 需要获取 cookies 的域名 - - """ - ... - - async def get_csrf_token(self) -> Dict[str, Any]: - """ - :说明: - - 获取 CSRF Token。 - - """ - ... - - async def get_credentials( - self, - *, - domain: str = ..., - ) -> Dict[str, Any]: - """ - :说明: - - 获取 QQ 相关接口凭证。 - - :参数: - - * ``domain``: 需要获取 cookies 的域名 - - """ - ... - - async def get_record( - self, - *, - file: str, - out_format: str, - ) -> Dict[str, Any]: - """ - :说明: - - 获取语音。 - - :参数: - - * ``file``: 收到的语音文件名(CQ 码的 ``file`` 参数),如 ``0B38145AA44505000B38145AA4450500.silk`` - * ``out_format``: 要转换到的格式,目前支持 ``mp3``、``amr``、``wma``、``m4a``、``spx``、``ogg``、``wav``、``flac`` - - """ - ... - - async def get_image( - self, - *, - file: str, - ) -> Dict[str, Any]: - """ - :说明: - - 获取图片。 - - :参数: - - * ``file``: 收到的图片文件名(CQ 码的 ``file`` 参数),如 ``6B4DE3DFD1BD271E3297859D41C530F5.jpg`` - - """ - ... - - async def can_send_image(self) -> Dict[str, Any]: - """ - :说明: - - 检查是否可以发送图片。 - - """ - ... - - async def can_send_record(self) -> Dict[str, Any]: - """ - :说明: - - 检查是否可以发送语音。 - - """ - ... - - async def get_status(self) -> Dict[str, Any]: - """ - :说明: - - 获取插件运行状态。 - - """ - ... - - async def get_version_info(self) -> Dict[str, Any]: - """ - :说明: - - 获取版本信息。 - - """ - ... - - async def set_restart( - self, - *, - delay: int = ..., - ) -> None: - """ - :说明: - - 重启 OneBot 实现。 - - :参数: - - * ``delay``: 要延迟的毫秒数,如果默认情况下无法重启,可以尝试设置延迟为 2000 左右 - - """ - ... - - async def clean_cache(self) -> None: - """ - :说明: - - 清理数据目录。 - - """ - ... diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py deleted file mode 100644 index 12908073..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py +++ /dev/null @@ -1,24 +0,0 @@ -from typing import Dict, Optional - -from pydantic import Field, AnyUrl, BaseModel - - -# priority: alias > origin -class Config(BaseModel): - """ - CQHTTP 配置类 - - :配置项: - - - ``access_token`` / ``cqhttp_access_token``: CQHTTP 协议授权令牌 - - ``secret`` / ``cqhttp_secret``: CQHTTP HTTP 上报数据签名口令 - - ``ws_urls`` / ``cqhttp_ws_urls``: CQHTTP 正向 Websocket 连接 Bot ID、目标 URL 字典 - """ - - access_token: Optional[str] = Field(default=None, alias="cqhttp_access_token") - secret: Optional[str] = Field(default=None, alias="cqhttp_secret") - ws_urls: Dict[str, AnyUrl] = Field(default_factory=set, alias="cqhttp_ws_urls") - - class Config: - extra = "ignore" - allow_population_by_field_name = True diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py deleted file mode 100644 index 21c7b34c..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py +++ /dev/null @@ -1,633 +0,0 @@ -import inspect -from typing_extensions import Literal -from typing import TYPE_CHECKING, List, Type, Optional - -from pydantic import BaseModel -from pygtrie import StringTrie - -from nonebot.typing import overrides -from nonebot.utils import escape_tag -from nonebot.adapters import Event as BaseEvent - -from .message import Message -from .exception import NoLogException - -if TYPE_CHECKING: - from .bot import Bot - - -class Event(BaseEvent): - """ - CQHTTP 协议事件,字段与 CQHTTP 一致。各事件字段参考 `CQHTTP 文档`_ - - .. _CQHTTP 文档: - https://github.com/howmanybots/onebot/blob/master/README.md - """ - - __event__ = "" - time: int - self_id: int - post_type: str - - @overrides(BaseEvent) - def get_type(self) -> str: - return self.post_type - - @overrides(BaseEvent) - def get_event_name(self) -> str: - return self.post_type - - @overrides(BaseEvent) - def get_event_description(self) -> str: - return escape_tag(str(self.dict())) - - @overrides(BaseEvent) - def get_message(self) -> Message: - raise ValueError("Event has no message!") - - @overrides(BaseEvent) - def get_plaintext(self) -> str: - raise ValueError("Event has no message!") - - @overrides(BaseEvent) - def get_user_id(self) -> str: - raise ValueError("Event has no message!") - - @overrides(BaseEvent) - def get_session_id(self) -> str: - raise ValueError("Event has no message!") - - @overrides(BaseEvent) - def is_tome(self) -> bool: - return False - - -# Models -class Sender(BaseModel): - user_id: Optional[int] = None - nickname: Optional[str] = None - sex: Optional[str] = None - age: Optional[int] = None - card: Optional[str] = None - area: Optional[str] = None - level: Optional[str] = None - role: Optional[str] = None - title: Optional[str] = None - - class Config: - extra = "allow" - - -class Reply(BaseModel): - time: int - message_type: str - message_id: int - real_id: int - sender: Sender - message: Message - - class Config: - extra = "allow" - - -class Anonymous(BaseModel): - id: int - name: str - flag: str - - class Config: - extra = "allow" - - -class File(BaseModel): - id: str - name: str - size: int - busid: int - - class Config: - extra = "allow" - - -class Status(BaseModel): - online: bool - good: bool - - class Config: - extra = "allow" - - -# Message Events -class MessageEvent(Event): - """消息事件""" - - __event__ = "message" - post_type: Literal["message"] - sub_type: str - user_id: int - message_type: str - message_id: int - message: Message - raw_message: str - font: int - sender: Sender - to_me: bool = False - """ - :说明: 消息是否与机器人有关 - - :类型: ``bool`` - """ - reply: Optional[Reply] = None - """ - :说明: 消息中提取的回复消息,内容为 ``get_msg`` API 返回结果 - - :类型: ``Optional[Reply]`` - """ - - @overrides(Event) - def get_event_name(self) -> str: - sub_type = getattr(self, "sub_type", None) - return f"{self.post_type}.{self.message_type}" + ( - f".{sub_type}" if sub_type else "" - ) - - @overrides(Event) - def get_message(self) -> Message: - return self.message - - @overrides(Event) - def get_plaintext(self) -> str: - return self.message.extract_plain_text() - - @overrides(Event) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(Event) - def get_session_id(self) -> str: - return str(self.user_id) - - @overrides(Event) - def is_tome(self) -> bool: - return self.to_me - - -class PrivateMessageEvent(MessageEvent): - """私聊消息""" - - __event__ = "message.private" - message_type: Literal["private"] - - @overrides(Event) - def get_event_description(self) -> str: - return ( - f'Message {self.message_id} from {self.user_id} "' - + "".join( - map( - lambda x: escape_tag(str(x)) - if x.is_text() - else f"{escape_tag(str(x))}", - self.message, - ) - ) - + '"' - ) - - -class GroupMessageEvent(MessageEvent): - """群消息""" - - __event__ = "message.group" - message_type: Literal["group"] - group_id: int - anonymous: Optional[Anonymous] = None - - @overrides(Event) - def get_event_description(self) -> str: - return ( - f'Message {self.message_id} from {self.user_id}@[群:{self.group_id}] "' - + "".join( - map( - lambda x: escape_tag(str(x)) - if x.is_text() - else f"{escape_tag(str(x))}", - self.message, - ) - ) - + '"' - ) - - @overrides(MessageEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -# Notice Events -class NoticeEvent(Event): - """通知事件""" - - __event__ = "notice" - post_type: Literal["notice"] - notice_type: str - - @overrides(Event) - def get_event_name(self) -> str: - sub_type = getattr(self, "sub_type", None) - return f"{self.post_type}.{self.notice_type}" + ( - f".{sub_type}" if sub_type else "" - ) - - -class GroupUploadNoticeEvent(NoticeEvent): - """群文件上传事件""" - - __event__ = "notice.group_upload" - notice_type: Literal["group_upload"] - user_id: int - group_id: int - file: File - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class GroupAdminNoticeEvent(NoticeEvent): - """群管理员变动""" - - __event__ = "notice.group_admin" - notice_type: Literal["group_admin"] - sub_type: str - user_id: int - group_id: int - - @overrides(NoticeEvent) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class GroupDecreaseNoticeEvent(NoticeEvent): - """群成员减少事件""" - - __event__ = "notice.group_decrease" - notice_type: Literal["group_decrease"] - sub_type: str - user_id: int - group_id: int - operator_id: int - - @overrides(NoticeEvent) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class GroupIncreaseNoticeEvent(NoticeEvent): - """群成员增加事件""" - - __event__ = "notice.group_increase" - notice_type: Literal["group_increase"] - sub_type: str - user_id: int - group_id: int - operator_id: int - - @overrides(NoticeEvent) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class GroupBanNoticeEvent(NoticeEvent): - """群禁言事件""" - - __event__ = "notice.group_ban" - notice_type: Literal["group_ban"] - sub_type: str - user_id: int - group_id: int - operator_id: int - duration: int - - @overrides(NoticeEvent) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class FriendAddNoticeEvent(NoticeEvent): - """好友添加事件""" - - __event__ = "notice.friend_add" - notice_type: Literal["friend_add"] - user_id: int - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return str(self.user_id) - - -class GroupRecallNoticeEvent(NoticeEvent): - """群消息撤回事件""" - - __event__ = "notice.group_recall" - notice_type: Literal["group_recall"] - user_id: int - group_id: int - operator_id: int - message_id: int - - @overrides(Event) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class FriendRecallNoticeEvent(NoticeEvent): - """好友消息撤回事件""" - - __event__ = "notice.friend_recall" - notice_type: Literal["friend_recall"] - user_id: int - message_id: int - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return str(self.user_id) - - -class NotifyEvent(NoticeEvent): - """提醒事件""" - - __event__ = "notice.notify" - notice_type: Literal["notify"] - sub_type: str - user_id: int - group_id: int - - @overrides(NoticeEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(NoticeEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - -class PokeNotifyEvent(NotifyEvent): - """戳一戳提醒事件""" - - __event__ = "notice.notify.poke" - sub_type: Literal["poke"] - target_id: int - group_id: Optional[int] = None - - @overrides(Event) - def is_tome(self) -> bool: - return self.target_id == self.self_id - - @overrides(NotifyEvent) - def get_session_id(self) -> str: - if not self.group_id: - return str(self.user_id) - return super().get_session_id() - - -class LuckyKingNotifyEvent(NotifyEvent): - """群红包运气王提醒事件""" - - __event__ = "notice.notify.lucky_king" - sub_type: Literal["lucky_king"] - target_id: int - - @overrides(Event) - def is_tome(self) -> bool: - return self.target_id == self.self_id - - @overrides(NotifyEvent) - def get_user_id(self) -> str: - return str(self.target_id) - - @overrides(NotifyEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.target_id}" - - -class HonorNotifyEvent(NotifyEvent): - """群荣誉变更提醒事件""" - - __event__ = "notice.notify.honor" - sub_type: Literal["honor"] - honor_type: str - - @overrides(Event) - def is_tome(self) -> bool: - return self.user_id == self.self_id - - -# Request Events -class RequestEvent(Event): - """请求事件""" - - __event__ = "request" - post_type: Literal["request"] - request_type: str - - @overrides(Event) - def get_event_name(self) -> str: - sub_type = getattr(self, "sub_type", None) - return f"{self.post_type}.{self.request_type}" + ( - f".{sub_type}" if sub_type else "" - ) - - -class FriendRequestEvent(RequestEvent): - """加好友请求事件""" - - __event__ = "request.friend" - request_type: Literal["friend"] - user_id: int - comment: str - flag: str - - @overrides(RequestEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(RequestEvent) - def get_session_id(self) -> str: - return str(self.user_id) - - async def approve(self, bot: "Bot", remark: str = ""): - return await bot.set_friend_add_request( - flag=self.flag, approve=True, remark=remark - ) - - async def reject(self, bot: "Bot"): - return await bot.set_friend_add_request(flag=self.flag, approve=False) - - -class GroupRequestEvent(RequestEvent): - """加群请求/邀请事件""" - - __event__ = "request.group" - request_type: Literal["group"] - sub_type: str - group_id: int - user_id: int - comment: str - flag: str - - @overrides(RequestEvent) - def get_user_id(self) -> str: - return str(self.user_id) - - @overrides(RequestEvent) - def get_session_id(self) -> str: - return f"group_{self.group_id}_{self.user_id}" - - async def approve(self, bot: "Bot"): - return await bot.set_group_add_request( - flag=self.flag, sub_type=self.sub_type, approve=True - ) - - async def reject(self, bot: "Bot", reason: str = ""): - return await bot.set_group_add_request( - flag=self.flag, sub_type=self.sub_type, approve=False, reason=reason - ) - - -# Meta Events -class MetaEvent(Event): - """元事件""" - - __event__ = "meta_event" - post_type: Literal["meta_event"] - meta_event_type: str - - @overrides(Event) - def get_event_name(self) -> str: - sub_type = getattr(self, "sub_type", None) - return f"{self.post_type}.{self.meta_event_type}" + ( - f".{sub_type}" if sub_type else "" - ) - - @overrides(Event) - def get_log_string(self) -> str: - raise NoLogException - - -class LifecycleMetaEvent(MetaEvent): - """生命周期元事件""" - - __event__ = "meta_event.lifecycle" - meta_event_type: Literal["lifecycle"] - sub_type: str - - -class HeartbeatMetaEvent(MetaEvent): - """心跳元事件""" - - __event__ = "meta_event.heartbeat" - meta_event_type: Literal["heartbeat"] - status: Status - interval: int - - -_t = StringTrie(separator=".") - -# define `model` first to avoid globals changing while `for` -model = None -for model in globals().values(): - if not inspect.isclass(model) or not issubclass(model, Event): - continue - _t["." + model.__event__] = model - - -def get_event_model(event_name) -> List[Type[Event]]: - """ - :说明: - - 根据事件名获取对应 ``Event Model`` 及 ``FallBack Event Model`` 列表 - - :返回: - - - ``List[Type[Event]]`` - """ - return [model.value for model in _t.prefixes("." + event_name)][::-1] - - -__all__ = [ - "Event", - "MessageEvent", - "PrivateMessageEvent", - "GroupMessageEvent", - "NoticeEvent", - "GroupUploadNoticeEvent", - "GroupAdminNoticeEvent", - "GroupDecreaseNoticeEvent", - "GroupIncreaseNoticeEvent", - "GroupBanNoticeEvent", - "FriendAddNoticeEvent", - "GroupRecallNoticeEvent", - "FriendRecallNoticeEvent", - "NotifyEvent", - "PokeNotifyEvent", - "LuckyKingNotifyEvent", - "HonorNotifyEvent", - "RequestEvent", - "FriendRequestEvent", - "GroupRequestEvent", - "MetaEvent", - "LifecycleMetaEvent", - "HeartbeatMetaEvent", - "get_event_model", -] diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py deleted file mode 100644 index 1ea01f80..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py +++ /dev/null @@ -1,68 +0,0 @@ -from typing import Optional - -from nonebot.exception import AdapterException -from nonebot.exception import ActionFailed as BaseActionFailed -from nonebot.exception import NetworkError as BaseNetworkError -from nonebot.exception import NoLogException as BaseNoLogException -from nonebot.exception import ApiNotAvailable as BaseApiNotAvailable - - -class CQHTTPAdapterException(AdapterException): - def __init__(self): - super().__init__("cqhttp") - - -class NoLogException(BaseNoLogException, CQHTTPAdapterException): - pass - - -class ActionFailed(BaseActionFailed, CQHTTPAdapterException): - """ - :说明: - - API 请求返回错误信息。 - - :参数: - - * ``retcode: Optional[int]``: 错误码 - """ - - def __init__(self, **kwargs): - super().__init__() - self.info = kwargs - - def __repr__(self): - return ( - f"" - ) - - def __str__(self): - return self.__repr__() - - -class NetworkError(BaseNetworkError, CQHTTPAdapterException): - """ - :说明: - - 网络错误。 - - :参数: - - * ``retcode: Optional[int]``: 错误码 - """ - - def __init__(self, msg: Optional[str] = None): - super().__init__() - self.msg = msg - - def __repr__(self): - return f"" - - def __str__(self): - return self.__repr__() - - -class ApiNotAvailable(BaseApiNotAvailable, CQHTTPAdapterException): - pass diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py deleted file mode 100644 index 8ca6378a..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py +++ /dev/null @@ -1,321 +0,0 @@ -import re -from io import BytesIO -from pathlib import Path -from base64 import b64encode -from typing import Any, Type, Tuple, Union, Mapping, Iterable, Optional, cast - -from nonebot.typing import overrides -from nonebot.adapters import Message as BaseMessage -from nonebot.adapters import MessageSegment as BaseMessageSegment - -from .utils import log, _b2s, escape, unescape - - -class MessageSegment(BaseMessageSegment["Message"]): - """ - CQHTTP 协议 MessageSegment 适配。具体方法参考协议消息段类型或源码。 - """ - - @classmethod - @overrides(BaseMessageSegment) - def get_message_class(cls) -> Type["Message"]: - return Message - - @overrides(BaseMessageSegment) - def __str__(self) -> str: - type_ = self.type - data = self.data.copy() - - # process special types - if type_ == "text": - return escape(data.get("text", ""), escape_comma=False) # type: ignore - - params = ",".join( - [f"{k}={escape(str(v))}" for k, v in data.items() if v is not None] - ) - return f"[CQ:{type_}{',' if params else ''}{params}]" - - @overrides(BaseMessageSegment) - def __add__(self, other) -> "Message": - return Message(self) + ( - MessageSegment.text(other) if isinstance(other, str) else other - ) - - @overrides(BaseMessageSegment) - def __radd__(self, other) -> "Message": - return ( - MessageSegment.text(other) if isinstance(other, str) else Message(other) - ) + self - - @overrides(BaseMessageSegment) - def is_text(self) -> bool: - return self.type == "text" - - @staticmethod - def anonymous(ignore_failure: Optional[bool] = None) -> "MessageSegment": - return MessageSegment("anonymous", {"ignore": _b2s(ignore_failure)}) - - @staticmethod - def at(user_id: Union[int, str]) -> "MessageSegment": - return MessageSegment("at", {"qq": str(user_id)}) - - @staticmethod - def contact(type_: str, id: int) -> "MessageSegment": - return MessageSegment("contact", {"type": type_, "id": str(id)}) - - @staticmethod - def contact_group(group_id: int) -> "MessageSegment": - return MessageSegment("contact", {"type": "group", "id": str(group_id)}) - - @staticmethod - def contact_user(user_id: int) -> "MessageSegment": - return MessageSegment("contact", {"type": "qq", "id": str(user_id)}) - - @staticmethod - def dice() -> "MessageSegment": - return MessageSegment("dice", {}) - - @staticmethod - def face(id_: int) -> "MessageSegment": - return MessageSegment("face", {"id": str(id_)}) - - @staticmethod - def forward(id_: str) -> "MessageSegment": - log("WARNING", "Forward Message only can be received!") - return MessageSegment("forward", {"id": id_}) - - @staticmethod - def image( - file: Union[str, bytes, BytesIO, Path], - type_: Optional[str] = None, - cache: bool = True, - proxy: bool = True, - timeout: Optional[int] = None, - ) -> "MessageSegment": - if isinstance(file, BytesIO): - file = file.getvalue() - if isinstance(file, bytes): - file = f"base64://{b64encode(file).decode()}" - elif isinstance(file, Path): - file = f"file:///{file.resolve()}" - return MessageSegment( - "image", - { - "file": file, - "type": type_, - "cache": _b2s(cache), - "proxy": _b2s(proxy), - "timeout": timeout, - }, - ) - - @staticmethod - def json(data: str) -> "MessageSegment": - return MessageSegment("json", {"data": data}) - - @staticmethod - def location( - latitude: float, - longitude: float, - title: Optional[str] = None, - content: Optional[str] = None, - ) -> "MessageSegment": - return MessageSegment( - "location", - { - "lat": str(latitude), - "lon": str(longitude), - "title": title, - "content": content, - }, - ) - - @staticmethod - def music(type_: str, id_: int) -> "MessageSegment": - return MessageSegment("music", {"type": type_, "id": id_}) - - @staticmethod - def music_custom( - url: str, - audio: str, - title: str, - content: Optional[str] = None, - img_url: Optional[str] = None, - ) -> "MessageSegment": - return MessageSegment( - "music", - { - "type": "custom", - "url": url, - "audio": audio, - "title": title, - "content": content, - "image": img_url, - }, - ) - - @staticmethod - def node(id_: int) -> "MessageSegment": - return MessageSegment("node", {"id": str(id_)}) - - @staticmethod - def node_custom( - user_id: int, nickname: str, content: Union[str, "Message"] - ) -> "MessageSegment": - return MessageSegment( - "node", {"user_id": str(user_id), "nickname": nickname, "content": content} - ) - - @staticmethod - def poke(type_: str, id_: str) -> "MessageSegment": - return MessageSegment("poke", {"type": type_, "id": id_}) - - @staticmethod - def record( - file: Union[str, bytes, BytesIO, Path], - magic: Optional[bool] = None, - cache: Optional[bool] = None, - proxy: Optional[bool] = None, - timeout: Optional[int] = None, - ) -> "MessageSegment": - if isinstance(file, BytesIO): - file = file.getvalue() - if isinstance(file, bytes): - file = f"base64://{b64encode(file).decode()}" - elif isinstance(file, Path): - file = f"file:///{file.resolve()}" - return MessageSegment( - "record", - { - "file": file, - "magic": _b2s(magic), - "cache": _b2s(cache), - "proxy": _b2s(proxy), - "timeout": timeout, - }, - ) - - @staticmethod - def reply(id_: int) -> "MessageSegment": - return MessageSegment("reply", {"id": str(id_)}) - - @staticmethod - def rps() -> "MessageSegment": - return MessageSegment("rps", {}) - - @staticmethod - def shake() -> "MessageSegment": - return MessageSegment("shake", {}) - - @staticmethod - def share( - url: str = "", - title: str = "", - content: Optional[str] = None, - image: Optional[str] = None, - ) -> "MessageSegment": - return MessageSegment( - "share", {"url": url, "title": title, "content": content, "image": image} - ) - - @staticmethod - def text(text: str) -> "MessageSegment": - return MessageSegment("text", {"text": text}) - - @staticmethod - def video( - file: Union[str, bytes, BytesIO, Path], - cache: Optional[bool] = None, - proxy: Optional[bool] = None, - timeout: Optional[int] = None, - ) -> "MessageSegment": - if isinstance(file, BytesIO): - file = file.getvalue() - if isinstance(file, bytes): - file = f"base64://{b64encode(file).decode()}" - elif isinstance(file, Path): - file = f"file:///{file.resolve()}" - return MessageSegment( - "video", - { - "file": file, - "cache": _b2s(cache), - "proxy": _b2s(proxy), - "timeout": timeout, - }, - ) - - @staticmethod - def xml(data: str) -> "MessageSegment": - return MessageSegment("xml", {"data": data}) - - -class Message(BaseMessage[MessageSegment]): - """ - CQHTTP 协议 Message 适配。 - """ - - @classmethod - @overrides(BaseMessage) - def get_segment_class(cls) -> Type[MessageSegment]: - return MessageSegment - - @overrides(BaseMessage) - def __add__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message": - return super(Message, self).__add__( - MessageSegment.text(other) if isinstance(other, str) else other - ) - - @overrides(BaseMessage) - def __radd__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message": - return super(Message, self).__radd__( - MessageSegment.text(other) if isinstance(other, str) else other - ) - - @staticmethod - @overrides(BaseMessage) - def _construct( - msg: Union[str, Mapping, Iterable[Mapping]] - ) -> Iterable[MessageSegment]: - if isinstance(msg, Mapping): - msg = cast(Mapping[str, Any], msg) - yield MessageSegment(msg["type"], msg.get("data") or {}) - return - elif isinstance(msg, Iterable) and not isinstance(msg, str): - for seg in msg: - yield MessageSegment(seg["type"], seg.get("data") or {}) - return - elif isinstance(msg, str): - - def _iter_message(msg: str) -> Iterable[Tuple[str, str]]: - text_begin = 0 - for cqcode in re.finditer( - r"\[CQ:(?P[a-zA-Z0-9-_.]+)" - r"(?P" - r"(?:,[a-zA-Z0-9-_.]+=[^,\]]+)*" - r"),?\]", - msg, - ): - yield "text", msg[text_begin : cqcode.pos + cqcode.start()] - text_begin = cqcode.pos + cqcode.end() - yield cqcode.group("type"), cqcode.group("params").lstrip(",") - yield "text", msg[text_begin:] - - for type_, data in _iter_message(msg): - if type_ == "text": - if data: - # only yield non-empty text segment - yield MessageSegment(type_, {"text": unescape(data)}) - else: - data = { - k: unescape(v) - for k, v in map( - lambda x: x.split("=", maxsplit=1), - filter(lambda x: x, (x.lstrip() for x in data.split(","))), - ) - } - yield MessageSegment(type_, data) - - @overrides(BaseMessage) - def extract_plain_text(self) -> str: - return "".join(seg.data["text"] for seg in self if seg.is_text()) diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py deleted file mode 100644 index 2a85d6f1..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py +++ /dev/null @@ -1,87 +0,0 @@ -from nonebot.adapters import Event -from nonebot.permission import Permission - -from .event import GroupMessageEvent, PrivateMessageEvent - - -async def _private(event: Event) -> bool: - return isinstance(event, PrivateMessageEvent) - - -async def _private_friend(event: Event) -> bool: - return isinstance(event, PrivateMessageEvent) and event.sub_type == "friend" - - -async def _private_group(event: Event) -> bool: - return isinstance(event, PrivateMessageEvent) and event.sub_type == "group" - - -async def _private_other(event: Event) -> bool: - return isinstance(event, PrivateMessageEvent) and event.sub_type == "other" - - -PRIVATE = Permission(_private) -""" -- **说明**: 匹配任意私聊消息类型事件 -""" -PRIVATE_FRIEND = Permission(_private_friend) -""" -- **说明**: 匹配任意好友私聊消息类型事件 -""" -PRIVATE_GROUP = Permission(_private_group) -""" -- **说明**: 匹配任意群临时私聊消息类型事件 -""" -PRIVATE_OTHER = Permission(_private_other) -""" -- **说明**: 匹配任意其他私聊消息类型事件 -""" - - -async def _group(event: Event) -> bool: - return isinstance(event, GroupMessageEvent) - - -async def _group_member(event: Event) -> bool: - return isinstance(event, GroupMessageEvent) and event.sender.role == "member" - - -async def _group_admin(event: Event) -> bool: - return isinstance(event, GroupMessageEvent) and event.sender.role == "admin" - - -async def _group_owner(event: Event) -> bool: - return isinstance(event, GroupMessageEvent) and event.sender.role == "owner" - - -GROUP = Permission(_group) -""" -- **说明**: 匹配任意群聊消息类型事件 -""" -GROUP_MEMBER = Permission(_group_member) -r""" -- **说明**: 匹配任意群员群聊消息类型事件 - -\:\:\:warning 警告 -该权限通过 event.sender 进行判断且不包含管理员以及群主! -\:\:\: -""" -GROUP_ADMIN = Permission(_group_admin) -""" -- **说明**: 匹配任意群管理员群聊消息类型事件 -""" -GROUP_OWNER = Permission(_group_owner) -""" -- **说明**: 匹配任意群主群聊消息类型事件 -""" - -__all__ = [ - "PRIVATE", - "PRIVATE_FRIEND", - "PRIVATE_GROUP", - "PRIVATE_OTHER", - "GROUP", - "GROUP_MEMBER", - "GROUP_ADMIN", - "GROUP_OWNER", -] diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py deleted file mode 100644 index a3d2d0e4..00000000 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py +++ /dev/null @@ -1,45 +0,0 @@ -from typing import Optional - -from nonebot.utils import logger_wrapper - -log = logger_wrapper("CQHTTP") - - -def escape(s: str, *, escape_comma: bool = True) -> str: - """ - :说明: - - 对字符串进行 CQ 码转义。 - - :参数: - - * ``s: str``: 需要转义的字符串 - * ``escape_comma: bool``: 是否转义逗号(``,``)。 - """ - s = s.replace("&", "&").replace("[", "[").replace("]", "]") - if escape_comma: - s = s.replace(",", ",") - return s - - -def unescape(s: str) -> str: - """ - :说明: - - 对字符串进行 CQ 码去转义。 - - :参数: - - * ``s: str``: 需要转义的字符串 - """ - return ( - s.replace(",", ",") - .replace("[", "[") - .replace("]", "]") - .replace("&", "&") - ) - - -def _b2s(b: Optional[bool]) -> Optional[str]: - """转换布尔值为字符串。""" - return b if b is None else str(b).lower() diff --git a/packages/nonebot-adapter-cqhttp/poetry.lock b/packages/nonebot-adapter-cqhttp/poetry.lock deleted file mode 100644 index 9945f985..00000000 --- a/packages/nonebot-adapter-cqhttp/poetry.lock +++ /dev/null @@ -1,649 +0,0 @@ -[[package]] -name = "anyio" -version = "3.3.4" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] - -[[package]] -name = "asgiref" -version = "3.4.1" -description = "ASGI specs, helper code, and adapters" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] - -[[package]] -name = "certifi" -version = "2021.10.8" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "charset-normalizer" -version = "2.0.7" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - -[[package]] -name = "click" -version = "8.0.3" -description = "Composable command line interface toolkit" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "fastapi" -version = "0.70.0" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" -starlette = "0.16.0" - -[package.extras] -all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "ujson (>=4.0.1,<5.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] -dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.16.0)"] -doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=7.1.9,<8.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer-cli (>=0.0.12,<0.0.13)", "pyyaml (>=5.3.1,<6.0.0)"] -test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==21.9b0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,<5.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==0.1.1)", "types-orjson (==3.6.0)", "types-dataclasses (==0.1.7)"] - -[[package]] -name = "h11" -version = "0.12.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "h2" -version = "4.1.0" -description = "HTTP/2 State-Machine based protocol implementation" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -hpack = ">=4.0,<5" -hyperframe = ">=6.0,<7" - -[[package]] -name = "hpack" -version = "4.0.0" -description = "Pure-Python HPACK header compression" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[[package]] -name = "httpcore" -version = "0.13.7" -description = "A minimal low-level HTTP client." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -anyio = ">=3.0.0,<4.0.0" -h11 = ">=0.11,<0.13" -sniffio = ">=1.0.0,<2.0.0" - -[package.extras] -http2 = ["h2 (>=3,<5)"] - -[[package]] -name = "httptools" -version = "0.2.0" -description = "A collection of framework independent HTTP protocol utils." -category = "main" -optional = false -python-versions = "*" - -[package.extras] -test = ["Cython (==0.29.22)"] - -[[package]] -name = "httpx" -version = "0.20.0" -description = "The next generation HTTP client." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -certifi = "*" -charset-normalizer = "*" -h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} -httpcore = ">=0.13.3,<0.14.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} -sniffio = "*" - -[package.extras] -brotli = ["brotlicffi", "brotli"] -cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10.0.0,<11.0.0)", "pygments (>=2.0.0,<3.0.0)"] -http2 = ["h2 (>=3,<5)"] - -[[package]] -name = "hyperframe" -version = "6.0.1" -description = "HTTP/2 framing layer for Python" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[[package]] -name = "idna" -version = "3.3" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "importlib-metadata" -version = "4.8.1" -description = "Read metadata from Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] - -[[package]] -name = "loguru" -version = "0.5.3" -description = "Python logging made (stupidly) simple" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["codecov (>=2.0.15)", "colorama (>=0.3.4)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "tox-travis (>=0.12)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "Sphinx (>=2.2.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "black (>=19.10b0)", "isort (>=5.1.1)"] - -[[package]] -name = "nonebot2" -version = "2.0.0-alpha.16" -description = "An asynchronous python bot framework." -category = "main" -optional = false -python-versions = "^3.7.3" -develop = true - -[package.dependencies] -fastapi = "^0.70.0" -httpx = {version = ">=0.20.0, <1.0.0", extras = ["http2"]} -loguru = "^0.5.1" -pydantic = {version = "~1.8.0", extras = ["dotenv"]} -pygtrie = "^2.4.1" -tomlkit = "^0.7.0" -uvicorn = {version = "^0.15.0", extras = ["standard"]} -websockets = ">=9.1" - -[package.extras] -quart = ["Quart (>=0.15.0,<0.16.0)"] -aiohttp = ["aiohttp[speedups] (>=3.7.4,<4.0.0)"] -all = ["Quart (>=0.15.0,<0.16.0)", "aiohttp[speedups] (>=3.7.4,<4.0.0)"] - -[package.source] -type = "directory" -url = "../.." - -[[package]] -name = "pydantic" -version = "1.8.2" -description = "Data validation and settings management using python 3.6 type hinting" -category = "main" -optional = false -python-versions = ">=3.6.1" - -[package.dependencies] -python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} -typing-extensions = ">=3.7.4.3" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pygtrie" -version = "2.4.2" -description = "A pure Python trie data structure implementation." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "python-dotenv" -version = "0.19.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "rfc3986" -version = "1.5.0" -description = "Validating URI References per RFC 3986" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} - -[package.extras] -idna2008 = ["idna"] - -[[package]] -name = "sniffio" -version = "1.2.0" -description = "Sniff out which async library your code is running under" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "starlette" -version = "0.16.0" -description = "The little ASGI library that shines." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -anyio = ">=3.0.0,<4" -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "graphene"] - -[[package]] -name = "tomlkit" -version = "0.7.2" -description = "Style preserving TOML library" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "uvicorn" -version = "0.15.0" -description = "The lightning-fast ASGI server." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -asgiref = ">=3.4.0" -click = ">=7.0" -colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} -h11 = ">=0.8" -httptools = {version = ">=0.2.0,<0.3.0", optional = true, markers = "extra == \"standard\""} -python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} -PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} -uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} -watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\""} -websockets = {version = ">=9.1", optional = true, markers = "extra == \"standard\""} - -[package.extras] -standard = ["websockets (>=9.1)", "httptools (>=0.2.0,<0.3.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] - -[[package]] -name = "uvloop" -version = "0.16.0" -description = "Fast implementation of asyncio event loop on top of libuv" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] -docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] -test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] - -[[package]] -name = "watchgod" -version = "0.7" -description = "Simple, modern file watching and code reload in python." -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "websockets" -version = "10.0" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "win32-setctime" -version = "1.0.3" -description = "A small Python utility to set file creation time on Windows" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] - -[[package]] -name = "zipp" -version = "3.6.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] - -[metadata] -lock-version = "1.1" -python-versions = "^3.7.3" -content-hash = "0cc9df471eb39cfb9b3225370913296535c45171158adc19753cebb7fe791ae3" - -[metadata.files] -anyio = [ - {file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"}, - {file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"}, -] -asgiref = [ - {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, - {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, -] -certifi = [ - {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, - {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.0.7.tar.gz", hash = "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0"}, - {file = "charset_normalizer-2.0.7-py3-none-any.whl", hash = "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b"}, -] -click = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, -] -colorama = [ - {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, -] -fastapi = [ - {file = "fastapi-0.70.0-py3-none-any.whl", hash = "sha256:a36d5f2fad931aa3575c07a3472c784e81f3e664e3bb5c8b9c88d0ec1104f59c"}, - {file = "fastapi-0.70.0.tar.gz", hash = "sha256:66da43cfe5185ea1df99552acffd201f1832c6b364e0f4136c0a99f933466ced"}, -] -h11 = [ - {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, - {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, -] -h2 = [ - {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, - {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, -] -hpack = [ - {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, - {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, -] -httpcore = [ - {file = "httpcore-0.13.7-py3-none-any.whl", hash = "sha256:369aa481b014cf046f7067fddd67d00560f2f00426e79569d99cb11245134af0"}, - {file = "httpcore-0.13.7.tar.gz", hash = "sha256:036f960468759e633574d7c121afba48af6419615d36ab8ede979f1ad6276fa3"}, -] -httptools = [ - {file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"}, - {file = "httptools-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149"}, - {file = "httptools-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7"}, - {file = "httptools-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77"}, - {file = "httptools-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658"}, - {file = "httptools-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb"}, - {file = "httptools-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e"}, - {file = "httptools-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb"}, - {file = "httptools-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943"}, - {file = "httptools-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15"}, - {file = "httptools-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380"}, - {file = "httptools-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557"}, - {file = "httptools-0.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"}, - {file = "httptools-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f"}, - {file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"}, -] -httpx = [ - {file = "httpx-0.20.0-py3-none-any.whl", hash = "sha256:33af5aad9bdc82ef1fc89219c1e36f5693bf9cd0ebe330884df563445682c0f8"}, - {file = "httpx-0.20.0.tar.gz", hash = "sha256:09606d630f070d07f9ff28104fbcea429ea0014c1e89ac90b4d8de8286c40e7b"}, -] -hyperframe = [ - {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, - {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, -] -idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, -] -loguru = [ - {file = "loguru-0.5.3-py3-none-any.whl", hash = "sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c"}, - {file = "loguru-0.5.3.tar.gz", hash = "sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319"}, -] -nonebot2 = [] -pydantic = [ - {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, - {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"}, - {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"}, - {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"}, - {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"}, - {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"}, - {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"}, - {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"}, - {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"}, - {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"}, - {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"}, - {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"}, - {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"}, - {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"}, - {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"}, - {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"}, - {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"}, - {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"}, - {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"}, - {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"}, - {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, - {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, -] -pygtrie = [ - {file = "pygtrie-2.4.2.tar.gz", hash = "sha256:43205559d28863358dbbf25045029f58e2ab357317a59b11f11ade278ac64692"}, -] -python-dotenv = [ - {file = "python-dotenv-0.19.1.tar.gz", hash = "sha256:14f8185cc8d494662683e6914addcb7e95374771e707601dfc70166946b4c4b8"}, - {file = "python_dotenv-0.19.1-py2.py3-none-any.whl", hash = "sha256:bbd3da593fc49c249397cbfbcc449cf36cb02e75afc8157fcc6a81df6fb7750a"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -rfc3986 = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, -] -sniffio = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, -] -starlette = [ - {file = "starlette-0.16.0-py3-none-any.whl", hash = "sha256:38eb24bf705a2c317e15868e384c1b8a12ca396e5a3c3a003db7e667c43f939f"}, - {file = "starlette-0.16.0.tar.gz", hash = "sha256:e1904b5d0007aee24bdd3c43994be9b3b729f4f58e740200de1d623f8c3a8870"}, -] -tomlkit = [ - {file = "tomlkit-0.7.2-py2.py3-none-any.whl", hash = "sha256:173ad840fa5d2aac140528ca1933c29791b79a374a0861a80347f42ec9328117"}, - {file = "tomlkit-0.7.2.tar.gz", hash = "sha256:d7a454f319a7e9bd2e249f239168729327e4dd2d27b17dc68be264ad1ce36754"}, -] -typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, -] -uvicorn = [ - {file = "uvicorn-0.15.0-py3-none-any.whl", hash = "sha256:17f898c64c71a2640514d4089da2689e5db1ce5d4086c2d53699bf99513421c1"}, - {file = "uvicorn-0.15.0.tar.gz", hash = "sha256:d9a3c0dd1ca86728d3e235182683b4cf94cd53a867c288eaeca80ee781b2caff"}, -] -uvloop = [ - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, - {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, - {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, -] -watchgod = [ - {file = "watchgod-0.7-py3-none-any.whl", hash = "sha256:d6c1ea21df37847ac0537ca0d6c2f4cdf513562e95f77bb93abbcf05573407b7"}, - {file = "watchgod-0.7.tar.gz", hash = "sha256:48140d62b0ebe9dd9cf8381337f06351e1f2e70b2203fa9c6eff4e572ca84f29"}, -] -websockets = [ - {file = "websockets-10.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cd8c6f2ec24aedace251017bc7a414525171d4e6578f914acab9349362def4da"}, - {file = "websockets-10.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1f6b814cff6aadc4288297cb3a248614829c6e4ff5556593c44a115e9dd49939"}, - {file = "websockets-10.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:01db0ecd1a0ca6702d02a5ed40413e18b7d22f94afb3bbe0d323bac86c42c1c8"}, - {file = "websockets-10.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:82b17524b1ce6ae7f7dd93e4d18e9b9474071e28b65dbf1dfe9b5767778db379"}, - {file = "websockets-10.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8bbf8660c3f833ddc8b1afab90213f2e672a9ddac6eecb3cde968e6b2807c1c7"}, - {file = "websockets-10.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b8176deb6be540a46695960a765a77c28ac8b2e3ef2ec95d50a4f5df901edb1c"}, - {file = "websockets-10.0-cp37-cp37m-win32.whl", hash = "sha256:706e200fc7f03bed99ad0574cd1ea8b0951477dd18cc978ccb190683c69dba76"}, - {file = "websockets-10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5b2600e01c7ca6f840c42c747ffbe0254f319594ed108db847eb3d75f4aacb80"}, - {file = "websockets-10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:085bb8a6e780d30eaa1ba48ac7f3a6707f925edea787cfb761ce5a39e77ac09b"}, - {file = "websockets-10.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9a4d889162bd48588e80950e07fa5e039eee9deb76a58092e8c3ece96d7ef537"}, - {file = "websockets-10.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b4ade7569b6fd17912452f9c3757d96f8e4044016b6d22b3b8391e641ca50456"}, - {file = "websockets-10.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:2a43072e434c041a99f2e1eb9b692df0232a38c37c61d00e9f24db79474329e4"}, - {file = "websockets-10.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7f79f02c7f9a8320aff7d3321cd1c7e3a7dbc15d922ac996cca827301ee75238"}, - {file = "websockets-10.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:1ac35426fe3e7d3d0fac3d63c8965c76ed67a8fd713937be072bf0ce22808539"}, - {file = "websockets-10.0-cp38-cp38-win32.whl", hash = "sha256:ff59c6bdb87b31f7e2d596f09353d5a38c8c8ff571b0e2238e8ee2d55ad68465"}, - {file = "websockets-10.0-cp38-cp38-win_amd64.whl", hash = "sha256:d67646ddd17a86117ae21c27005d83c1895c0cef5d7be548b7549646372f868a"}, - {file = "websockets-10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82bd921885231f4a30d9bc550552495b3fc36b1235add6d374e7c65c3babd805"}, - {file = "websockets-10.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7d2e12e4f901f1bc062dfdf91831712c4106ed18a9a4cdb65e2e5f502124ca37"}, - {file = "websockets-10.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:71358c7816e2762f3e4af3adf0040f268e219f5a38cb3487a9d0fc2e554fef6a"}, - {file = "websockets-10.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:fe83b3ec9ef34063d86dfe1029160a85f24a5a94271036e5714a57acfdd089a1"}, - {file = "websockets-10.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:eb282127e9c136f860c6068a4fba5756eb25e755baffb5940b6f1eae071928b2"}, - {file = "websockets-10.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:62160772314920397f9d219147f958b33fa27a12c662d4455c9ccbba9a07e474"}, - {file = "websockets-10.0-cp39-cp39-win32.whl", hash = "sha256:e42a1f1e03437b017af341e9bbfdc09252cd48ef32a8c3c3ead769eab3b17368"}, - {file = "websockets-10.0-cp39-cp39-win_amd64.whl", hash = "sha256:c5880442f5fc268f1ef6d37b2c152c114deccca73f48e3a8c48004d2f16f4567"}, - {file = "websockets-10.0.tar.gz", hash = "sha256:c4fc9a1d242317892590abe5b61a9127f1a61740477bfb121743f290b8054002"}, -] -win32-setctime = [ - {file = "win32_setctime-1.0.3-py3-none-any.whl", hash = "sha256:dc925662de0a6eb987f0b01f599c01a8236cb8c62831c22d9cada09ad958243e"}, - {file = "win32_setctime-1.0.3.tar.gz", hash = "sha256:4e88556c32fdf47f64165a2180ba4552f8bb32c1103a2fafd05723a0bd42bd4b"}, -] -zipp = [ - {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, - {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, -] diff --git a/packages/nonebot-adapter-cqhttp/pyproject.toml b/packages/nonebot-adapter-cqhttp/pyproject.toml deleted file mode 100644 index 35386f9f..00000000 --- a/packages/nonebot-adapter-cqhttp/pyproject.toml +++ /dev/null @@ -1,54 +0,0 @@ -[tool.poetry] -name = "nonebot-adapter-cqhttp" -version = "2.0.0-alpha.16" -description = "OneBot(CQHTTP) adapter for nonebot2" -authors = ["yanyongyu "] -license = "MIT" -readme = "README.md" -homepage = "https://v2.nonebot.dev/" -repository = "https://github.com/nonebot/nonebot2" -documentation = "https://v2.nonebot.dev/" -keywords = ["bot", "qq", "qqbot", "coolq", "cqhttp"] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Framework :: Robot Framework", - "Framework :: Robot Framework :: Library", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3" -] -packages = [ - { include = "nonebot" } -] -exclude = ["nonebot/__init__.py", "nonebot/adapters/__init__.py"] - -[tool.poetry.dependencies] -python = "^3.7.3" -httpx = ">=0.20.0, <1.0.0" -nonebot2 = "^2.0.0-alpha.14" - -[tool.poetry.dev-dependencies] -nonebot2 = { path = "../../", develop = true } - -# [[tool.poetry.source]] -# name = "aliyun" -# url = "https://mirrors.aliyun.com/pypi/simple/" -# default = true - -[tool.black] -line-length = 88 -target-version = ["py37", "py38", "py39"] -include = '\.pyi?$' -extend-exclude = ''' -''' - -[tool.isort] -profile = "black" -line_length = 80 -length_sort = true -skip_gitignore = true -force_sort_within_sections = true -extra_standard_library = ["typing_extensions"] - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/poetry.lock b/poetry.lock index 56535b06..c8bf9923 100644 --- a/poetry.lock +++ b/poetry.lock @@ -77,7 +77,7 @@ python-versions = "*" [[package]] name = "anyio" -version = "3.3.4" +version = "3.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" category = "main" optional = false @@ -90,7 +90,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] +test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] trio = ["trio (>=0.16)"] [[package]] @@ -509,23 +509,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "nonebot-adapter-cqhttp" -version = "2.0.0-alpha.16" -description = "OneBot(CQHTTP) adapter for nonebot2" -category = "dev" -optional = false -python-versions = "^3.7.3" -develop = true - -[package.dependencies] -httpx = ">=0.20.0, <1.0.0" -nonebot2 = "^2.0.0-alpha.14" - -[package.source] -type = "directory" -url = "packages/nonebot-adapter-cqhttp" - [[package]] name = "nonebot-adapter-ding" version = "2.0.0-alpha.16" @@ -1197,7 +1180,7 @@ quart = ["Quart"] [metadata] lock-version = "1.1" python-versions = "^3.7.3" -content-hash = "9a64b2ba25ea3367e1636545241122d5b4d454ab3042865416193f84bf358fc3" +content-hash = "9c7bf3b0936f4084baf0184046f4443a37c60dadb289c2baaa4360c8d85e3ae8" [metadata.files] aiocache = [ @@ -1295,8 +1278,8 @@ alabaster = [ {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] anyio = [ - {file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"}, - {file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"}, + {file = "anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"}, + {file = "anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"}, ] asgiref = [ {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, @@ -1781,7 +1764,6 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] -nonebot-adapter-cqhttp = [] nonebot-adapter-ding = [] nonebot-adapter-feishu = [] nonebot-adapter-mirai = [] diff --git a/pyproject.toml b/pyproject.toml index 1b00e887..79c2faf3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,6 @@ sphinx = "^4.1.1" isort = "^5.10.1" black = "^21.11b1" nonebot-plugin-test = "^0.3.0" -nonebot-adapter-cqhttp = { path = "./packages/nonebot-adapter-cqhttp", develop = true } nonebot-adapter-ding = { path = "./packages/nonebot-adapter-ding", develop = true } nonebot-adapter-mirai = { path = "./packages/nonebot-adapter-mirai", develop = true } nonebot-adapter-feishu = { path = "./packages/nonebot-adapter-feishu", develop = true } diff --git a/tests/bot.py b/tests/bot.py index 739078b2..695857b3 100644 --- a/tests/bot.py +++ b/tests/bot.py @@ -4,7 +4,6 @@ import sys sys.path.insert(0, os.path.abspath("..")) import nonebot -from nonebot.adapters.cqhttp import Bot from nonebot.log import logger, default_format from nonebot.adapters.ding import Bot as DingBot from nonebot.adapters.mirai import Bot as MiraiBot @@ -18,7 +17,6 @@ logger.add( nonebot.init(custom_config2="config on init") app = nonebot.get_asgi() driver = nonebot.get_driver() -driver.register_adapter("cqhttp", Bot) driver.register_adapter("ding", DingBot) driver.register_adapter("mirai", MiraiBot) driver.register_adapter("feishu", FeishuBot) diff --git a/tests/test_plugins/test_group/__init__.py b/tests/test_plugins/test_group/__init__.py index cd081381..0de0241f 100644 --- a/tests/test_plugins/test_group/__init__.py +++ b/tests/test_plugins/test_group/__init__.py @@ -4,4 +4,4 @@ from nonebot import CommandGroup, MatcherGroup cmd = CommandGroup("test", rule=to_me()) match = MatcherGroup(priority=2) -from . import matches, commands +from . import commands diff --git a/tests/test_plugins/test_group/matches.py b/tests/test_plugins/test_group/matches.py deleted file mode 100644 index 595fd6a4..00000000 --- a/tests/test_plugins/test_group/matches.py +++ /dev/null @@ -1,16 +0,0 @@ -from . import match -from nonebot.typing import T_State -from nonebot.adapters import Bot, Event -from nonebot.adapters.cqhttp import HeartbeatMetaEvent - - -async def heartbeat(bot: Bot, event: Event, state: T_State) -> bool: - return isinstance(event, HeartbeatMetaEvent) - - -test = match.on_metaevent(rule=heartbeat) - - -@test.receive() -async def handle_heartbeat(bot: Bot): - print("[i] Heartbeat") diff --git a/tests/test_plugins/test_metaevent.py b/tests/test_plugins/test_metaevent.py deleted file mode 100644 index 98f76f78..00000000 --- a/tests/test_plugins/test_metaevent.py +++ /dev/null @@ -1,21 +0,0 @@ -from nonebot.typing import T_State -from nonebot.adapters import Bot, Event -from nonebot.plugin import on_metaevent -from nonebot.adapters.cqhttp import HeartbeatMetaEvent - - -async def heartbeat(bot: Bot, event: Event, state: T_State) -> bool: - return isinstance(event, HeartbeatMetaEvent) - - -async def factory(bot: Bot, event: Event) -> T_State: - return {"factory": True} - - -test_matcher = on_metaevent(heartbeat, state_factory=factory) - - -@test_matcher.receive() -async def handle_heartbeat(bot: Bot, event: Event, state: T_State): - print(state) - print("[i] Heartbeat") diff --git a/tests/test_plugins/test_overload.py b/tests/test_plugins/test_overload.py deleted file mode 100644 index 4e9074e5..00000000 --- a/tests/test_plugins/test_overload.py +++ /dev/null @@ -1,19 +0,0 @@ -from nonebot import on_command -from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent - -overload = on_command("overload") - - -@overload.handle() -async def handle_first_receive(bot: Bot): - return - - -@overload.got("message", prompt="群?") -async def handle_group(bot: Bot, event: GroupMessageEvent): - return - - -@overload.got("message", prompt="私?") -async def handle_private(bot: Bot, event: PrivateMessageEvent): - return diff --git a/tests/test_plugins/test_permission.py b/tests/test_plugins/test_permission.py deleted file mode 100644 index 51e2f7cd..00000000 --- a/tests/test_plugins/test_permission.py +++ /dev/null @@ -1,18 +0,0 @@ -from nonebot.rule import to_me -from nonebot.typing import T_State -from nonebot.permission import SUPERUSER -from nonebot.plugin import on_startswith -from nonebot.adapters.ding import Bot as DingBot -from nonebot.adapters.cqhttp import Bot as CQHTTPBot - -test_command = on_startswith("hello", to_me(), permission=SUPERUSER) - - -@test_command.handle() -async def test_handler1(bot: CQHTTPBot): - await test_command.finish("cqhttp hello") - - -@test_command.handle() -async def test_handler2(bot: DingBot): - await test_command.finish("ding hello") diff --git a/tests/test_plugins/test_template.py b/tests/test_plugins/test_template.py deleted file mode 100644 index 6ca02081..00000000 --- a/tests/test_plugins/test_template.py +++ /dev/null @@ -1,14 +0,0 @@ -from nonebot import on_command -from nonebot.typing import T_State -from nonebot.adapters.cqhttp import Bot, MessageSegment, GroupMessageEvent - -template = on_command("template") - - -@template.handle() -async def _(bot: Bot, event: GroupMessageEvent, state: T_State): - state["at"] = MessageSegment.at(event.get_user_id()) - state["test"] = "test" - # message: /template {at} hello {test}! - ft = event.message.template(event.message) - await template.send(ft)