diff --git a/archive/2.0.0a2/api/adapters/README.md b/archive/2.0.0a2/api/adapters/README.md deleted file mode 100644 index b652999012de..000000000000 --- a/archive/2.0.0a2/api/adapters/README.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -contentSidebar: true -sidebarDepth: 0 ---- - -# NoneBot.adapters 模块 - - -## _class_ `BaseBot` - -基类:`abc.ABC` - - -## _class_ `BaseEvent` - -基类:`abc.ABC` - - -### `_raw_event` - -原始 event - - -## _class_ `BaseMessageSegment` - -基类:`abc.ABC` - - -## _class_ `BaseMessage` - -基类:`list`, `abc.ABC` - - -### `append(obj)` - -Append object to the end of the list. - - -### `extend(obj)` - -Extend list by appending elements from the iterable. diff --git a/archive/2.0.0a2/README.md b/archive/2.0.0a3/README.md similarity index 100% rename from archive/2.0.0a2/README.md rename to archive/2.0.0a3/README.md diff --git a/archive/2.0.0a2/api/README.md b/archive/2.0.0a3/api/README.md similarity index 72% rename from archive/2.0.0a2/api/README.md rename to archive/2.0.0a3/api/README.md index 1c8acf1b3f68..52c6e9f6295b 100644 --- a/archive/2.0.0a2/api/README.md +++ b/archive/2.0.0a3/api/README.md @@ -7,28 +7,40 @@ * [nonebot](nonebot.html) - * [nonebot.typing](typing.html) + * [nonebot.config](config.html) - * [nonebot.config](config.html) + * [nonebot.matcher](matcher.html) - * [nonebot.sched](sched.html) + * [nonebot.rule](rule.html) - * [nonebot.log](log.html) + * [nonebot.permission](permission.html) - * [nonebot.rule](rule.html) + * [nonebot.sched](sched.html) - * [nonebot.permission](permission.html) + * [nonebot.log](log.html) * [nonebot.utils](utils.html) + * [nonebot.typing](typing.html) + + * [nonebot.exception](exception.html) + * [nonebot.drivers](drivers/) + + + * [nonebot.drivers.fastapi](drivers/fastapi.html) + + + * [nonebot.adapters](adapters/) + + * [nonebot.adapters.cqhttp](adapters/cqhttp.html) diff --git a/archive/2.0.0a3/api/adapters/README.md b/archive/2.0.0a3/api/adapters/README.md new file mode 100644 index 000000000000..f3f937ec6932 --- /dev/null +++ b/archive/2.0.0a3/api/adapters/README.md @@ -0,0 +1,323 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.adapters 模块 + +## 协议适配基类 + +各协议请继承以下基类,并使用 `driver.register_adapter` 注册适配器 + + +## _class_ `BaseBot` + +基类:`abc.ABC` + +Bot 基类。用于处理上报消息,并提供 API 调用接口。 + + +### _abstract_ `__init__(driver, connection_type, config, self_id, *, websocket=None)` + + +* **参数** + + + * `driver: Driver`: Driver 对象 + + + * `connection_type: str`: http 或者 websocket + + + * `config: Config`: Config 对象 + + + * `self_id: str`: 机器人 ID + + + * `websocket: Optional[WebSocket]`: Websocket 连接对象 + + + +### `driver` + +Driver 对象 + + +### `connection_type` + +连接类型 + + +### `config` + +Config 配置对象 + + +### `self_id` + +机器人 ID + + +### `websocket` + +Websocket 连接对象 + + +### _abstract property_ `type` + +Adapter 类型 + + +### _abstract async_ `handle_message(message)` + + +* **说明** + + 处理上报消息的函数,转换为 `Event` 事件后调用 `nonebot.message.handle_event` 进一步处理事件。 + + + +* **参数** + + + * `message: dict`: 收到的上报消息 + + + +### _abstract async_ `call_api(api, **data)` + + +* **说明** + + 调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用 + + + +* **参数** + + + * `api: str`: API 名称 + + + * `**data`: API 数据 + + + +* **示例** + + +```python +await bot.call_api("send_msg", data={"message": "hello world"}) +await bot.send_msg(message="hello world") +``` + + +### _abstract async_ `send(event, message, **kwargs)` + + +* **说明** + + 调用机器人基础发送消息接口 + + + +* **参数** + + + * `event: Event`: 上报事件 + + + * `message: Union[str, Message, MessageSegment]`: 要发送的消息 + + + * `**kwargs` + + + +## _class_ `BaseEvent` + +基类:`abc.ABC` + +Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。 + + +### `__init__(raw_event)` + + +* **参数** + + + * `raw_event: dict`: 原始上报消息 + + + +### _property_ `raw_event` + +原始上报消息 + + +### _abstract property_ `id` + +事件 ID + + +### _abstract property_ `name` + +事件名称 + + +### _abstract property_ `self_id` + +机器人 ID + + +### _abstract property_ `time` + +事件发生时间 + + +### _abstract property_ `type` + +事件主类型 + + +### _abstract property_ `detail_type` + +事件详细类型 + + +### _abstract property_ `sub_type` + +事件子类型 + + +### _abstract property_ `user_id` + +触发事件的主体 ID + + +### _abstract property_ `group_id` + +触发事件的主体群 ID + + +### _abstract property_ `to_me` + +事件是否为发送给机器人的消息 + + +### _abstract property_ `message` + +消息内容 + + +### _abstract property_ `reply` + +回复的消息 + + +### _abstract property_ `raw_message` + +原始消息 + + +### _abstract property_ `plain_text` + +纯文本消息 + + +### _abstract property_ `sender` + +消息发送者信息 + + +## _class_ `BaseMessageSegment` + +基类:`abc.ABC` + +消息段基类 + + +### `type` + + +* 类型: `str` + + +* 说明: 消息段类型 + + +### `data` + + +* 类型: `Dict[str, Union[str, list]]` + + +* 说明: 消息段数据 + + +## _class_ `BaseMessage` + +基类:`list`, `abc.ABC` + +消息数组 + + +### `__init__(message=None, *args, **kwargs)` + + +* **参数** + + + * `message: Union[str, dict, list, MessageSegment, Message]`: 消息内容 + + + +### `append(obj)` + + +* **说明** + + 添加一个消息段到消息数组末尾 + + + +* **参数** + + + * `obj: Union[str, MessageSegment]`: 要添加的消息段 + + + +### `extend(obj)` + + +* **说明** + + 拼接一个消息数组或多个消息段到消息数组末尾 + + + +* **参数** + + + * `obj: Union[Message, Iterable[MessageSegment]]`: 要添加的消息数组 + + + +### `reduce()` + + +* **说明** + + 缩减消息数组,即拼接相邻纯文本消息段 + + + +### `extract_plain_text()` + + +* **说明** + + 提取消息内纯文本消息 diff --git a/archive/2.0.0a2/api/adapters/cqhttp.md b/archive/2.0.0a3/api/adapters/cqhttp.md similarity index 98% rename from archive/2.0.0a2/api/adapters/cqhttp.md rename to archive/2.0.0a3/api/adapters/cqhttp.md index 53fa04f9921b..aae78f8668cd 100644 --- a/archive/2.0.0a2/api/adapters/cqhttp.md +++ b/archive/2.0.0a3/api/adapters/cqhttp.md @@ -323,10 +323,10 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent) ### _property_ `sub_type` -* 类型: `str` +* 类型: `Optional[str]` -* 说明: 事件类型 +* 说明: 事件子类型 ### _property_ `user_id` diff --git a/archive/2.0.0a2/api/config.md b/archive/2.0.0a3/api/config.md similarity index 98% rename from archive/2.0.0a2/api/config.md rename to archive/2.0.0a3/api/config.md index fd90f50ebe81..6943427b4f1a 100644 --- a/archive/2.0.0a2/api/config.md +++ b/archive/2.0.0a3/api/config.md @@ -194,10 +194,10 @@ SUPER_USERS=[12345789] ### `nickname` -* 类型: `Union[str, Set[str]]` +* 类型: `Set[str]` -* 默认值: `""` +* 默认值: `set()` * 说明: diff --git a/archive/2.0.0a3/api/drivers/README.md b/archive/2.0.0a3/api/drivers/README.md new file mode 100644 index 000000000000..f78812f0c6b3 --- /dev/null +++ b/archive/2.0.0a3/api/drivers/README.md @@ -0,0 +1,37 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.drivers 模块 + +## 后端驱动适配基类 + +各驱动请继承以下基类 + + +## _class_ `BaseDriver` + +基类:`abc.ABC` + +Driver 基类。将后端框架封装,以满足适配器使用。 + + +### `_adapters` + + +* **类型** + + `Dict[str, Type[Bot]]` + + + +* **说明** + + 已注册的适配器列表 + + + +### _abstract_ `__init__(env, config)` + +Initialize self. See help(type(self)) for accurate signature. diff --git a/archive/2.0.0a3/api/drivers/fastapi.md b/archive/2.0.0a3/api/drivers/fastapi.md new file mode 100644 index 000000000000..029c9bc8fa97 --- /dev/null +++ b/archive/2.0.0a3/api/drivers/fastapi.md @@ -0,0 +1,16 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.drivers.fastapi 模块 + + +## _class_ `Driver` + +基类:[`nonebot.drivers.BaseDriver`](#None) + + +### `__init__(env, config)` + +Initialize self. See help(type(self)) for accurate signature. diff --git a/archive/2.0.0a2/api/exception.md b/archive/2.0.0a3/api/exception.md similarity index 100% rename from archive/2.0.0a2/api/exception.md rename to archive/2.0.0a3/api/exception.md diff --git a/archive/2.0.0a2/api/log.md b/archive/2.0.0a3/api/log.md similarity index 100% rename from archive/2.0.0a2/api/log.md rename to archive/2.0.0a3/api/log.md diff --git a/archive/2.0.0a3/api/matcher.md b/archive/2.0.0a3/api/matcher.md new file mode 100644 index 000000000000..c1176030a3f5 --- /dev/null +++ b/archive/2.0.0a3/api/matcher.md @@ -0,0 +1,485 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.matcher 模块 + +## 事件响应器 + +该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。 + + +## `matchers` + + +* **类型** + + `Dict[int, List[Type[Matcher]]]` + + + +* **说明** + + 用于存储当前所有的事件响应器 + + + +## _class_ `Matcher` + +基类:`object` + +事件响应器类 + + +### `module` + + +* **类型** + + `Optional[str]` + + + +* **说明** + + 事件响应器所在模块名称 + + + +### `type` + + +* **类型** + + `str` + + + +* **说明** + + 事件响应器类型 + + + +### `rule` + + +* **类型** + + `Rule` + + + +* **说明** + + 事件响应器匹配规则 + + + +### `permission` + + +* **类型** + + `Permission` + + + +* **说明** + + 事件响应器触发权限 + + + +### `priority` + + +* **类型** + + `int` + + + +* **说明** + + 事件响应器优先级 + + + +### `block` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否阻止事件传播 + + + +### `temp` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否为临时 + + + +### `expire_time` + + +* **类型** + + `Optional[datetime]` + + + +* **说明** + + 事件响应器过期时间点 + + + +### `_default_state` + + +* **类型** + + `dict` + + + +* **说明** + + 事件响应器默认状态 + + + +### `_default_parser` + + +* **类型** + + `Optional[ArgsParser]` + + + +* **说明** + + 事件响应器默认参数解析函数 + + + +### `__init__()` + +实例化 Matcher 以便运行 + + +### `handlers` + + +* **类型** + + `List[Handler]` + + + +* **说明** + + 事件响应器拥有的事件处理函数列表 + + + +### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 创建一个新的事件响应器,并存储至 [matchers](#matchers) + + + +* **参数** + + + * `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意 + + + * `rule: Optional[Rule]`: 匹配规则 + + + * `permission: Optional[Permission]`: 权限 + + + * `handlers: Optional[List[Handler]]`: 事件处理函数列表 + + + * `temp: bool`: 是否为临时事件响应器,即触发一次后删除 + + + * `priority: int`: 响应优先级 + + + * `block: bool`: 是否阻止事件向更低优先级的响应器传播 + + + * `module: Optional[str]`: 事件响应器所在模块名称 + + + * `default_state: Optional[dict]`: 默认状态 `state` + + + * `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除 + + + +* **返回** + + + * `Type[Matcher]`: 新的事件响应器类 + + + +### _async classmethod_ `check_perm(bot, event)` + + +* **说明** + + 检查是否满足触发权限 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + +* **返回** + + + * `bool`: 是否满足权限 + + + +### _async classmethod_ `check_rule(bot, event, state)` + + +* **说明** + + 检查是否满足匹配规则 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + * `state: dict`: 当前状态 + + + +* **返回** + + + * `bool`: 是否满足匹配规则 + + + +### _classmethod_ `args_parser(func)` + + +* **说明** + + 装饰一个函数来更改当前事件响应器的默认参数解析函数 + + + +* **参数** + + + * `func: ArgsParser`: 参数解析函数 + + + +### _classmethod_ `handle()` + + +* **说明** + + 装饰一个函数来向事件响应器直接添加一个处理函数 + + + +* **参数** + + + * 无 + + + +### _classmethod_ `receive()` + + +* **说明** + + 装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数 + + + +* **参数** + + + * 无 + + + +### _classmethod_ `got(key, prompt=None, args_parser=None)` + + +* **说明** + + 装饰一个函数来指示 NoneBot 当要获取的 `key` 不存在时接收用户新的一条消息并经过 `ArgsParser` 处理后再运行该函数,如果 `key` 已存在则直接继续运行 + + + +* **参数** + + + * `key: str`: 参数名 + + + * `prompt: Optional[Union[str, Message, MessageSegment]]`: 在参数不存在时向用户发送的消息 + + + * `args_parser: Optional[ArgsParser]`: 可选参数解析函数,空则使用默认解析函数 + + + +### _async classmethod_ `send(message)` + + +* **说明** + + 发送一条消息给当前交互用户 + + + +* **参数** + + + * `message: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `finish(message=None)` + + +* **说明** + + 发送一条消息给当前交互用户并结束当前事件响应器 + + + +* **参数** + + + * `message: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `pause(prompt=None)` + + +* **说明** + + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数 + + + +* **参数** + + + * `prompt: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `reject(prompt=None)` + + +* **说明** + + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数 + + + +* **参数** + + + * `prompt: Union[str, Message, MessageSegment]`: 消息内容 + + + +## _class_ `MatcherGroup` + +基类:`object` + +事件响应器组合,统一管理。用法同 `Matcher` + + +### `__init__(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 创建一个事件响应器组合,参数为默认值,与 `Matcher.new` 一致 + + + +### `matchers` + + +* **类型** + + `List[Type[Matcher]]` + + + +* **说明** + + 组内事件响应器列表 + + + +### `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 在组中创建一个新的事件响应器,参数留空则使用组合默认值 + + +:::danger 警告 +如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数 +::: diff --git a/archive/2.0.0a2/api/nonebot.md b/archive/2.0.0a3/api/nonebot.md similarity index 74% rename from archive/2.0.0a2/api/nonebot.md rename to archive/2.0.0a3/api/nonebot.md index 3c278a5c3c2f..7c89c8828c42 100644 --- a/archive/2.0.0a2/api/nonebot.md +++ b/archive/2.0.0a3/api/nonebot.md @@ -5,6 +5,55 @@ sidebarDepth: 0 # NoneBot 模块 +## 快捷导入 + +为方便使用,`nonebot` 模块从子模块导入了部分内容 + + +* `on_message` => `nonebot.plugin.on_message` + + +* `on_notice` => `nonebot.plugin.on_notice` + + +* `on_request` => `nonebot.plugin.on_request` + + +* `on_metaevent` => `nonebot.plugin.on_metaevent` + + +* `on_startswith` => `nonebot.plugin.on_startswith` + + +* `on_endswith` => `nonebot.plugin.on_endswith` + + +* `on_command` => `nonebot.plugin.on_command` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `CommandGroup` => `nonebot.plugin.CommandGroup` + + +* `load_plugin` => `nonebot.plugin.load_plugin` + + +* `load_plugins` => `nonebot.plugin.load_plugins` + + +* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins` + + +* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins` + ## `get_driver()` diff --git a/archive/2.0.0a2/api/permission.md b/archive/2.0.0a3/api/permission.md similarity index 100% rename from archive/2.0.0a2/api/permission.md rename to archive/2.0.0a3/api/permission.md diff --git a/archive/2.0.0a2/api/rule.md b/archive/2.0.0a3/api/rule.md similarity index 51% rename from archive/2.0.0a2/api/rule.md rename to archive/2.0.0a3/api/rule.md index 269abc570030..2054d04b5643 100644 --- a/archive/2.0.0a2/api/rule.md +++ b/archive/2.0.0a3/api/rule.md @@ -7,10 +7,10 @@ sidebarDepth: 0 ## 规则 -每个 `Matcher` 拥有一个 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 +每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 :::tip 提示 -`RuleChecker` 既可以是 async function 也可以是 sync function +`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function ::: @@ -120,3 +120,83 @@ Rule(async_function, run_sync(sync_function)) * `msg: str`: 消息结尾字符串 + + + +## `keyword(msg)` + + +* **说明** + + 匹配消息关键词 + + + +* **参数** + + + * `msg: str`: 关键词 + + + +## `command(command)` + + +* **说明** + + 命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。 + + + +* **参数** + + + * `command: Tuples[str, ...]`: 命令内容 + + + +* **示例** + + 使用默认 `command_start`, `command_sep` 配置 + + 命令 `("test",)` 可以匹配:`/test` 开头的消息 + 命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息 + + +:::tip 提示 +命令内容与后续消息间无需空格! +::: + + +## `regex(regex, flags=0)` + + +* **说明** + + 根据正则表达式进行匹配 + + + +* **参数** + + + * `regex: str`: 正则表达式 + + + * `flags: Union[int, re.RegexFlag]`: 正则标志 + + + +## `to_me()` + + +* **说明** + + 通过 `event.to_me` 判断消息是否是发送给机器人 + + + +* **参数** + + + * 无 diff --git a/archive/2.0.0a2/api/sched.md b/archive/2.0.0a3/api/sched.md similarity index 100% rename from archive/2.0.0a2/api/sched.md rename to archive/2.0.0a3/api/sched.md diff --git a/archive/2.0.0a2/api/typing.md b/archive/2.0.0a3/api/typing.md similarity index 100% rename from archive/2.0.0a2/api/typing.md rename to archive/2.0.0a3/api/typing.md diff --git a/archive/2.0.0a2/api/utils.md b/archive/2.0.0a3/api/utils.md similarity index 100% rename from archive/2.0.0a2/api/utils.md rename to archive/2.0.0a3/api/utils.md diff --git a/archive/2.0.0a2/guide/README.md b/archive/2.0.0a3/guide/README.md similarity index 63% rename from archive/2.0.0a2/guide/README.md rename to archive/2.0.0a3/guide/README.md index 6cf31e908a35..86397ee27a09 100644 --- a/archive/2.0.0a2/guide/README.md +++ b/archive/2.0.0a3/guide/README.md @@ -20,11 +20,7 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人 ## 它如何工作? -NoneBot 的运行离不开 酷 Q 和 CQHTTP 插件。酷 Q 扮演着「无头 QQ 客户端」的角色,它进行实际的消息、通知、请求的接收和发送,当 酷 Q 收到消息时,它将这个消息包装为一个事件(通知和请求同理),并通过它自己的插件机制将事件传送给 CQHTTP 插件,后者再根据其配置中的 `post_url` 或 `ws_reverse_url` 等项来将事件发送至 NoneBot。 - -在 NoneBot 收到事件前,它底层的 aiocqhttp 实际已经先看到了事件,aiocqhttp 根据事件的类型信息,通知到 NoneBot 的相应函数。特别地,对于消息类型的事件,还将消息内容转换成了 `aiocqhttp.message.Message` 类型,以便处理。 - -NoneBot 的事件处理函数收到通知后,对于不同类型的事件,再做相应的预处理和解析,然后调用对应的插件,并向其提供适合此类事件的会话(Session)对象。NoneBot 插件的编写者要做的,就是利用 Session 对象中提供的数据,在插件的处理函数中实现所需的功能。 +~~未填坑~~ ## 特色 diff --git a/archive/2.0.0a2/guide/basic-configuration.md b/archive/2.0.0a3/guide/basic-configuration.md similarity index 100% rename from archive/2.0.0a2/guide/basic-configuration.md rename to archive/2.0.0a3/guide/basic-configuration.md diff --git a/archive/2.0.0a2/guide/creating-a-project.md b/archive/2.0.0a3/guide/creating-a-project.md similarity index 100% rename from archive/2.0.0a2/guide/creating-a-project.md rename to archive/2.0.0a3/guide/creating-a-project.md diff --git a/archive/2.0.0a2/guide/getting-started.md b/archive/2.0.0a3/guide/getting-started.md similarity index 100% rename from archive/2.0.0a2/guide/getting-started.md rename to archive/2.0.0a3/guide/getting-started.md diff --git a/archive/2.0.0a2/guide/installation.md b/archive/2.0.0a3/guide/installation.md similarity index 100% rename from archive/2.0.0a2/guide/installation.md rename to archive/2.0.0a3/guide/installation.md diff --git a/archive/2.0.0a2/guide/writing-a-plugin.md b/archive/2.0.0a3/guide/writing-a-plugin.md similarity index 100% rename from archive/2.0.0a2/guide/writing-a-plugin.md rename to archive/2.0.0a3/guide/writing-a-plugin.md diff --git a/archive/2.0.0a2/sidebar.config.json b/archive/2.0.0a3/sidebar.config.json similarity index 86% rename from archive/2.0.0a2/sidebar.config.json rename to archive/2.0.0a3/sidebar.config.json index bec088a6b8e9..c68d09ef6173 100644 --- a/archive/2.0.0a2/sidebar.config.json +++ b/archive/2.0.0a3/sidebar.config.json @@ -47,21 +47,13 @@ "title": "nonebot 模块", "path": "nonebot" }, - { - "title": "nonebot.typing 模块", - "path": "typing" - }, { "title": "nonebot.config 模块", "path": "config" }, { - "title": "nonebot.sched 模块", - "path": "sched" - }, - { - "title": "nonebot.log 模块", - "path": "log" + "title": "nonebot.matcher 模块", + "path": "matcher" }, { "title": "nonebot.rule 模块", @@ -71,14 +63,34 @@ "title": "nonebot.permission 模块", "path": "permission" }, + { + "title": "nonebot.sched 模块", + "path": "sched" + }, + { + "title": "nonebot.log 模块", + "path": "log" + }, { "title": "nonebot.utils 模块", "path": "utils" }, + { + "title": "nonebot.typing 模块", + "path": "typing" + }, { "title": "nonebot.exception 模块", "path": "exception" }, + { + "title": "nonebot.drivers 模块", + "path": "drivers/" + }, + { + "title": "nonebot.drivers.fastapi 模块", + "path": "drivers/fastapi" + }, { "title": "nonebot.adapters 模块", "path": "adapters/" diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index da72ca0c29c1..863b0d64b5a6 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -88,21 +88,13 @@ module.exports = context => ({ title: "nonebot 模块", path: "nonebot" }, - { - title: "nonebot.typing 模块", - path: "typing" - }, { title: "nonebot.config 模块", path: "config" }, { - title: "nonebot.sched 模块", - path: "sched" - }, - { - title: "nonebot.log 模块", - path: "log" + title: "nonebot.matcher 模块", + path: "matcher" }, { title: "nonebot.rule 模块", @@ -112,14 +104,34 @@ module.exports = context => ({ title: "nonebot.permission 模块", path: "permission" }, + { + title: "nonebot.sched 模块", + path: "sched" + }, + { + title: "nonebot.log 模块", + path: "log" + }, { title: "nonebot.utils 模块", path: "utils" }, + { + title: "nonebot.typing 模块", + path: "typing" + }, { title: "nonebot.exception 模块", path: "exception" }, + { + title: "nonebot.drivers 模块", + path: "drivers/" + }, + { + title: "nonebot.drivers.fastapi 模块", + path: "drivers/fastapi" + }, { title: "nonebot.adapters 模块", path: "adapters/" diff --git a/docs/.vuepress/versions.json b/docs/.vuepress/versions.json index 386fcf77b3e1..65abfcfd972d 100644 --- a/docs/.vuepress/versions.json +++ b/docs/.vuepress/versions.json @@ -1,3 +1,3 @@ [ - "2.0.0a2" + "2.0.0a3" ] \ No newline at end of file diff --git a/docs/api/README.md b/docs/api/README.md index 1c8acf1b3f68..52c6e9f6295b 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -7,28 +7,40 @@ * [nonebot](nonebot.html) - * [nonebot.typing](typing.html) + * [nonebot.config](config.html) - * [nonebot.config](config.html) + * [nonebot.matcher](matcher.html) - * [nonebot.sched](sched.html) + * [nonebot.rule](rule.html) - * [nonebot.log](log.html) + * [nonebot.permission](permission.html) - * [nonebot.rule](rule.html) + * [nonebot.sched](sched.html) - * [nonebot.permission](permission.html) + * [nonebot.log](log.html) * [nonebot.utils](utils.html) + * [nonebot.typing](typing.html) + + * [nonebot.exception](exception.html) + * [nonebot.drivers](drivers/) + + + * [nonebot.drivers.fastapi](drivers/fastapi.html) + + + * [nonebot.adapters](adapters/) + + * [nonebot.adapters.cqhttp](adapters/cqhttp.html) diff --git a/docs/api/adapters/README.md b/docs/api/adapters/README.md index b652999012de..f3f937ec6932 100644 --- a/docs/api/adapters/README.md +++ b/docs/api/adapters/README.md @@ -5,37 +5,319 @@ sidebarDepth: 0 # NoneBot.adapters 模块 +## 协议适配基类 + +各协议请继承以下基类,并使用 `driver.register_adapter` 注册适配器 + ## _class_ `BaseBot` 基类:`abc.ABC` +Bot 基类。用于处理上报消息,并提供 API 调用接口。 + + +### _abstract_ `__init__(driver, connection_type, config, self_id, *, websocket=None)` + + +* **参数** + + + * `driver: Driver`: Driver 对象 + + + * `connection_type: str`: http 或者 websocket + + + * `config: Config`: Config 对象 + + + * `self_id: str`: 机器人 ID + + + * `websocket: Optional[WebSocket]`: Websocket 连接对象 + + + +### `driver` + +Driver 对象 + + +### `connection_type` + +连接类型 + + +### `config` + +Config 配置对象 + + +### `self_id` + +机器人 ID + + +### `websocket` + +Websocket 连接对象 + + +### _abstract property_ `type` + +Adapter 类型 + + +### _abstract async_ `handle_message(message)` + + +* **说明** + + 处理上报消息的函数,转换为 `Event` 事件后调用 `nonebot.message.handle_event` 进一步处理事件。 + + + +* **参数** + + + * `message: dict`: 收到的上报消息 + + + +### _abstract async_ `call_api(api, **data)` + + +* **说明** + + 调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用 + + + +* **参数** + + + * `api: str`: API 名称 + + + * `**data`: API 数据 + + + +* **示例** + + +```python +await bot.call_api("send_msg", data={"message": "hello world"}) +await bot.send_msg(message="hello world") +``` + + +### _abstract async_ `send(event, message, **kwargs)` + + +* **说明** + + 调用机器人基础发送消息接口 + + + +* **参数** + + + * `event: Event`: 上报事件 + + + * `message: Union[str, Message, MessageSegment]`: 要发送的消息 + + + * `**kwargs` + + ## _class_ `BaseEvent` 基类:`abc.ABC` +Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。 + + +### `__init__(raw_event)` + + +* **参数** + + + * `raw_event: dict`: 原始上报消息 + + + +### _property_ `raw_event` + +原始上报消息 + + +### _abstract property_ `id` -### `_raw_event` +事件 ID -原始 event + +### _abstract property_ `name` + +事件名称 + + +### _abstract property_ `self_id` + +机器人 ID + + +### _abstract property_ `time` + +事件发生时间 + + +### _abstract property_ `type` + +事件主类型 + + +### _abstract property_ `detail_type` + +事件详细类型 + + +### _abstract property_ `sub_type` + +事件子类型 + + +### _abstract property_ `user_id` + +触发事件的主体 ID + + +### _abstract property_ `group_id` + +触发事件的主体群 ID + + +### _abstract property_ `to_me` + +事件是否为发送给机器人的消息 + + +### _abstract property_ `message` + +消息内容 + + +### _abstract property_ `reply` + +回复的消息 + + +### _abstract property_ `raw_message` + +原始消息 + + +### _abstract property_ `plain_text` + +纯文本消息 + + +### _abstract property_ `sender` + +消息发送者信息 ## _class_ `BaseMessageSegment` 基类:`abc.ABC` +消息段基类 + + +### `type` + + +* 类型: `str` + + +* 说明: 消息段类型 + + +### `data` + + +* 类型: `Dict[str, Union[str, list]]` + + +* 说明: 消息段数据 + ## _class_ `BaseMessage` 基类:`list`, `abc.ABC` +消息数组 + + +### `__init__(message=None, *args, **kwargs)` + + +* **参数** + + + * `message: Union[str, dict, list, MessageSegment, Message]`: 消息内容 + + ### `append(obj)` -Append object to the end of the list. + +* **说明** + + 添加一个消息段到消息数组末尾 + + + +* **参数** + + + * `obj: Union[str, MessageSegment]`: 要添加的消息段 + ### `extend(obj)` -Extend list by appending elements from the iterable. + +* **说明** + + 拼接一个消息数组或多个消息段到消息数组末尾 + + + +* **参数** + + + * `obj: Union[Message, Iterable[MessageSegment]]`: 要添加的消息数组 + + + +### `reduce()` + + +* **说明** + + 缩减消息数组,即拼接相邻纯文本消息段 + + + +### `extract_plain_text()` + + +* **说明** + + 提取消息内纯文本消息 diff --git a/docs/api/adapters/cqhttp.md b/docs/api/adapters/cqhttp.md index 53fa04f9921b..aae78f8668cd 100644 --- a/docs/api/adapters/cqhttp.md +++ b/docs/api/adapters/cqhttp.md @@ -323,10 +323,10 @@ CQHTTP 协议 Event 适配。继承属性参考 [BaseEvent](./#class-baseevent) ### _property_ `sub_type` -* 类型: `str` +* 类型: `Optional[str]` -* 说明: 事件类型 +* 说明: 事件子类型 ### _property_ `user_id` diff --git a/docs/api/config.md b/docs/api/config.md index fd90f50ebe81..6943427b4f1a 100644 --- a/docs/api/config.md +++ b/docs/api/config.md @@ -194,10 +194,10 @@ SUPER_USERS=[12345789] ### `nickname` -* 类型: `Union[str, Set[str]]` +* 类型: `Set[str]` -* 默认值: `""` +* 默认值: `set()` * 说明: diff --git a/docs/api/drivers/README.md b/docs/api/drivers/README.md new file mode 100644 index 000000000000..f78812f0c6b3 --- /dev/null +++ b/docs/api/drivers/README.md @@ -0,0 +1,37 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.drivers 模块 + +## 后端驱动适配基类 + +各驱动请继承以下基类 + + +## _class_ `BaseDriver` + +基类:`abc.ABC` + +Driver 基类。将后端框架封装,以满足适配器使用。 + + +### `_adapters` + + +* **类型** + + `Dict[str, Type[Bot]]` + + + +* **说明** + + 已注册的适配器列表 + + + +### _abstract_ `__init__(env, config)` + +Initialize self. See help(type(self)) for accurate signature. diff --git a/docs/api/drivers/fastapi.md b/docs/api/drivers/fastapi.md new file mode 100644 index 000000000000..029c9bc8fa97 --- /dev/null +++ b/docs/api/drivers/fastapi.md @@ -0,0 +1,16 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.drivers.fastapi 模块 + + +## _class_ `Driver` + +基类:[`nonebot.drivers.BaseDriver`](#None) + + +### `__init__(env, config)` + +Initialize self. See help(type(self)) for accurate signature. diff --git a/docs/api/matcher.md b/docs/api/matcher.md new file mode 100644 index 000000000000..c1176030a3f5 --- /dev/null +++ b/docs/api/matcher.md @@ -0,0 +1,485 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +# NoneBot.matcher 模块 + +## 事件响应器 + +该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。 + + +## `matchers` + + +* **类型** + + `Dict[int, List[Type[Matcher]]]` + + + +* **说明** + + 用于存储当前所有的事件响应器 + + + +## _class_ `Matcher` + +基类:`object` + +事件响应器类 + + +### `module` + + +* **类型** + + `Optional[str]` + + + +* **说明** + + 事件响应器所在模块名称 + + + +### `type` + + +* **类型** + + `str` + + + +* **说明** + + 事件响应器类型 + + + +### `rule` + + +* **类型** + + `Rule` + + + +* **说明** + + 事件响应器匹配规则 + + + +### `permission` + + +* **类型** + + `Permission` + + + +* **说明** + + 事件响应器触发权限 + + + +### `priority` + + +* **类型** + + `int` + + + +* **说明** + + 事件响应器优先级 + + + +### `block` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否阻止事件传播 + + + +### `temp` + + +* **类型** + + `bool` + + + +* **说明** + + 事件响应器是否为临时 + + + +### `expire_time` + + +* **类型** + + `Optional[datetime]` + + + +* **说明** + + 事件响应器过期时间点 + + + +### `_default_state` + + +* **类型** + + `dict` + + + +* **说明** + + 事件响应器默认状态 + + + +### `_default_parser` + + +* **类型** + + `Optional[ArgsParser]` + + + +* **说明** + + 事件响应器默认参数解析函数 + + + +### `__init__()` + +实例化 Matcher 以便运行 + + +### `handlers` + + +* **类型** + + `List[Handler]` + + + +* **说明** + + 事件响应器拥有的事件处理函数列表 + + + +### _classmethod_ `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 创建一个新的事件响应器,并存储至 [matchers](#matchers) + + + +* **参数** + + + * `type_: str`: 事件响应器类型,与 `event.type` 一致时触发,空字符串表示任意 + + + * `rule: Optional[Rule]`: 匹配规则 + + + * `permission: Optional[Permission]`: 权限 + + + * `handlers: Optional[List[Handler]]`: 事件处理函数列表 + + + * `temp: bool`: 是否为临时事件响应器,即触发一次后删除 + + + * `priority: int`: 响应优先级 + + + * `block: bool`: 是否阻止事件向更低优先级的响应器传播 + + + * `module: Optional[str]`: 事件响应器所在模块名称 + + + * `default_state: Optional[dict]`: 默认状态 `state` + + + * `expire_time: Optional[datetime]`: 事件响应器最终有效时间点,过时即被删除 + + + +* **返回** + + + * `Type[Matcher]`: 新的事件响应器类 + + + +### _async classmethod_ `check_perm(bot, event)` + + +* **说明** + + 检查是否满足触发权限 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + +* **返回** + + + * `bool`: 是否满足权限 + + + +### _async classmethod_ `check_rule(bot, event, state)` + + +* **说明** + + 检查是否满足匹配规则 + + + +* **参数** + + + * `bot: Bot`: Bot 对象 + + + * `event: Event`: 上报事件 + + + * `state: dict`: 当前状态 + + + +* **返回** + + + * `bool`: 是否满足匹配规则 + + + +### _classmethod_ `args_parser(func)` + + +* **说明** + + 装饰一个函数来更改当前事件响应器的默认参数解析函数 + + + +* **参数** + + + * `func: ArgsParser`: 参数解析函数 + + + +### _classmethod_ `handle()` + + +* **说明** + + 装饰一个函数来向事件响应器直接添加一个处理函数 + + + +* **参数** + + + * 无 + + + +### _classmethod_ `receive()` + + +* **说明** + + 装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数 + + + +* **参数** + + + * 无 + + + +### _classmethod_ `got(key, prompt=None, args_parser=None)` + + +* **说明** + + 装饰一个函数来指示 NoneBot 当要获取的 `key` 不存在时接收用户新的一条消息并经过 `ArgsParser` 处理后再运行该函数,如果 `key` 已存在则直接继续运行 + + + +* **参数** + + + * `key: str`: 参数名 + + + * `prompt: Optional[Union[str, Message, MessageSegment]]`: 在参数不存在时向用户发送的消息 + + + * `args_parser: Optional[ArgsParser]`: 可选参数解析函数,空则使用默认解析函数 + + + +### _async classmethod_ `send(message)` + + +* **说明** + + 发送一条消息给当前交互用户 + + + +* **参数** + + + * `message: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `finish(message=None)` + + +* **说明** + + 发送一条消息给当前交互用户并结束当前事件响应器 + + + +* **参数** + + + * `message: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `pause(prompt=None)` + + +* **说明** + + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数 + + + +* **参数** + + + * `prompt: Union[str, Message, MessageSegment]`: 消息内容 + + + +### _async classmethod_ `reject(prompt=None)` + + +* **说明** + + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数 + + + +* **参数** + + + * `prompt: Union[str, Message, MessageSegment]`: 消息内容 + + + +## _class_ `MatcherGroup` + +基类:`object` + +事件响应器组合,统一管理。用法同 `Matcher` + + +### `__init__(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 创建一个事件响应器组合,参数为默认值,与 `Matcher.new` 一致 + + + +### `matchers` + + +* **类型** + + `List[Type[Matcher]]` + + + +* **说明** + + 组内事件响应器列表 + + + +### `new(type_='', rule=None, permission=None, handlers=None, temp=False, priority=1, block=False, *, module=None, default_state=None, expire_time=None)` + + +* **说明** + + 在组中创建一个新的事件响应器,参数留空则使用组合默认值 + + +:::danger 警告 +如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数 +::: diff --git a/docs/api/nonebot.md b/docs/api/nonebot.md index 3c278a5c3c2f..7c89c8828c42 100644 --- a/docs/api/nonebot.md +++ b/docs/api/nonebot.md @@ -5,6 +5,55 @@ sidebarDepth: 0 # NoneBot 模块 +## 快捷导入 + +为方便使用,`nonebot` 模块从子模块导入了部分内容 + + +* `on_message` => `nonebot.plugin.on_message` + + +* `on_notice` => `nonebot.plugin.on_notice` + + +* `on_request` => `nonebot.plugin.on_request` + + +* `on_metaevent` => `nonebot.plugin.on_metaevent` + + +* `on_startswith` => `nonebot.plugin.on_startswith` + + +* `on_endswith` => `nonebot.plugin.on_endswith` + + +* `on_command` => `nonebot.plugin.on_command` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `on_regex` => `nonebot.plugin.on_regex` + + +* `CommandGroup` => `nonebot.plugin.CommandGroup` + + +* `load_plugin` => `nonebot.plugin.load_plugin` + + +* `load_plugins` => `nonebot.plugin.load_plugins` + + +* `load_builtin_plugins` => `nonebot.plugin.load_builtin_plugins` + + +* `get_loaded_plugins` => `nonebot.plugin.get_loaded_plugins` + ## `get_driver()` diff --git a/docs/api/rule.md b/docs/api/rule.md index 269abc570030..2054d04b5643 100644 --- a/docs/api/rule.md +++ b/docs/api/rule.md @@ -7,10 +7,10 @@ sidebarDepth: 0 ## 规则 -每个 `Matcher` 拥有一个 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 +每个事件响应器 `Matcher` 拥有一个匹配规则 `Rule` ,其中是 **异步** `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查结果为 `True` 时继续运行。 :::tip 提示 -`RuleChecker` 既可以是 async function 也可以是 sync function +`RuleChecker` 既可以是 async function 也可以是 sync function,但在最终会被 `nonebot.utils.run_sync` 转换为 async function ::: @@ -120,3 +120,83 @@ Rule(async_function, run_sync(sync_function)) * `msg: str`: 消息结尾字符串 + + + +## `keyword(msg)` + + +* **说明** + + 匹配消息关键词 + + + +* **参数** + + + * `msg: str`: 关键词 + + + +## `command(command)` + + +* **说明** + + 命令形式匹配,根据配置里提供的 `command_start`, `command_sep` 判断消息是否为命令。 + + + +* **参数** + + + * `command: Tuples[str, ...]`: 命令内容 + + + +* **示例** + + 使用默认 `command_start`, `command_sep` 配置 + + 命令 `("test",)` 可以匹配:`/test` 开头的消息 + 命令 `("test", "sub")` 可以匹配”`/test.sub` 开头的消息 + + +:::tip 提示 +命令内容与后续消息间无需空格! +::: + + +## `regex(regex, flags=0)` + + +* **说明** + + 根据正则表达式进行匹配 + + + +* **参数** + + + * `regex: str`: 正则表达式 + + + * `flags: Union[int, re.RegexFlag]`: 正则标志 + + + +## `to_me()` + + +* **说明** + + 通过 `event.to_me` 判断消息是否是发送给机器人 + + + +* **参数** + + + * 无 diff --git a/docs/guide/README.md b/docs/guide/README.md index 6cf31e908a35..86397ee27a09 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -20,11 +20,7 @@ NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人 ## 它如何工作? -NoneBot 的运行离不开 酷 Q 和 CQHTTP 插件。酷 Q 扮演着「无头 QQ 客户端」的角色,它进行实际的消息、通知、请求的接收和发送,当 酷 Q 收到消息时,它将这个消息包装为一个事件(通知和请求同理),并通过它自己的插件机制将事件传送给 CQHTTP 插件,后者再根据其配置中的 `post_url` 或 `ws_reverse_url` 等项来将事件发送至 NoneBot。 - -在 NoneBot 收到事件前,它底层的 aiocqhttp 实际已经先看到了事件,aiocqhttp 根据事件的类型信息,通知到 NoneBot 的相应函数。特别地,对于消息类型的事件,还将消息内容转换成了 `aiocqhttp.message.Message` 类型,以便处理。 - -NoneBot 的事件处理函数收到通知后,对于不同类型的事件,再做相应的预处理和解析,然后调用对应的插件,并向其提供适合此类事件的会话(Session)对象。NoneBot 插件的编写者要做的,就是利用 Session 对象中提供的数据,在插件的处理函数中实现所需的功能。 +~~未填坑~~ ## 特色 diff --git a/docs_build/README.rst b/docs_build/README.rst index 97f45a20f92f..20439caa0e0b 100644 --- a/docs_build/README.rst +++ b/docs_build/README.rst @@ -3,12 +3,16 @@ NoneBot Api Reference :模块索引: - `nonebot `_ - - `nonebot.typing `_ - `nonebot.config `_ - - `nonebot.sched `_ - - `nonebot.log `_ + - `nonebot.matcher `_ - `nonebot.rule `_ - `nonebot.permission `_ + - `nonebot.sched `_ + - `nonebot.log `_ - `nonebot.utils `_ + - `nonebot.typing `_ - `nonebot.exception `_ + - `nonebot.drivers `_ + - `nonebot.drivers.fastapi `_ + - `nonebot.adapters `_ - `nonebot.adapters.cqhttp `_ diff --git a/docs_build/adapters/README.rst b/docs_build/adapters/README.rst index 25dbf4e975da..e6e0d24ed7ea 100644 --- a/docs_build/adapters/README.rst +++ b/docs_build/adapters/README.rst @@ -4,9 +4,10 @@ sidebarDepth: 0 --- NoneBot.adapters 模块 -================= +===================== .. automodule:: nonebot.adapters :members: :private-members: + :special-members: __init__ :show-inheritance: diff --git a/docs_build/adapters/cqhttp.rst b/docs_build/adapters/cqhttp.rst index ddf781053187..3e63952ba4fe 100644 --- a/docs_build/adapters/cqhttp.rst +++ b/docs_build/adapters/cqhttp.rst @@ -4,7 +4,7 @@ sidebarDepth: 0 --- NoneBot.adapters.cqhttp 模块 -================= +============================ .. automodule:: nonebot.adapters.cqhttp :members: diff --git a/docs_build/drivers/README.rst b/docs_build/drivers/README.rst new file mode 100644 index 000000000000..e4bf61046b37 --- /dev/null +++ b/docs_build/drivers/README.rst @@ -0,0 +1,13 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +NoneBot.drivers 模块 +===================== + +.. automodule:: nonebot.drivers + :members: + :private-members: + :special-members: __init__ + :show-inheritance: diff --git a/docs_build/drivers/fastapi.rst b/docs_build/drivers/fastapi.rst new file mode 100644 index 000000000000..bbc67caf7bd7 --- /dev/null +++ b/docs_build/drivers/fastapi.rst @@ -0,0 +1,13 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +NoneBot.drivers.fastapi 模块 +===================== + +.. automodule:: nonebot.drivers.fastapi + :members: + :private-members: + :special-members: __init__ + :show-inheritance: diff --git a/docs_build/matcher.rst b/docs_build/matcher.rst new file mode 100644 index 000000000000..edc42bfe41da --- /dev/null +++ b/docs_build/matcher.rst @@ -0,0 +1,13 @@ +--- +contentSidebar: true +sidebarDepth: 0 +--- + +NoneBot.matcher 模块 +==================== + +.. automodule:: nonebot.matcher + :members: + :private-members: + :special-members: __init__ + :show-inheritance: diff --git a/docs_build/permission.rst b/docs_build/permission.rst index 15144a62e538..783a65f5d675 100644 --- a/docs_build/permission.rst +++ b/docs_build/permission.rst @@ -4,7 +4,7 @@ sidebarDepth: 0 --- NoneBot.permission 模块 -==================== +======================= .. automodule:: nonebot.permission :members: diff --git a/nonebot/__init__.py b/nonebot/__init__.py index 213b63d242c8..cbf1411500ee 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -1,5 +1,27 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +快捷导入 +======== + +为方便使用,``nonebot`` 模块从子模块导入了部分内容 + +- ``on_message`` => ``nonebot.plugin.on_message`` +- ``on_notice`` => ``nonebot.plugin.on_notice`` +- ``on_request`` => ``nonebot.plugin.on_request`` +- ``on_metaevent`` => ``nonebot.plugin.on_metaevent`` +- ``on_startswith`` => ``nonebot.plugin.on_startswith`` +- ``on_endswith`` => ``nonebot.plugin.on_endswith`` +- ``on_command`` => ``nonebot.plugin.on_command`` +- ``on_regex`` => ``nonebot.plugin.on_regex`` +- ``on_regex`` => ``nonebot.plugin.on_regex`` +- ``on_regex`` => ``nonebot.plugin.on_regex`` +- ``CommandGroup`` => ``nonebot.plugin.CommandGroup`` +- ``load_plugin`` => ``nonebot.plugin.load_plugin`` +- ``load_plugins`` => ``nonebot.plugin.load_plugins`` +- ``load_builtin_plugins`` => ``nonebot.plugin.load_builtin_plugins`` +- ``get_loaded_plugins`` => ``nonebot.plugin.get_loaded_plugins`` +""" import importlib from nonebot.typing import Bot, Dict, Type, Union, Driver, Optional, NoReturn diff --git a/nonebot/adapters/__init__.py b/nonebot/adapters/__init__.py index fb1fdbeca863..ba9b712b0d6b 100644 --- a/nonebot/adapters/__init__.py +++ b/nonebot/adapters/__init__.py @@ -1,5 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +协议适配基类 +============ + +各协议请继承以下基类,并使用 ``driver.register_adapter`` 注册适配器 +""" import abc from functools import reduce, partial @@ -11,6 +17,9 @@ class BaseBot(abc.ABC): + """ + Bot 基类。用于处理上报消息,并提供 API 调用接口。 + """ @abc.abstractmethod def __init__(self, @@ -19,12 +28,25 @@ def __init__(self, config: Config, self_id: str, *, - websocket: WebSocket = None): + websocket: Optional[WebSocket] = None): + """ + :参数: + * ``driver: Driver``: Driver 对象 + * ``connection_type: str``: http 或者 websocket + * ``config: Config``: Config 对象 + * ``self_id: str``: 机器人 ID + * ``websocket: Optional[WebSocket]``: Websocket 连接对象 + """ self.driver = driver + """Driver 对象""" self.connection_type = connection_type + """连接类型""" self.config = config + """Config 配置对象""" self.self_id = self_id + """机器人 ID""" self.websocket = websocket + """Websocket 连接对象""" def __getattr__(self, name: str) -> Callable[..., Awaitable[Any]]: return partial(self.call_api, name) @@ -32,60 +54,99 @@ def __getattr__(self, name: str) -> Callable[..., Awaitable[Any]]: @property @abc.abstractmethod def type(self) -> str: + """Adapter 类型""" raise NotImplementedError @abc.abstractmethod async def handle_message(self, message: dict): + """ + :说明: + 处理上报消息的函数,转换为 ``Event`` 事件后调用 ``nonebot.message.handle_event`` 进一步处理事件。 + :参数: + * ``message: dict``: 收到的上报消息 + """ raise NotImplementedError @abc.abstractmethod - async def call_api(self, api: str, data: dict): + async def call_api(self, api: str, **data): + """ + :说明: + 调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用 + :参数: + * ``api: str``: API 名称 + * ``**data``: API 数据 + :示例: + + .. code-block:: python + + await bot.call_api("send_msg", data={"message": "hello world"}) + await bot.send_msg(message="hello world") + """ raise NotImplementedError @abc.abstractmethod - async def send(self, *args, **kwargs): + async def send(self, event: "BaseEvent", + message: Union[str, "BaseMessage", + "BaseMessageSegment"], **kwargs): + """ + :说明: + 调用机器人基础发送消息接口 + :参数: + * ``event: Event``: 上报事件 + * ``message: Union[str, Message, MessageSegment]``: 要发送的消息 + * ``**kwargs`` + """ raise NotImplementedError -# TODO: improve event class BaseEvent(abc.ABC): + """ + Event 基类。提供上报信息的关键信息,其余信息可从原始上报消息获取。 + """ def __init__(self, raw_event: dict): - self._raw_event = raw_event """ - 原始 event + :参数: + * ``raw_event: dict``: 原始上报消息 """ + self._raw_event = raw_event def __repr__(self) -> str: return f"" @property def raw_event(self) -> dict: + """原始上报消息""" return self._raw_event @property @abc.abstractmethod def id(self) -> int: + """事件 ID""" raise NotImplementedError @property @abc.abstractmethod def name(self) -> str: + """事件名称""" raise NotImplementedError @property @abc.abstractmethod def self_id(self) -> str: + """机器人 ID""" raise NotImplementedError @property @abc.abstractmethod def time(self) -> int: + """事件发生时间""" raise NotImplementedError @property @abc.abstractmethod def type(self) -> str: + """事件主类型""" raise NotImplementedError @type.setter @@ -96,6 +157,7 @@ def type(self, value) -> None: @property @abc.abstractmethod def detail_type(self) -> str: + """事件详细类型""" raise NotImplementedError @detail_type.setter @@ -106,6 +168,7 @@ def detail_type(self, value) -> None: @property @abc.abstractmethod def sub_type(self) -> Optional[str]: + """事件子类型""" raise NotImplementedError @sub_type.setter @@ -116,6 +179,7 @@ def sub_type(self, value) -> None: @property @abc.abstractmethod def user_id(self) -> Optional[int]: + """触发事件的主体 ID""" raise NotImplementedError @user_id.setter @@ -126,6 +190,7 @@ def user_id(self, value) -> None: @property @abc.abstractmethod def group_id(self) -> Optional[int]: + """触发事件的主体群 ID""" raise NotImplementedError @group_id.setter @@ -136,6 +201,7 @@ def group_id(self, value) -> None: @property @abc.abstractmethod def to_me(self) -> Optional[bool]: + """事件是否为发送给机器人的消息""" raise NotImplementedError @to_me.setter @@ -146,6 +212,7 @@ def to_me(self, value) -> None: @property @abc.abstractmethod def message(self) -> Optional[Message]: + """消息内容""" raise NotImplementedError @message.setter @@ -156,6 +223,7 @@ def message(self, value) -> None: @property @abc.abstractmethod def reply(self) -> Optional[dict]: + """回复的消息""" raise NotImplementedError @reply.setter @@ -166,6 +234,7 @@ def reply(self, value) -> None: @property @abc.abstractmethod def raw_message(self) -> Optional[str]: + """原始消息""" raise NotImplementedError @raw_message.setter @@ -176,11 +245,13 @@ def raw_message(self, value) -> None: @property @abc.abstractmethod def plain_text(self) -> Optional[str]: + """纯文本消息""" raise NotImplementedError @property @abc.abstractmethod def sender(self) -> Optional[dict]: + """消息发送者信息""" raise NotImplementedError @sender.setter @@ -191,8 +262,17 @@ def sender(self, value) -> None: @dataclass class BaseMessageSegment(abc.ABC): + """消息段基类""" type: str - data: Dict[str, Union[str, list]] = field(default_factory=lambda: {}) + """ + - 类型: ``str`` + - 说明: 消息段类型 + """ + data: Dict[str, Any] = field(default_factory=lambda: {}) + """ + - 类型: ``Dict[str, Union[str, list]]`` + - 说明: 消息段数据 + """ @abc.abstractmethod def __str__(self): @@ -202,14 +282,30 @@ def __str__(self): def __add__(self, other): raise NotImplementedError + def __getitem__(self, key): + return getattr(self, key) + + def __setitem__(self, key, value): + return setattr(self, key, value) + + @classmethod + @abc.abstractmethod + def text(cls, text: str) -> "BaseMessageSegment": + return cls("text", {"text": text}) + class BaseMessage(list, abc.ABC): + """消息数组""" def __init__(self, message: Union[str, dict, list, BaseMessageSegment, "BaseMessage"] = None, *args, **kwargs): + """ + :参数: + * ``message: Union[str, dict, list, MessageSegment, Message]``: 消息内容 + """ super().__init__(*args, **kwargs) if isinstance(message, (str, dict, list)): self.extend(self._construct(message)) @@ -243,6 +339,12 @@ def __radd__(self, other: Union[str, BaseMessageSegment, "BaseMessage"]): return result.__add__(self) def append(self, obj: Union[str, BaseMessageSegment]) -> "BaseMessage": + """ + :说明: + 添加一个消息段到消息数组末尾 + :参数: + * ``obj: Union[str, MessageSegment]``: 要添加的消息段 + """ if isinstance(obj, BaseMessageSegment): if obj.type == "text" and self and self[-1].type == "text": self[-1].data["text"] += obj.data["text"] @@ -257,11 +359,21 @@ def append(self, obj: Union[str, BaseMessageSegment]) -> "BaseMessage": def extend( self, obj: Union["BaseMessage", Iterable[BaseMessageSegment]]) -> "BaseMessage": + """ + :说明: + 拼接一个消息数组或多个消息段到消息数组末尾 + :参数: + * ``obj: Union[Message, Iterable[MessageSegment]]``: 要添加的消息数组 + """ for segment in obj: self.append(segment) return self def reduce(self) -> None: + """ + :说明: + 缩减消息数组,即拼接相邻纯文本消息段 + """ index = 0 while index < len(self): if index > 0 and self[ @@ -272,8 +384,13 @@ def reduce(self) -> None: index += 1 def extract_plain_text(self) -> str: + """ + :说明: + 提取消息内纯文本消息 + """ def _concat(x: str, y: BaseMessageSegment) -> str: return f"{x} {y.data['text']}" if y.type == "text" else x - return reduce(_concat, self, "") + plain_text = reduce(_concat, self, "") + return plain_text[1:] if plain_text else plain_text diff --git a/nonebot/adapters/cqhttp.py b/nonebot/adapters/cqhttp.py index 96777759171e..33aee948a51d 100644 --- a/nonebot/adapters/cqhttp.py +++ b/nonebot/adapters/cqhttp.py @@ -182,13 +182,13 @@ def _check_nickname(bot: "Bot", event: "Event"): first_text = first_msg_seg.data["text"] - if bot.config.NICKNAME: + if bot.config.nickname: # check if the user is calling me with my nickname - if isinstance(bot.config.NICKNAME, str) or \ - not isinstance(bot.config.NICKNAME, Iterable): - nicknames = (bot.config.NICKNAME,) + if isinstance(bot.config.nickname, str) or \ + not isinstance(bot.config.nickname, Iterable): + nicknames = (bot.config.nickname,) else: - nicknames = filter(lambda n: n, bot.config.NICKNAME) + nicknames = filter(lambda n: n, bot.config.nickname) nickname_regex = "|".join(nicknames) m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text, re.IGNORECASE) @@ -265,7 +265,7 @@ def __init__(self, config: Config, self_id: str, *, - websocket: WebSocket = None): + websocket: Optional[WebSocket] = None): if connection_type not in ["http", "websocket"]: raise ValueError("Unsupported connection type") @@ -521,7 +521,7 @@ def sub_type(self) -> Optional[str]: """ return self._raw_event.get("sub_type") - @type.setter + @sub_type.setter @overrides(BaseEvent) def sub_type(self, value) -> None: self._raw_event["sub_type"] = value @@ -637,9 +637,9 @@ def sender(self, value) -> None: class MessageSegment(BaseMessageSegment): @overrides(BaseMessageSegment) - def __init__(self, type: str, data: Dict[str, Union[str, list]]) -> None: + def __init__(self, type: str, data: Dict[str, Any]) -> None: if type == "text": - data["text"] = unescape(data["text"]) # type: ignore + data["text"] = unescape(data["text"]) super().__init__(type=type, data=data) @overrides(BaseMessageSegment) diff --git a/nonebot/adapters/cqhttp.pyi b/nonebot/adapters/cqhttp.pyi index 08cdb2cdf74c..25e8a7a3afee 100644 --- a/nonebot/adapters/cqhttp.pyi +++ b/nonebot/adapters/cqhttp.pyi @@ -791,7 +791,7 @@ class Event: def sub_type(self) -> Optional[str]: ... - @type.setter + @sub_type.setter def sub_type(self, value) -> None: ... @@ -858,7 +858,7 @@ class Event: class MessageSegment: - def __init__(self, type: str, data: Dict[str, Union[str, list]]) -> None: + def __init__(self, type: str, data: Dict[str, Any]) -> None: ... def __str__(self): diff --git a/nonebot/config.py b/nonebot/config.py index 1680f40cadd3..70b8e3cb563c 100644 --- a/nonebot/config.py +++ b/nonebot/config.py @@ -211,10 +211,10 @@ class Config(BaseConfig): SUPER_USERS=[12345789] """ - nickname: Union[str, Set[str]] = "" + nickname: Set[str] = set() """ - - 类型: ``Union[str, Set[str]]`` - - 默认值: ``""`` + - 类型: ``Set[str]`` + - 默认值: ``set()`` - 说明: 机器人昵称。 """ diff --git a/nonebot/drivers/__init__.py b/nonebot/drivers/__init__.py index af8587d189a5..396622ed1dbf 100644 --- a/nonebot/drivers/__init__.py +++ b/nonebot/drivers/__init__.py @@ -1,5 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +后端驱动适配基类 +=============== + +各驱动请继承以下基类 +""" import abc @@ -9,7 +15,15 @@ class BaseDriver(abc.ABC): + """ + Driver 基类。将后端框架封装,以满足适配器使用。 + """ + _adapters: Dict[str, Type[Bot]] = {} + """ + :类型: ``Dict[str, Type[Bot]]`` + :说明: 已注册的适配器列表 + """ @abc.abstractmethod def __init__(self, env: Env, config: Config): diff --git a/nonebot/matcher.py b/nonebot/matcher.py index 76465b0b7768..9f0d7a9d7f7a 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -1,5 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +""" +事件响应器 +========== + +该模块实现事件响应器的创建与运行,并提供一些快捷方法来帮助用户更好的与机器人进行 对话 。 +""" from nonebot.log import logger import typing @@ -16,6 +22,10 @@ from nonebot.exception import PausedException, RejectedException, FinishedException matchers: Dict[int, List[Type["Matcher"]]] = defaultdict(list) +""" +:类型: ``Dict[int, List[Type[Matcher]]]`` +:说明: 用于存储当前所有的事件响应器 +""" current_bot: ContextVar = ContextVar("current_bot") current_event: ContextVar = ContextVar("current_event") @@ -32,22 +42,65 @@ def __str__(self) -> str: class Matcher(metaclass=MatcherMeta): - """`Matcher`类 - """ + """事件响应器类""" module: Optional[str] = None + """ + :类型: ``Optional[str]`` + :说明: 事件响应器所在模块名称 + """ type: str = "" + """ + :类型: ``str`` + :说明: 事件响应器类型 + """ rule: Rule = Rule() + """ + :类型: ``Rule`` + :说明: 事件响应器匹配规则 + """ permission: Permission = Permission() + """ + :类型: ``Permission`` + :说明: 事件响应器触发权限 + """ handlers: List[Handler] = [] - temp: bool = False - expire_time: Optional[datetime] = None + """ + :类型: ``List[Handler]`` + :说明: 事件响应器拥有的事件处理函数列表 + """ priority: int = 1 + """ + :类型: ``int`` + :说明: 事件响应器优先级 + """ block: bool = False + """ + :类型: ``bool`` + :说明: 事件响应器是否阻止事件传播 + """ + temp: bool = False + """ + :类型: ``bool`` + :说明: 事件响应器是否为临时 + """ + expire_time: Optional[datetime] = None + """ + :类型: ``Optional[datetime]`` + :说明: 事件响应器过期时间点 + """ _default_state: dict = {} + """ + :类型: ``dict`` + :说明: 事件响应器默认状态 + """ _default_parser: Optional[ArgsParser] = None + """ + :类型: ``Optional[ArgsParser]`` + :说明: 事件响应器默认参数解析函数 + """ def __init__(self): """实例化 Matcher 以便运行 @@ -65,9 +118,9 @@ def __str__(self) -> str: @classmethod def new(cls, type_: str = "", - rule: Rule = Rule(), - permission: Permission = Permission(), - handlers: Optional[list] = None, + rule: Optional[Rule] = None, + permission: Optional[Permission] = None, + handlers: Optional[List[Handler]] = None, temp: bool = False, priority: int = 1, block: bool = False, @@ -75,18 +128,30 @@ def new(cls, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None) -> Type["Matcher"]: - """创建新的 Matcher - - Returns: - Type["Matcher"]: 新的 Matcher 类 + """ + :说明: + 创建一个新的事件响应器,并存储至 `matchers <#matchers>`_ + :参数: + * ``type_: str``: 事件响应器类型,与 ``event.type`` 一致时触发,空字符串表示任意 + * ``rule: Optional[Rule]``: 匹配规则 + * ``permission: Optional[Permission]``: 权限 + * ``handlers: Optional[List[Handler]]``: 事件处理函数列表 + * ``temp: bool``: 是否为临时事件响应器,即触发一次后删除 + * ``priority: int``: 响应优先级 + * ``block: bool``: 是否阻止事件向更低优先级的响应器传播 + * ``module: Optional[str]``: 事件响应器所在模块名称 + * ``default_state: Optional[dict]``: 默认状态 ``state`` + * ``expire_time: Optional[datetime]``: 事件响应器最终有效时间点,过时即被删除 + :返回: + - ``Type[Matcher]``: 新的事件响应器类 """ NewMatcher = type( "Matcher", (Matcher,), { "module": module, "type": type_, - "rule": rule, - "permission": permission, + "rule": rule or Rule(), + "permission": permission or Permission(), "handlers": handlers or [], "temp": temp, "expire_time": expire_time, @@ -101,29 +166,51 @@ def new(cls, @classmethod async def check_perm(cls, bot: Bot, event: Event) -> bool: + """ + :说明: + 检查是否满足触发权限 + :参数: + * ``bot: Bot``: Bot 对象 + * ``event: Event``: 上报事件 + :返回: + - ``bool``: 是否满足权限 + """ return await cls.permission(bot, event) @classmethod async def check_rule(cls, bot: Bot, event: Event, state: dict) -> bool: - """检查 Matcher 的 Rule 是否成立 - - Args: - event (Event): 消息事件 - - Returns: - bool: 条件成立与否 + """ + :说明: + 检查是否满足匹配规则 + :参数: + * ``bot: Bot``: Bot 对象 + * ``event: Event``: 上报事件 + * ``state: dict``: 当前状态 + :返回: + - ``bool``: 是否满足匹配规则 """ return (event.type == (cls.type or event.type) and await cls.rule(bot, event, state)) @classmethod def args_parser(cls, func: ArgsParser) -> ArgsParser: + """ + :说明: + 装饰一个函数来更改当前事件响应器的默认参数解析函数 + :参数: + * ``func: ArgsParser``: 参数解析函数 + """ cls._default_parser = func return func @classmethod def handle(cls) -> Callable[[Handler], Handler]: - """直接处理消息事件""" + """ + :说明: + 装饰一个函数来向事件响应器直接添加一个处理函数 + :参数: + * 无 + """ def _decorator(func: Handler) -> Handler: cls.handlers.append(func) @@ -133,7 +220,12 @@ def _decorator(func: Handler) -> Handler: @classmethod def receive(cls) -> Callable[[Handler], Handler]: - """接收一条新消息并处理""" + """ + :说明: + 装饰一个函数来指示 NoneBot 在接收用户新的一条消息后继续运行该函数 + :参数: + * 无 + """ async def _receive(bot: Bot, event: Event, state: dict) -> NoReturn: raise PausedException @@ -154,9 +246,17 @@ def _decorator(func: Handler) -> Handler: def got( cls, key: str, - prompt: Optional[str] = None, + prompt: Optional[Union[str, Message, MessageSegment]] = None, args_parser: Optional[ArgsParser] = None ) -> Callable[[Handler], Handler]: + """ + :说明: + 装饰一个函数来指示 NoneBot 当要获取的 ``key`` 不存在时接收用户新的一条消息并经过 ``ArgsParser`` 处理后再运行该函数,如果 ``key`` 已存在则直接继续运行 + :参数: + * ``key: str``: 参数名 + * ``prompt: Optional[Union[str, Message, MessageSegment]]``: 在参数不存在时向用户发送的消息 + * ``args_parser: Optional[ArgsParser]``: 可选参数解析函数,空则使用默认解析函数 + """ async def _key_getter(bot: Bot, event: Event, state: dict): state["_current_key"] = key @@ -197,15 +297,33 @@ async def wrapper(bot: Bot, event: Event, state: dict): return _decorator + @classmethod + async def send(cls, message: Union[str, Message, MessageSegment]): + """ + :说明: + 发送一条消息给当前交互用户 + :参数: + * ``message: Union[str, Message, MessageSegment]``: 消息内容 + """ + bot = current_bot.get() + event = current_event.get() + await bot.send(event=event, message=message) + @classmethod async def finish( cls, - prompt: Optional[Union[str, Message, - MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() - if prompt: - await bot.send(event=event, message=prompt) + message: Optional[Union[str, Message, + MessageSegment]] = None) -> NoReturn: + """ + :说明: + 发送一条消息给当前交互用户并结束当前事件响应器 + :参数: + * ``message: Union[str, Message, MessageSegment]``: 消息内容 + """ + bot = current_bot.get() + event = current_event.get() + if message: + await bot.send(event=event, message=message) raise FinishedException @classmethod @@ -213,8 +331,14 @@ async def pause( cls, prompt: Optional[Union[str, Message, MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() + """ + :说明: + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后继续下一个处理函数 + :参数: + * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + """ + bot = current_bot.get() + event = current_event.get() if prompt: await bot.send(event=event, message=prompt) raise PausedException @@ -224,8 +348,14 @@ async def reject( cls, prompt: Optional[Union[str, Message, MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() + """ + :说明: + 发送一条消息给当前交互用户并暂停事件响应器,在接收用户新的一条消息后重新运行当前处理函数 + :参数: + * ``prompt: Union[str, Message, MessageSegment]``: 消息内容 + """ + bot = current_bot.get() + event = current_event.get() if prompt: await bot.send(event=event, message=prompt) raise RejectedException @@ -281,11 +411,12 @@ async def run(self, bot: Bot, event: Event, state: dict): class MatcherGroup: + """事件响应器组合,统一管理。用法同 ``Matcher``""" def __init__(self, type_: str = "", - rule: Rule = Rule(), - permission: Permission = Permission(), + rule: Optional[Rule] = None, + permission: Optional[Permission] = None, handlers: Optional[list] = None, temp: bool = False, priority: int = 1, @@ -294,19 +425,30 @@ def __init__(self, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None): + """ + :说明: + 创建一个事件响应器组合,参数为默认值,与 ``Matcher.new`` 一致 + """ self.matchers: List[Type[Matcher]] = [] + """ + :类型: ``List[Type[Matcher]]`` + :说明: 组内事件响应器列表 + """ self.type = type_ - self.rule = rule - self.permission = permission + self.rule = rule or Rule() + self.permission = permission or Permission() self.handlers = handlers self.temp = temp self.priority = priority self.block = block self.module = module - self.default_state = default_state self.expire_time = expire_time + self._default_state = default_state + + self._default_parser: Optional[ArgsParser] = None + def __repr__(self) -> str: return ( f" str: def new(self, type_: str = "", - rule: Rule = Rule(), - permission: Permission = Permission(), + rule: Optional[Rule] = None, + permission: Optional[Permission] = None, handlers: Optional[list] = None, temp: bool = False, priority: int = 1, @@ -327,6 +469,14 @@ def new(self, module: Optional[str] = None, default_state: Optional[dict] = None, expire_time: Optional[datetime] = None) -> Type[Matcher]: + """ + :说明: + 在组中创建一个新的事件响应器,参数留空则使用组合默认值 + + \:\:\:danger 警告 + 如果使用 handlers 参数覆盖组合默认值则该事件响应器不会随组合一起添加新的事件处理函数 + \:\:\: + """ matcher = Matcher.new(type_=type_ or self.type, rule=self.rule & rule, permission=permission or self.permission, @@ -335,7 +485,8 @@ def new(self, priority=priority or self.priority, block=block or self.block, module=module or self.module, - default_state=default_state or self.default_state, + default_state=default_state or + self._default_state, expire_time=expire_time or self.expire_time) self.matchers.append(matcher) return matcher @@ -346,7 +497,6 @@ def args_parser(self, func: ArgsParser) -> ArgsParser: return func def handle(self) -> Callable[[Handler], Handler]: - """直接处理消息事件""" def _decorator(func: Handler) -> Handler: self.handlers.append(func) @@ -355,7 +505,6 @@ def _decorator(func: Handler) -> Handler: return _decorator def receive(self) -> Callable[[Handler], Handler]: - """接收一条新消息并处理""" async def _receive(bot: Bot, event: Event, state: dict) -> NoReturn: raise PausedException @@ -418,22 +567,27 @@ async def wrapper(bot: Bot, event: Event, state: dict): return _decorator + async def send(self, message: Union[str, Message, MessageSegment]): + bot = current_bot.get() + event = current_event.get() + await bot.send(event=event, message=message) + async def finish( self, - prompt: Optional[Union[str, Message, - MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() - if prompt: - await bot.send(event=event, message=prompt) + message: Optional[Union[str, Message, + MessageSegment]] = None) -> NoReturn: + bot = current_bot.get() + event = current_event.get() + if message: + await bot.send(event=event, message=message) raise FinishedException async def pause( self, prompt: Optional[Union[str, Message, MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() + bot = current_bot.get() + event = current_event.get() if prompt: await bot.send(event=event, message=prompt) raise PausedException @@ -442,8 +596,8 @@ async def reject( self, prompt: Optional[Union[str, Message, MessageSegment]] = None) -> NoReturn: - bot: Bot = current_bot.get() - event: Event = current_event.get() + bot = current_bot.get() + event = current_event.get() if prompt: await bot.send(event=event, message=prompt) raise RejectedException diff --git a/nonebot/message.py b/nonebot/message.py index f3a69e3af89f..9374d46ac646 100644 --- a/nonebot/message.py +++ b/nonebot/message.py @@ -74,7 +74,7 @@ async def handle_event(bot: Bot, event: Event): elif event.type == "request": log_msg += f"Request {event.raw_event}" elif event.type == "meta_event": - log_msg += f"MetaEvent {event.raw_event}" + log_msg += f"MetaEvent {event.detail_type}" logger.opt(colors=True).info(log_msg) coros = [] diff --git a/nonebot/plugins/base.py b/nonebot/plugins/base.py index de743d14ea5c..075ddd203a24 100644 --- a/nonebot/plugins/base.py +++ b/nonebot/plugins/base.py @@ -1,10 +1,34 @@ +from functools import reduce + from nonebot.rule import to_me from nonebot.plugin import on_command -from nonebot.typing import Bot, Event +from nonebot.permission import SUPERUSER +from nonebot.typing import Bot, Event, MessageSegment -say = on_command("say", to_me()) +say = on_command("say", to_me(), permission=SUPERUSER) @say.handle() -async def repeat(bot: Bot, event: Event, state: dict): - await bot.send(message=event.message, event=event) +async def say_unescape(bot: Bot, event: Event, state: dict): + Message = event.message.__class__ + + def _unescape(message: Message, segment: MessageSegment): + if segment.type == "text": + return message.append(segment.data["text"]) + return message.append(segment) + + message = reduce(_unescape, event.message, Message()) # type: ignore + await bot.send(message=message, event=event) + + +echo = on_command("echo", to_me()) + + +@echo.handle() +async def echo_escape(bot: Bot, event: Event, state: dict): + Message = event.message.__class__ + MessageSegment = event.message[0].__class__ + + message = Message().append( # type: ignore + MessageSegment.text(str(event.message))) + await bot.send(message=message, event=event) diff --git a/nonebot/rule.py b/nonebot/rule.py index 7d57b33ef197..b12d4ae13554 100644 --- a/nonebot/rule.py +++ b/nonebot/rule.py @@ -4,10 +4,10 @@ 规则 ==== -每个 ``Matcher`` 拥有一个 ``Rule`` ,其中是 **异步** ``RuleChecker`` 的集合,只有当所有 ``RuleChecker`` 检查结果为 ``True`` 时继续运行。 +每个事件响应器 ``Matcher`` 拥有一个匹配规则 ``Rule`` ,其中是 **异步** ``RuleChecker`` 的集合,只有当所有 ``RuleChecker`` 检查结果为 ``True`` 时继续运行。 \:\:\:tip 提示 -``RuleChecker`` 既可以是 async function 也可以是 sync function +``RuleChecker`` 既可以是 async function 也可以是 sync function,但在最终会被 ``nonebot.utils.run_sync`` 转换为 async function \:\:\: """ @@ -185,6 +185,12 @@ async def _endswith(bot: Bot, event: Event, state: dict) -> bool: def keyword(msg: str) -> Rule: + """ + :说明: + 匹配消息关键词 + :参数: + * ``msg: str``: 关键词 + """ async def _keyword(bot: Bot, event: Event, state: dict) -> bool: return bool(event.plain_text and msg in event.plain_text) @@ -193,6 +199,22 @@ async def _keyword(bot: Bot, event: Event, state: dict) -> bool: def command(command: Tuple[str, ...]) -> Rule: + """ + :说明: + 命令形式匹配,根据配置里提供的 ``command_start``, ``command_sep`` 判断消息是否为命令。 + :参数: + * ``command: Tuples[str, ...]``: 命令内容 + :示例: + 使用默认 ``command_start``, ``command_sep`` 配置 + + 命令 ``("test",)`` 可以匹配:``/test`` 开头的消息 + 命令 ``("test", "sub")`` 可以匹配”``/test.sub`` 开头的消息 + + \:\:\:tip 提示 + 命令内容与后续消息间无需空格! + \:\:\: + """ + config = get_driver().config command_start = config.command_start command_sep = config.command_sep @@ -210,6 +232,14 @@ async def _command(bot: Bot, event: Event, state: dict) -> bool: def regex(regex: str, flags: Union[int, re.RegexFlag] = 0) -> Rule: + """ + :说明: + 根据正则表达式进行匹配 + :参数: + * ``regex: str``: 正则表达式 + * ``flags: Union[int, re.RegexFlag]``: 正则标志 + """ + pattern = re.compile(regex, flags) async def _regex(bot: Bot, event: Event, state: dict) -> bool: @@ -219,6 +249,12 @@ async def _regex(bot: Bot, event: Event, state: dict) -> bool: def to_me() -> Rule: + """ + :说明: + 通过 ``event.to_me`` 判断消息是否是发送给机器人 + :参数: + * 无 + """ async def _to_me(bot: Bot, event: Event, state: dict) -> bool: return bool(event.to_me) diff --git a/poetry.lock b/poetry.lock index f4d0c251ee79..e07cdc8f759e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,27 +1,39 @@ [[package]] -category = "dev" -description = "A configurable sidebar-enabled Sphinx theme" +name = "aiofiles" +version = "0.5.0" +description = "File support for asyncio." +category = "main" +optional = true +python-versions = "*" + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" + +[[package]] name = "alabaster" +version = "0.7.12" +description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" optional = false python-versions = "*" -version = "0.7.12" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "In-process task scheduler with Cron-like capabilities" name = "apscheduler" +version = "3.6.3" +description = "In-process task scheduler with Cron-like capabilities" +category = "main" optional = true python-versions = "*" -version = "3.6.3" [package.dependencies] pytz = "*" -setuptools = ">=0.7" six = ">=1.4.0" tzlocal = ">=1.2" @@ -39,68 +51,68 @@ twisted = ["twisted"] zookeeper = ["kazoo"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Better dates & times for Python" name = "arrow" +version = "0.17.0" +description = "Better dates & times for Python" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.16.0" [package.dependencies] python-dateutil = ">=2.7.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Classes Without Boilerplate" name = "attrs" +version = "20.2.0" +description = "Classes Without Boilerplate" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.2.0" [package.extras] -dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] -tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Internationalization utilities" name = "babel" +version = "2.8.0" +description = "Internationalization utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8.0" [package.dependencies] pytz = ">=2015.7" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Modern password hashing for your software and your servers" name = "bcrypt" +version = "3.2.0" +description = "Modern password hashing for your software and your servers" +category = "main" optional = true python-versions = ">=3.6" -version = "3.2.0" [package.dependencies] cffi = ">=1.1" @@ -111,138 +123,138 @@ tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)"] typecheck = ["mypy"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Ultra-lightweight pure Python package to check if a file is binary or text." name = "binaryornot" +version = "0.4.4" +description = "Ultra-lightweight pure Python package to check if a file is binary or text." +category = "main" optional = true python-versions = "*" -version = "0.4.4" [package.dependencies] chardet = ">=3.0.2" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A decorator for caching properties in classes." name = "cached-property" +version = "1.5.2" +description = "A decorator for caching properties in classes." +category = "main" optional = true python-versions = "*" -version = "1.5.2" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." name = "certifi" +version = "2020.6.20" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" -version = "2020.6.20" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Foreign Function Interface for Python calling C code." name = "cffi" +version = "1.14.3" +description = "Foreign Function Interface for Python calling C code." +category = "main" optional = true python-versions = "*" -version = "1.14.3" [package.dependencies] pycparser = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" name = "chardet" +version = "3.0.4" +description = "Universal encoding detector for Python 2 and 3" +category = "main" optional = false python-versions = "*" -version = "3.0.4" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Composable command line interface toolkit" name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.2" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Cross-platform colored terminal text." name = "colorama" +version = "0.4.3" +description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.3" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." name = "cookiecutter" +version = "1.7.2" +description = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.7.2" [package.dependencies] -Jinja2 = "<3.0.0" -MarkupSafe = "<2.0.0" binaryornot = ">=0.4.4" click = ">=7.0" +Jinja2 = "<3.0.0" jinja2-time = ">=0.2.0" +MarkupSafe = "<2.0.0" poyo = ">=0.5.0" python-slugify = ">=4.0.0" requests = ">=2.23.0" six = ">=1.10" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." name = "cryptography" +version = "3.1.1" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = true python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "3.1.1" [package.dependencies] cffi = ">=1.8,<1.11.3 || >1.11.3" @@ -256,133 +268,127 @@ ssh = ["bcrypt (>=3.1.5)"] test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Distro - an OS platform information API" name = "distro" +version = "1.5.0" +description = "Distro - an OS platform information API" +category = "main" optional = true python-versions = "*" -version = "1.5.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A Python library for the Docker Engine API." name = "docker" +version = "4.3.1" +description = "A Python library for the Docker Engine API." +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.3.1" [package.dependencies] -pywin32 = "227" +paramiko = {version = ">=2.4.2", optional = true, markers = "extra == \"ssh\""} +pywin32 = {version = "227", markers = "sys_platform == \"win32\""} requests = ">=2.14.2,<2.18.0 || >2.18.0" six = ">=1.4.0" websocket-client = ">=0.32.0" -[package.dependencies.paramiko] -optional = true -version = ">=2.4.2" - [package.extras] ssh = ["paramiko (>=2.4.2)"] tls = ["pyOpenSSL (>=17.5.0)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Multi-container orchestration for Docker" name = "docker-compose" +version = "1.27.4" +description = "Multi-container orchestration for Docker" +category = "main" optional = true python-versions = ">=3.4" -version = "1.27.4" [package.dependencies] -PyYAML = ">=3.10,<6" cached-property = ">=1.2.0,<2" -colorama = ">=0.4,<1" +colorama = {version = ">=0.4,<1", markers = "sys_platform == \"win32\""} distro = ">=1.5.0,<2" +docker = {version = ">=4.3.1,<5", extras = ["ssh"]} dockerpty = ">=0.4.1,<1" docopt = ">=0.6.1,<1" jsonschema = ">=2.5.1,<4" python-dotenv = ">=0.13.0,<1" +PyYAML = ">=3.10,<6" requests = ">=2.20.0,<3" texttable = ">=0.9.0,<2" websocket-client = ">=0.32.0,<1" -[package.dependencies.docker] -extras = ["ssh"] -version = ">=4.3.1,<5" - [package.extras] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2)"] tests = ["ddt (>=1.2.2,<2)", "pytest (<6)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python library to use the pseudo-tty of a docker container" name = "dockerpty" +version = "0.4.1" +description = "Python library to use the pseudo-tty of a docker container" +category = "main" optional = true python-versions = "*" -version = "0.4.1" [package.dependencies] six = ">=1.3.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Pythonic argument parser, that will make you smile" name = "docopt" +version = "0.6.2" +description = "Pythonic argument parser, that will make you smile" +category = "main" optional = true python-versions = "*" -version = "0.6.2" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Docutils -- Python Documentation Utilities" name = "docutils" +version = "0.16" +description = "Docutils -- Python Documentation Utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.16" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" name = "fastapi" +version = "0.58.1" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" optional = false python-versions = ">=3.6" -version = "0.58.1" [package.dependencies] pydantic = ">=0.32.2,<2.0.0" @@ -395,86 +401,86 @@ doc = ["mkdocs", "mkdocs-material", "markdown-include", "typer", "typer-cli", "p test = ["pytest (5.4.3)", "pytest-cov (2.10.0)", "mypy", "black", "isort", "requests", "email-validator", "sqlalchemy", "peewee", "databases", "orjson", "async-exit-stack", "async-generator", "python-multipart", "aiofiles", "flask"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" name = "h11" +version = "0.9.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" optional = false python-versions = "*" -version = "0.9.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "HTTP/2 State-Machine based protocol implementation" name = "h2" +version = "3.2.0" +description = "HTTP/2 State-Machine based protocol implementation" +category = "main" optional = false python-versions = "*" -version = "3.2.0" [package.dependencies] hpack = ">=3.0,<4" hyperframe = ">=5.2.0,<6" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Pure-Python HPACK header compression" name = "hpack" +version = "3.0.0" +description = "Pure-Python HPACK header compression" +category = "main" optional = false python-versions = "*" -version = "3.0.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Chromium HSTS Preload list as a Python package and updated daily" name = "hstspreload" +version = "2020.10.6" +description = "Chromium HSTS Preload list as a Python package and updated daily" +category = "main" optional = false python-versions = ">=3.6" -version = "2020.9.29" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Turn HTML into equivalent Markdown-structured text." name = "html2text" +version = "2020.1.16" +description = "Turn HTML into equivalent Markdown-structured text." +category = "dev" optional = false python-versions = ">=3.5" -version = "2020.1.16" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A minimal low-level HTTP client." name = "httpcore" +version = "0.9.1" +description = "A minimal low-level HTTP client." +category = "main" optional = false python-versions = ">=3.6" -version = "0.9.1" [package.dependencies] h11 = ">=0.8,<0.10" @@ -482,34 +488,33 @@ h2 = ">=3.0.0,<4.0.0" sniffio = ">=1.0.0,<2.0.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A collection of framework independent HTTP protocol utils." -marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" name = "httptools" +version = "0.1.1" +description = "A collection of framework independent HTTP protocol utils." +category = "main" optional = false python-versions = "*" -version = "0.1.1" [package.extras] test = ["Cython (0.29.14)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "The next generation HTTP client." name = "httpx" +version = "0.13.3" +description = "The next generation HTTP client." +category = "main" optional = false python-versions = ">=3.6" -version = "0.13.3" [package.dependencies] certifi = "*" @@ -521,57 +526,56 @@ rfc3986 = ">=1.3,<2" sniffio = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "HTTP/2 framing layer for Python" name = "hyperframe" +version = "5.2.0" +description = "HTTP/2 framing layer for Python" +category = "main" optional = false python-versions = "*" -version = "5.2.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" +version = "2.10" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.10" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Getting image size from png/jpeg/jpeg2000/gif file" name = "imagesize" +version = "1.2.0" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.2.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" name = "importlib-metadata" +version = "2.0.0" +description = "Read metadata from Python packages" +category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "2.0.0" [package.dependencies] zipp = ">=0.5" @@ -581,17 +585,17 @@ docs = ["sphinx", "rst.linker"] testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A very fast and expressive template engine." name = "jinja2" +version = "2.11.2" +description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -600,94 +604,90 @@ MarkupSafe = ">=0.23" i18n = ["Babel (>=0.8)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Jinja2 Extension for Dates and Times" name = "jinja2-time" +version = "0.2.0" +description = "Jinja2 Extension for Dates and Times" +category = "main" optional = true python-versions = "*" -version = "0.2.0" [package.dependencies] arrow = "*" jinja2 = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "An implementation of JSON Schema validation for Python" name = "jsonschema" +version = "3.2.0" +description = "An implementation of JSON Schema validation for Python" +category = "main" optional = true python-versions = "*" -version = "3.2.0" [package.dependencies] attrs = ">=17.4.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} pyrsistent = ">=0.14.0" -setuptools = "*" six = ">=1.11.0" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - [package.extras] format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python logging made (stupidly) simple" name = "loguru" +version = "0.5.3" +description = "Python logging made (stupidly) simple" +category = "main" optional = false python-versions = ">=3.5" -version = "0.5.3" [package.dependencies] -colorama = ">=0.3.4" -win32-setctime = ">=1.0.0" +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.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Safely add untrusted strings to HTML/XML markup." name = "markupsafe" +version = "1.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.1.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "CLI for nonebot2" name = "nb-cli" +version = "0.1.0" +description = "CLI for nonebot2" +category = "main" optional = true python-versions = ">=3.7,<4.0" -version = "0.1.0" [package.dependencies] click = ">=7.1.2,<8.0.0" @@ -699,34 +699,52 @@ pyfiglet = ">=0.8.post1,<0.9" pyinquirer = "1.0.3" [package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" reference = "aliyun" + +[[package]] +name = "nonebot-test" +version = "0.1.0" +description = "Test frontend for nonebot v2+" +category = "main" +optional = true +python-versions = ">=3.7,<4.0" + +[package.dependencies] +aiofiles = ">=0.5.0,<0.6.0" +nonebot2 = ">=2.0.0-alpha.1,<3.0.0" +python-socketio = ">=4.6.0,<5.0.0" + +[package.source] type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Core utilities for Python packages" name = "packaging" +version = "20.4" +description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "SSH2 protocol library" name = "paramiko" +version = "2.7.2" +description = "SSH2 protocol library" +category = "main" optional = true python-versions = "*" -version = "2.7.2" [package.dependencies] bcrypt = ">=3.1.3" @@ -740,65 +758,63 @@ gssapi = ["pyasn1 (>=0.1.7)", "gssapi (>=1.4.1)", "pywin32 (>=2.1.8)"] invoke = ["invoke (>=1.3)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A lightweight YAML Parser for Python. 🐓" name = "poyo" +version = "0.5.0" +description = "A lightweight YAML Parser for Python. 🐓" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.5.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Library for building powerful interactive command lines in Python" name = "prompt-toolkit" +version = "1.0.14" +description = "Library for building powerful interactive command lines in Python" +category = "main" optional = true python-versions = "*" -version = "1.0.14" [package.dependencies] six = ">=1.9.0" wcwidth = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "C parser in Python" name = "pycparser" +version = "2.20" +description = "C parser in Python" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.20" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Data validation and settings management using python 3.6 type hinting" name = "pydantic" +version = "1.6.1" +description = "Data validation and settings management using python 3.6 type hinting" +category = "main" optional = false python-versions = ">=3.6" -version = "1.6.1" [package.dependencies] -[package.dependencies.python-dotenv] -optional = true -version = ">=0.10.4" +python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} [package.extras] dotenv = ["python-dotenv (>=0.10.4)"] @@ -806,90 +822,90 @@ email = ["email-validator (>=1.0.3)"] typing_extensions = ["typing-extensions (>=3.7.2)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." name = "pydash" +version = "4.8.0" +description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." +category = "dev" optional = false python-versions = "*" -version = "4.8.0" [package.extras] dev = ["coverage", "flake8", "mock", "pylint", "pytest", "pytest-cov", "sphinx", "sphinx-rtd-theme", "tox", "twine", "wheel"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Pure-python FIGlet implementation" name = "pyfiglet" +version = "0.8.post1" +description = "Pure-python FIGlet implementation" +category = "main" optional = true python-versions = "*" -version = "0.8.post1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Pygments is a syntax highlighting package written in Python." name = "pygments" +version = "2.7.1" +description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.5" -version = "2.7.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Trie data structure implementation." name = "pygtrie" +version = "2.3.3" +description = "Trie data structure implementation." +category = "main" optional = false python-versions = "*" -version = "2.3.3" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A Python module for collection of common interactive command line user interfaces, based on Inquirer.js" name = "pyinquirer" +version = "1.0.3" +description = "A Python module for collection of common interactive command line user interfaces, based on Inquirer.js" +category = "main" optional = true python-versions = "*" -version = "1.0.3" [package.dependencies] -Pygments = ">=2.2.0" prompt_toolkit = "1.0.14" +Pygments = ">=2.2.0" regex = ">=2016.11.21" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python binding to the Networking and Cryptography (NaCl) library" name = "pynacl" +version = "1.4.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.4.0" [package.dependencies] cffi = ">=1.4.1" @@ -900,75 +916,95 @@ docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Python parsing module" name = "pyparsing" +version = "2.4.7" +description = "Python parsing module" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.7" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Persistent/Functional/Immutable data structures" name = "pyrsistent" +version = "0.17.3" +description = "Persistent/Functional/Immutable data structures" +category = "main" optional = true python-versions = ">=3.5" -version = "0.17.3" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Extensions to the standard Python datetime module" name = "python-dateutil" +version = "2.8.1" +description = "Extensions to the standard Python datetime module" +category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" [package.dependencies] six = ">=1.5" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Add .env support to your django/flask apps in development and deployments" name = "python-dotenv" +version = "0.14.0" +description = "Add .env support to your django/flask apps in development and deployments" +category = "main" optional = false python-versions = "*" -version = "0.14.0" [package.extras] cli = ["click (>=5.0)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] +name = "python-engineio" +version = "3.13.2" +description = "Engine.IO server" category = "main" -description = "A Python Slugify application that handles Unicode" +optional = true +python-versions = "*" + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +asyncio_client = ["aiohttp (>=3.4)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" + +[[package]] name = "python-slugify" +version = "4.0.1" +description = "A Python Slugify application that handles Unicode" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.0.1" [package.dependencies] text-unidecode = ">=1.3" @@ -977,70 +1013,90 @@ text-unidecode = ">=1.3" unidecode = ["Unidecode (>=1.1.1)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] +name = "python-socketio" +version = "4.6.0" +description = "Socket.IO server" category = "main" -description = "World timezone definitions, modern and historical" +optional = true +python-versions = "*" + +[package.dependencies] +python-engineio = ">=3.13.0" +six = ">=1.9.0" + +[package.extras] +asyncio_client = ["aiohttp (>=3.4)", "websockets (>=7.0)"] +client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"] + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" + +[[package]] name = "pytz" +version = "2020.1" +description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" -version = "2020.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python for Window Extensions" -marker = "sys_platform == \"win32\"" name = "pywin32" +version = "227" +description = "Python for Window Extensions" +category = "main" optional = true python-versions = "*" -version = "227" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "YAML parser and emitter for Python" name = "pyyaml" +version = "5.3.1" +description = "YAML parser and emitter for Python" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "5.3.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Alternative regular expression module, to replace re." name = "regex" +version = "2020.9.27" +description = "Alternative regular expression module, to replace re." +category = "main" optional = true python-versions = "*" -version = "2020.9.27" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python HTTP for Humans." name = "requests" +version = "2.24.0" +description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" @@ -1053,84 +1109,83 @@ security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Validating URI References per RFC 3986" name = "rfc3986" +version = "1.4.0" +description = "Validating URI References per RFC 3986" +category = "main" optional = false python-versions = "*" -version = "1.4.0" [package.extras] idna2008 = ["idna"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" name = "six" +version = "1.15.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.15.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Sniff out which async library your code is running under" name = "sniffio" +version = "1.1.0" +description = "Sniff out which async library your code is running under" +category = "main" optional = false python-versions = ">=3.5" -version = "1.1.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." name = "snowballstemmer" +version = "2.0.0" +description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +category = "dev" optional = false python-versions = "*" -version = "2.0.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Python documentation generator" name = "sphinx" +version = "3.2.1" +description = "Python documentation generator" +category = "dev" optional = false python-versions = ">=3.5" -version = "3.2.1" [package.dependencies] -Jinja2 = ">=2.3" -Pygments = ">=2.0" alabaster = ">=0.7,<0.8" babel = ">=1.3" -colorama = ">=0.3.5" +colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} docutils = ">=0.12" imagesize = "*" +Jinja2 = ">=2.3" packaging = "*" +Pygments = ">=2.0" requests = ">=2.5.0" -setuptools = "*" snowballstemmer = ">=1.1" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" @@ -1145,17 +1200,17 @@ lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.780)", "docutils-s test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "sphinx builder that outputs markdown files" name = "sphinx-markdown-builder" +version = "0.5.4" +description = "sphinx builder that outputs markdown files" +category = "dev" optional = false python-versions = "*" -version = "0.5.4" [package.dependencies] html2text = "*" @@ -1165,204 +1220,206 @@ unify = "*" yapf = "*" [package.source] -reference = "09751bd6c81ee246d91d63baa65d09e3618b7288" type = "git" url = "https://github.com/nonebot/sphinx-markdown-builder.git" +reference = "master" +resolved_reference = "09751bd6c81ee246d91d63baa65d09e3618b7288" + [[package]] -category = "dev" -description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" name = "sphinxcontrib-applehelp" +version = "1.0.2" +description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.2" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" name = "sphinxcontrib-htmlhelp" +version = "1.0.3" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest", "html5lib"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "A sphinx extension which renders display math in HTML via JavaScript" name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.1" [package.extras] test = ["pytest", "flake8", "mypy"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.0.3" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." name = "sphinxcontrib-serializinghtml" +version = "1.1.4" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" optional = false python-versions = ">=3.5" -version = "1.1.4" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "The little ASGI library that shines." name = "starlette" +version = "0.13.4" +description = "The little ASGI library that shines." +category = "main" optional = false python-versions = ">=3.6" -version = "0.13.4" [package.extras] full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "The most basic Text::Unidecode port" name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +category = "main" optional = true python-versions = "*" -version = "1.3" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "module for creating simple ASCII tables" name = "texttable" +version = "1.6.3" +description = "module for creating simple ASCII tables" +category = "main" optional = true python-versions = "*" -version = "1.6.3" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "tzinfo object for the local timezone" name = "tzlocal" +version = "2.1" +description = "tzinfo object for the local timezone" +category = "main" optional = true python-versions = "*" -version = "2.1" [package.dependencies] pytz = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Modifies strings to all use the same (single/double) quote where possible." name = "unify" +version = "0.5" +description = "Modifies strings to all use the same (single/double) quote where possible." +category = "dev" optional = false python-versions = "*" -version = "0.5" [package.dependencies] untokenize = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "Transforms tokens into original source code (while preserving whitespace)." name = "untokenize" +version = "0.1.1" +description = "Transforms tokens into original source code (while preserving whitespace)." +category = "dev" optional = false python-versions = "*" -version = "0.1.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" +version = "1.25.10" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.10" [package.extras] brotli = ["brotlipy (>=0.6.0)"] @@ -1370,148 +1427,150 @@ secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0 socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "The lightning-fast ASGI server." name = "uvicorn" +version = "0.11.8" +description = "The lightning-fast ASGI server." +category = "main" optional = false python-versions = "*" -version = "0.11.8" [package.dependencies] click = ">=7.0.0,<8.0.0" h11 = ">=0.8,<0.10" -httptools = ">=0.1.0,<0.2.0" -uvloop = ">=0.14.0" +httptools = {version = ">=0.1.0,<0.2.0", markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\""} +uvloop = {version = ">=0.14.0", markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\""} websockets = ">=8.0.0,<9.0.0" [package.extras] watchgodreload = ["watchgod (>=0.6,<0.7)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Fast implementation of asyncio event loop on top of libuv" -marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" name = "uvloop" +version = "0.14.0" +description = "Fast implementation of asyncio event loop on top of libuv" +category = "main" optional = false python-versions = "*" -version = "0.14.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Measures the displayed width of unicode strings in a terminal" name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "main" optional = true python-versions = "*" -version = "0.2.5" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "WebSocket client for Python. hybi13 is supported." name = "websocket-client" +version = "0.57.0" +description = "WebSocket client for Python. hybi13 is supported." +category = "main" optional = true python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.57.0" [package.dependencies] six = "*" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" name = "websockets" +version = "8.1" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +category = "main" optional = false python-versions = ">=3.6.1" -version = "8.1" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "A small Python utility to set file creation time on Windows" -marker = "sys_platform == \"win32\"" 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" -version = "1.0.2" [package.extras] dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "dev" -description = "A formatter for Python code." name = "yapf" +version = "0.30.0" +description = "A formatter for Python code." +category = "dev" optional = false python-versions = "*" -version = "0.30.0" [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [[package]] -category = "main" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" name = "zipp" +version = "3.3.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = true python-versions = ">=3.6" -version = "3.2.0" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,<3.7.3 || >3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [package.source] -reference = "aliyun" type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" +reference = "aliyun" [extras] cli = ["nb-cli"] -full = ["nb-cli"] +full = ["nb-cli", "nonebot-test"] scheduler = ["apscheduler"] +test = ["nonebot-test"] [metadata] -content-hash = "b8e6ee3b0726717b1cfa1978693f1c4c25cf6fe044784ef5661b9bee50c34d9a" -lock-version = "1.0" +lock-version = "1.1" python-versions = "^3.7" +content-hash = "04acfd9bf32ebb7173922b1d0c28500d1a80ff22307856d61b04668e808c19be" [metadata.files] +aiofiles = [ + {file = "aiofiles-0.5.0-py3-none-any.whl", hash = "sha256:377fdf7815cc611870c59cbd07b68b180841d2a2b79812d8c218be02448c2acb"}, + {file = "aiofiles-0.5.0.tar.gz", hash = "sha256:98e6bcfd1b50f97db4980e182ddd509b7cc35909e903a8fe50d8849e02d815af"}, +] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, @@ -1521,8 +1580,8 @@ apscheduler = [ {file = "APScheduler-3.6.3.tar.gz", hash = "sha256:3bb5229eed6fbbdafc13ce962712ae66e175aa214c69bed35a06bffcf0c5e244"}, ] arrow = [ - {file = "arrow-0.16.0-py2.py3-none-any.whl", hash = "sha256:98184d8dd3e5d30b96c2df4596526f7de679ccb467f358b82b0f686436f3a6b8"}, - {file = "arrow-0.16.0.tar.gz", hash = "sha256:92aac856ea5175c804f7ccb96aca4d714d936f1c867ba59d747a8096ec30e90a"}, + {file = "arrow-0.17.0-py2.py3-none-any.whl", hash = "sha256:e098abbd9af3665aea81bdd6c869e93af4feb078e98468dd351c383af187aac5"}, + {file = "arrow-0.17.0.tar.gz", hash = "sha256:ff08d10cda1d36c68657d6ad20d74fbea493d980f8b2d45344e00d6ed2bf6ed4"}, ] attrs = [ {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"}, @@ -1670,8 +1729,8 @@ hpack = [ {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, ] hstspreload = [ - {file = "hstspreload-2020.9.29-py3-none-any.whl", hash = "sha256:b6bdbe6e36d8acea5bb97b53ae50552293b6b0425785918da7b63e48f08af4a8"}, - {file = "hstspreload-2020.9.29.tar.gz", hash = "sha256:349c59cd2889a2cd94f49b3872a195164cc50754f1bef148b7d2d0d6c0efe0de"}, + {file = "hstspreload-2020.10.6-py3-none-any.whl", hash = "sha256:f413669d7b53a6d4cd5fc0fb313562bfba9fb5fba63bbb32a62a752ed72734bd"}, + {file = "hstspreload-2020.10.6.tar.gz", hash = "sha256:01a9b58e8f32f2ef4d1f9aacc7658ec13e23c57ce9f625ea18693ec2ed38dcfb"}, ] html2text = [ {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"}, @@ -1770,6 +1829,10 @@ nb-cli = [ {file = "nb-cli-0.1.0.tar.gz", hash = "sha256:5106212dd0bae270fc547a59f8c75e20951b9fbd87af263d647f8474677a2e26"}, {file = "nb_cli-0.1.0-py3-none-any.whl", hash = "sha256:a5b5f72bd68b48da446d56623e16b08a3483c84840b3a191771cd9b3e6fde8e9"}, ] +nonebot-test = [ + {file = "nonebot-test-0.1.0.tar.gz", hash = "sha256:f83bc095927f55e55cfe61c2ccc388e2536980d6d40412879009a16484487af4"}, + {file = "nonebot_test-0.1.0-py3-none-any.whl", hash = "sha256:3f981ac001f0f6c4f408d561b11fbe337fddc0a0f0d1e7a6602f34305ff82bcd"}, +] packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, @@ -1836,6 +1899,8 @@ pynacl = [ {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, + {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"}, + {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"}, {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, @@ -1861,9 +1926,17 @@ python-dotenv = [ {file = "python-dotenv-0.14.0.tar.gz", hash = "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d"}, {file = "python_dotenv-0.14.0-py2.py3-none-any.whl", hash = "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423"}, ] +python-engineio = [ + {file = "python-engineio-3.13.2.tar.gz", hash = "sha256:36b33c6aa702d9b6a7f527eec6387a2da1a9a24484ec2f086d76576413cef04b"}, + {file = "python_engineio-3.13.2-py2.py3-none-any.whl", hash = "sha256:cfded18156862f94544a9f8ef37f56727df731c8552d7023f5afee8369be2db6"}, +] python-slugify = [ {file = "python-slugify-4.0.1.tar.gz", hash = "sha256:69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270"}, ] +python-socketio = [ + {file = "python-socketio-4.6.0.tar.gz", hash = "sha256:358d8fbbc029c4538ea25bcaa283e47f375be0017fcba829de8a3a731c9df25a"}, + {file = "python_socketio-4.6.0-py2.py3-none-any.whl", hash = "sha256:d437f797c44b6efba2f201867cf02b8c96b97dff26d4e4281ac08b45817cd522"}, +] pytz = [ {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, @@ -1916,6 +1989,12 @@ regex = [ {file = "regex-2020.9.27-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:8d69cef61fa50c8133382e61fd97439de1ae623fe943578e477e76a9d9471637"}, {file = "regex-2020.9.27-cp38-cp38-win32.whl", hash = "sha256:f2388013e68e750eaa16ccbea62d4130180c26abb1d8e5d584b9baf69672b30f"}, {file = "regex-2020.9.27-cp38-cp38-win_amd64.whl", hash = "sha256:4318d56bccfe7d43e5addb272406ade7a2274da4b70eb15922a071c58ab0108c"}, + {file = "regex-2020.9.27-cp39-cp39-manylinux1_i686.whl", hash = "sha256:84cada8effefe9a9f53f9b0d2ba9b7b6f5edf8d2155f9fdbe34616e06ececf81"}, + {file = "regex-2020.9.27-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:816064fc915796ea1f26966163f6845de5af78923dfcecf6551e095f00983650"}, + {file = "regex-2020.9.27-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:5d892a4f1c999834eaa3c32bc9e8b976c5825116cde553928c4c8e7e48ebda67"}, + {file = "regex-2020.9.27-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c9443124c67b1515e4fe0bb0aa18df640965e1030f468a2a5dc2589b26d130ad"}, + {file = "regex-2020.9.27-cp39-cp39-win32.whl", hash = "sha256:49f23ebd5ac073765ecbcf046edc10d63dcab2f4ae2bce160982cb30df0c0302"}, + {file = "regex-2020.9.27-cp39-cp39-win_amd64.whl", hash = "sha256:3d20024a70b97b4f9546696cbf2fd30bae5f42229fbddf8661261b1eaff0deb7"}, {file = "regex-2020.9.27.tar.gz", hash = "sha256:a6f32aea4260dfe0e55dc9733ea162ea38f0ea86aa7d0f77b15beac5bf7b369d"}, ] requests = [ @@ -2041,14 +2120,14 @@ websockets = [ {file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"}, ] win32-setctime = [ - {file = "win32_setctime-1.0.2-py3-none-any.whl", hash = "sha256:02b4c5959ca0b195f45c98115826c6e8a630b7cf648e724feaab1a5aa6250640"}, - {file = "win32_setctime-1.0.2.tar.gz", hash = "sha256:47aa7c43548c1fc0a4f026d1944b748b37036df116c7c4cf908e82638d854313"}, + {file = "win32_setctime-1.0.3-py3-none-any.whl", hash = "sha256:dc925662de0a6eb987f0b01f599c01a8236cb8c62831c22d9cada09ad958243e"}, + {file = "win32_setctime-1.0.3.tar.gz", hash = "sha256:4e88556c32fdf47f64165a2180ba4552f8bb32c1103a2fafd05723a0bd42bd4b"}, ] yapf = [ {file = "yapf-0.30.0-py2.py3-none-any.whl", hash = "sha256:3abf61ba67cf603069710d30acbc88cfe565d907e16ad81429ae90ce9651e0c9"}, {file = "yapf-0.30.0.tar.gz", hash = "sha256:3000abee4c28daebad55da6c85f3cd07b8062ce48e2e9943c8da1b9667d48427"}, ] zipp = [ - {file = "zipp-3.2.0-py3-none-any.whl", hash = "sha256:43f4fa8d8bb313e65d8323a3952ef8756bf40f9a5c3ea7334be23ee4ec8278b6"}, - {file = "zipp-3.2.0.tar.gz", hash = "sha256:b52f22895f4cfce194bc8172f3819ee8de7540aa6d873535a8668b730b8b411f"}, + {file = "zipp-3.3.0-py3-none-any.whl", hash = "sha256:eed8ec0b8d1416b2ca33516a37a08892442f3954dee131e92cfd92d8fe3e7066"}, + {file = "zipp-3.3.0.tar.gz", hash = "sha256:64ad89efee774d1897a58607895d80789c59778ea02185dd846ac38394a8642b"}, ] diff --git a/pyproject.toml b/pyproject.toml index f0a3b83f2e9e..a0e3944e4e27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nonebot2" -version = "2.0.0a2" +version = "2.0.0a3" description = "An asynchronous python bot framework." authors = ["yanyongyu "] license = "MIT" @@ -31,7 +31,7 @@ fastapi = "^0.58.1" uvicorn = "^0.11.5" pydantic = { extras = ["dotenv"], version = "^1.6.1" } apscheduler = { version = "^3.6.3", optional = true } -# nonebot-test = { version = "^0.1.0", optional = true } +nonebot-test = { version = "^0.1.0", optional = true } nb-cli = { version="^0.1.0", optional = true } [tool.poetry.dev-dependencies] @@ -41,7 +41,7 @@ sphinx-markdown-builder = { git = "https://github.com/nonebot/sphinx-markdown-bu [tool.poetry.extras] cli = ["nb-cli"] -# test = ["nonebot-test"] +test = ["nonebot-test"] scheduler = ["apscheduler"] full = ["nb-cli", "nonebot-test", "scheduler"] diff --git a/tests/.env.dev b/tests/.env.dev index 2a129ee10271..96101fd4a3aa 100644 --- a/tests/.env.dev +++ b/tests/.env.dev @@ -3,6 +3,9 @@ HOST=0.0.0.0 PORT=2333 DEBUG=true +SUPERUSERS=[123123123] +NICKNAME=["bot"] + COMMAND_START=["", "/", "#"] COMMAND_SEP=["/", "."]