mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-27 18:45:05 +08:00
🔥 remove cqhttp files
This commit is contained in:
parent
db5d4d7acf
commit
286729f703
@ -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]]`
|
@ -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:
|
@ -1,32 +1,10 @@
|
||||
from functools import reduce
|
||||
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.adapters import Event
|
||||
from nonebot.plugin import on_command
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.adapters.cqhttp import (
|
||||
Message,
|
||||
MessageEvent,
|
||||
MessageSegment,
|
||||
unescape,
|
||||
)
|
||||
|
||||
say = on_command("say", to_me(), permission=SUPERUSER)
|
||||
|
||||
|
||||
@say.handle()
|
||||
async def say_unescape(event: MessageEvent):
|
||||
def _unescape(message: Message, segment: MessageSegment):
|
||||
if segment.is_text():
|
||||
return message.append(unescape(str(segment)))
|
||||
return message.append(segment)
|
||||
|
||||
message = reduce(_unescape, event.get_message(), Message()) # type: ignore
|
||||
await say.send(message=message)
|
||||
|
||||
|
||||
echo = on_command("echo", to_me())
|
||||
|
||||
|
||||
@echo.handle()
|
||||
async def echo_escape(event: MessageEvent):
|
||||
async def echo_escape(event: Event):
|
||||
await echo.send(message=event.get_message())
|
||||
|
@ -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>
|
@ -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
|
@ -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)
|
@ -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:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
清理数据目录。
|
||||
|
||||
"""
|
||||
...
|
@ -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
|
@ -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",
|
||||
]
|
@ -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
|
@ -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())
|
@ -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",
|
||||
]
|
@ -1,45 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from nonebot.utils import logger_wrapper
|
||||
|
||||
log = logger_wrapper("CQHTTP")
|
||||
|
||||
|
||||
def escape(s: str, *, escape_comma: bool = True) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
对字符串进行 CQ 码转义。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``s: str``: 需要转义的字符串
|
||||
* ``escape_comma: bool``: 是否转义逗号(``,``)。
|
||||
"""
|
||||
s = s.replace("&", "&").replace("[", "[").replace("]", "]")
|
||||
if escape_comma:
|
||||
s = s.replace(",", ",")
|
||||
return s
|
||||
|
||||
|
||||
def unescape(s: str) -> str:
|
||||
"""
|
||||
:说明:
|
||||
|
||||
对字符串进行 CQ 码去转义。
|
||||
|
||||
:参数:
|
||||
|
||||
* ``s: str``: 需要转义的字符串
|
||||
"""
|
||||
return (
|
||||
s.replace(",", ",")
|
||||
.replace("[", "[")
|
||||
.replace("]", "]")
|
||||
.replace("&", "&")
|
||||
)
|
||||
|
||||
|
||||
def _b2s(b: Optional[bool]) -> Optional[str]:
|
||||
"""转换布尔值为字符串。"""
|
||||
return b if b is None else str(b).lower()
|
649
packages/nonebot-adapter-cqhttp/poetry.lock
generated
649
packages/nonebot-adapter-cqhttp/poetry.lock
generated
@ -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"},
|
||||
]
|
@ -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
28
poetry.lock
generated
@ -77,7 +77,7 @@ python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "3.3.4"
|
||||
version = "3.4.0"
|
||||
description = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
category = "main"
|
||||
optional = false
|
||||
@ -90,7 +90,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
||||
|
||||
[package.extras]
|
||||
doc = ["sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
|
||||
trio = ["trio (>=0.16)"]
|
||||
|
||||
[[package]]
|
||||
@ -509,23 +509,6 @@ category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "nonebot-adapter-cqhttp"
|
||||
version = "2.0.0-alpha.16"
|
||||
description = "OneBot(CQHTTP) adapter for nonebot2"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "^3.7.3"
|
||||
develop = true
|
||||
|
||||
[package.dependencies]
|
||||
httpx = ">=0.20.0, <1.0.0"
|
||||
nonebot2 = "^2.0.0-alpha.14"
|
||||
|
||||
[package.source]
|
||||
type = "directory"
|
||||
url = "packages/nonebot-adapter-cqhttp"
|
||||
|
||||
[[package]]
|
||||
name = "nonebot-adapter-ding"
|
||||
version = "2.0.0-alpha.16"
|
||||
@ -1197,7 +1180,7 @@ quart = ["Quart"]
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.7.3"
|
||||
content-hash = "9a64b2ba25ea3367e1636545241122d5b4d454ab3042865416193f84bf358fc3"
|
||||
content-hash = "9c7bf3b0936f4084baf0184046f4443a37c60dadb289c2baaa4360c8d85e3ae8"
|
||||
|
||||
[metadata.files]
|
||||
aiocache = [
|
||||
@ -1295,8 +1278,8 @@ alabaster = [
|
||||
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
|
||||
]
|
||||
anyio = [
|
||||
{file = "anyio-3.3.4-py3-none-any.whl", hash = "sha256:4fd09a25ab7fa01d34512b7249e366cd10358cdafc95022c7ff8c8f8a5026d66"},
|
||||
{file = "anyio-3.3.4.tar.gz", hash = "sha256:67da67b5b21f96b9d3d65daa6ea99f5d5282cb09f50eb4456f8fb51dffefc3ff"},
|
||||
{file = "anyio-3.4.0-py3-none-any.whl", hash = "sha256:2855a9423524abcdd652d942f8932fda1735210f77a6b392eafd9ff34d3fe020"},
|
||||
{file = "anyio-3.4.0.tar.gz", hash = "sha256:24adc69309fb5779bc1e06158e143e0b6d2c56b302a3ac3de3083c705a6ed39d"},
|
||||
]
|
||||
asgiref = [
|
||||
{file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
|
||||
@ -1781,7 +1764,6 @@ mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
nonebot-adapter-cqhttp = []
|
||||
nonebot-adapter-ding = []
|
||||
nonebot-adapter-feishu = []
|
||||
nonebot-adapter-mirai = []
|
||||
|
@ -40,7 +40,6 @@ sphinx = "^4.1.1"
|
||||
isort = "^5.10.1"
|
||||
black = "^21.11b1"
|
||||
nonebot-plugin-test = "^0.3.0"
|
||||
nonebot-adapter-cqhttp = { path = "./packages/nonebot-adapter-cqhttp", develop = true }
|
||||
nonebot-adapter-ding = { path = "./packages/nonebot-adapter-ding", develop = true }
|
||||
nonebot-adapter-mirai = { path = "./packages/nonebot-adapter-mirai", develop = true }
|
||||
nonebot-adapter-feishu = { path = "./packages/nonebot-adapter-feishu", develop = true }
|
||||
|
@ -4,7 +4,6 @@ import sys
|
||||
sys.path.insert(0, os.path.abspath(".."))
|
||||
|
||||
import nonebot
|
||||
from nonebot.adapters.cqhttp import Bot
|
||||
from nonebot.log import logger, default_format
|
||||
from nonebot.adapters.ding import Bot as DingBot
|
||||
from nonebot.adapters.mirai import Bot as MiraiBot
|
||||
@ -18,7 +17,6 @@ logger.add(
|
||||
nonebot.init(custom_config2="config on init")
|
||||
app = nonebot.get_asgi()
|
||||
driver = nonebot.get_driver()
|
||||
driver.register_adapter("cqhttp", Bot)
|
||||
driver.register_adapter("ding", DingBot)
|
||||
driver.register_adapter("mirai", MiraiBot)
|
||||
driver.register_adapter("feishu", FeishuBot)
|
||||
|
@ -4,4 +4,4 @@ from nonebot import CommandGroup, MatcherGroup
|
||||
cmd = CommandGroup("test", rule=to_me())
|
||||
match = MatcherGroup(priority=2)
|
||||
|
||||
from . import matches, commands
|
||||
from . import commands
|
||||
|
@ -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")
|
@ -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")
|
@ -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
|
@ -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")
|
@ -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)
|
Loading…
Reference in New Issue
Block a user