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-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)