🔥 remove cqhttp files

This commit is contained in:
yanyongyu 2021-11-23 16:21:21 +08:00
parent db5d4d7acf
commit 286729f703
26 changed files with 8 additions and 4016 deletions

View File

@ -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]]`

View File

@ -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:

View File

@ -1,32 +1,10 @@
from functools import reduce
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot.adapters import Event
from nonebot.plugin import on_command 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 = on_command("echo", to_me())
@echo.handle() @echo.handle()
async def echo_escape(event: MessageEvent): async def echo_escape(event: Event):
await echo.send(message=event.get_message()) await echo.send(message=event.get_message())

View File

@ -1,11 +0,0 @@
<p align="center">
<a href="https://v2.nonebot.dev/"><img src="https://raw.githubusercontent.com/nonebot/nonebot2/master/docs/.vuepress/public/logo.png" width="200" height="200" alt="nonebot"></a>
</p>
<div align="center">
# NoneBot-Adapter-CQHTTP
_✨ OneBot(CQHTTP) 协议适配 ✨_
</div>

View File

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

View File

@ -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"<r><bg #f8bbd0>Bad url {escape_tag(url)} for bot {escape_tag(self_id)} "
"in cqhttp forward websocket</bg #f8bbd0></r>"
)
@classmethod
@overrides(BaseBot)
async def check_permission(
cls, driver: Driver, request: HTTPConnection
) -> Tuple[Optional[str], HTTPResponse]:
"""
:说明:
CQHTTP (OneBot) 协议鉴权参考 `鉴权 <https://github.com/howmanybots/onebot/blob/master/v11/specs/communication/authorization.md>`_
"""
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"<r><bg #f8bbd0>Failed to handle event. Raw: {escape_tag(str(data))}</bg #f8bbd0></r>"
)
@overrides(BaseBot)
async def _call_api(self, api: str, **data) -> Any:
log("DEBUG", f"Calling API <y>{api}</y>")
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)

View File

@ -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:
"""
:说明:
清理数据目录
"""
...

View File

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

View File

@ -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"<le>{escape_tag(str(x))}</le>",
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"<le>{escape_tag(str(x))}</le>",
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",
]

View File

@ -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"<ActionFailed "
+ ", ".join(f"{k}={v}" for k, v in self.info.items())
+ ">"
)
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"<NetWorkError message={self.msg}>"
def __str__(self):
return self.__repr__()
class ApiNotAvailable(BaseApiNotAvailable, CQHTTPAdapterException):
pass

View File

@ -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<type>[a-zA-Z0-9-_.]+)"
r"(?P<params>"
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())

View File

@ -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",
]

View File

@ -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("&", "&amp;").replace("[", "&#91;").replace("]", "&#93;")
if escape_comma:
s = s.replace(",", "&#44;")
return s
def unescape(s: str) -> str:
"""
:说明:
对字符串进行 CQ 码去转义
:参数:
* ``s: str``: 需要转义的字符串
"""
return (
s.replace("&#44;", ",")
.replace("&#91;", "[")
.replace("&#93;", "]")
.replace("&amp;", "&")
)
def _b2s(b: Optional[bool]) -> Optional[str]:
"""转换布尔值为字符串。"""
return b if b is None else str(b).lower()

View File

@ -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"},
]

View File

@ -1,54 +0,0 @@
[tool.poetry]
name = "nonebot-adapter-cqhttp"
version = "2.0.0-alpha.16"
description = "OneBot(CQHTTP) adapter for nonebot2"
authors = ["yanyongyu <yyy@nonebot.dev>"]
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"

28
poetry.lock generated
View File

@ -77,7 +77,7 @@ python-versions = "*"
[[package]] [[package]]
name = "anyio" name = "anyio"
version = "3.3.4" version = "3.4.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations" description = "High level compatibility layer for multiple asynchronous event loop implementations"
category = "main" category = "main"
optional = false optional = false
@ -90,7 +90,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] 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)"] trio = ["trio (>=0.16)"]
[[package]] [[package]]
@ -509,23 +509,6 @@ category = "dev"
optional = false optional = false
python-versions = "*" 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]] [[package]]
name = "nonebot-adapter-ding" name = "nonebot-adapter-ding"
version = "2.0.0-alpha.16" version = "2.0.0-alpha.16"
@ -1197,7 +1180,7 @@ quart = ["Quart"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.7.3" python-versions = "^3.7.3"
content-hash = "9a64b2ba25ea3367e1636545241122d5b4d454ab3042865416193f84bf358fc3" content-hash = "9c7bf3b0936f4084baf0184046f4443a37c60dadb289c2baaa4360c8d85e3ae8"
[metadata.files] [metadata.files]
aiocache = [ aiocache = [
@ -1295,8 +1278,8 @@ alabaster = [
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
] ]
anyio = [ anyio = [
{file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"}, {file = "anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"},
{file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"}, {file = "anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"},
] ]
asgiref = [ asgiref = [
{file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, {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-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
] ]
nonebot-adapter-cqhttp = []
nonebot-adapter-ding = [] nonebot-adapter-ding = []
nonebot-adapter-feishu = [] nonebot-adapter-feishu = []
nonebot-adapter-mirai = [] nonebot-adapter-mirai = []

View File

@ -40,7 +40,6 @@ sphinx = "^4.1.1"
isort = "^5.10.1" isort = "^5.10.1"
black = "^21.11b1" black = "^21.11b1"
nonebot-plugin-test = "^0.3.0" 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-ding = { path = "./packages/nonebot-adapter-ding", develop = true }
nonebot-adapter-mirai = { path = "./packages/nonebot-adapter-mirai", develop = true } nonebot-adapter-mirai = { path = "./packages/nonebot-adapter-mirai", develop = true }
nonebot-adapter-feishu = { path = "./packages/nonebot-adapter-feishu", develop = true } nonebot-adapter-feishu = { path = "./packages/nonebot-adapter-feishu", develop = true }

View File

@ -4,7 +4,6 @@ import sys
sys.path.insert(0, os.path.abspath("..")) sys.path.insert(0, os.path.abspath(".."))
import nonebot import nonebot
from nonebot.adapters.cqhttp import Bot
from nonebot.log import logger, default_format from nonebot.log import logger, default_format
from nonebot.adapters.ding import Bot as DingBot from nonebot.adapters.ding import Bot as DingBot
from nonebot.adapters.mirai import Bot as MiraiBot from nonebot.adapters.mirai import Bot as MiraiBot
@ -18,7 +17,6 @@ logger.add(
nonebot.init(custom_config2="config on init") nonebot.init(custom_config2="config on init")
app = nonebot.get_asgi() app = nonebot.get_asgi()
driver = nonebot.get_driver() driver = nonebot.get_driver()
driver.register_adapter("cqhttp", Bot)
driver.register_adapter("ding", DingBot) driver.register_adapter("ding", DingBot)
driver.register_adapter("mirai", MiraiBot) driver.register_adapter("mirai", MiraiBot)
driver.register_adapter("feishu", FeishuBot) driver.register_adapter("feishu", FeishuBot)

View File

@ -4,4 +4,4 @@ from nonebot import CommandGroup, MatcherGroup
cmd = CommandGroup("test", rule=to_me()) cmd = CommandGroup("test", rule=to_me())
match = MatcherGroup(priority=2) match = MatcherGroup(priority=2)
from . import matches, commands from . import commands

View File

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

View File

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

View File

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

View File

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

View File

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