mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-07-28 08:41:29 +00:00
🔖 PreRelease 2.0.0a8.post2
This commit is contained in:
33
archive/2.0.0a8.post2/guide/README.md
Normal file
33
archive/2.0.0a8.post2/guide/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# 概览
|
||||
|
||||
<!-- :::tip 提示
|
||||
如果在阅读本文档时遇到难以理解的词汇,请随时查阅 [术语表](../glossary.md) 或使用 [Google 搜索](https://www.google.com/)。
|
||||
::: -->
|
||||
|
||||
:::tip 提示
|
||||
初次使用时可能会觉得这里的概览过于枯燥,可以先简单略读之后直接前往 [安装](./installation.md) 查看安装方法,并进行后续的基础使用教程。
|
||||
:::
|
||||
|
||||
## 简介
|
||||
|
||||
NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的事件进行解析和处理,并以插件化的形式,按优先级分发给事件所对应的事件响应器,来完成具体的功能。
|
||||
|
||||
除了起到解析事件的作用,NoneBot 还为插件提供了大量实用的预设操作和权限控制机制。对于命令处理,它更是提供了完善且易用的会话机制和内部调用机制,以分别适应命令的连续交互和插件内部功能复用等需求。
|
||||
|
||||
得益于 Python 的 [asyncio](https://docs.python.org/3/library/asyncio.html) 机制,NoneBot 处理事件的吞吐量有了很大的保障,再配合 WebSocket 通信方式(也是最建议的通信方式),NoneBot 的性能可以达到 HTTP 通信方式的两倍以上,相较于传统同步 I/O 的 HTTP 通信,更是有质的飞跃。
|
||||
|
||||
需要注意的是,NoneBot 仅支持 **Python 3.7+**
|
||||
|
||||
## 特色
|
||||
|
||||
NoneBot2 的驱动框架 `Driver` 以及通信协议 `Adapter` 均可**自定义**,并且可以作为插件进行**替换/添加**!
|
||||
|
||||
- 提供使用简易的脚手架
|
||||
- 提供丰富的官方插件
|
||||
- 提供可添加/替换的驱动以及协议选项
|
||||
- 基于异步 I/O
|
||||
- 同时支持 HTTP 和反向 WebSocket 通信方式
|
||||
- 支持多个机器人账号负载均衡
|
||||
- 提供直观的交互式会话接口
|
||||
- 提供可自定义的权限控制机制
|
||||
- 多种方式渲染要发送的消息内容,使对话足够自然
|
83
archive/2.0.0a8.post2/guide/basic-configuration.md
Normal file
83
archive/2.0.0a8.post2/guide/basic-configuration.md
Normal file
@ -0,0 +1,83 @@
|
||||
# 基本配置
|
||||
|
||||
到目前为止我们还在使用 NoneBot 的默认行为,在开始编写自己的插件之前,我们先尝试在配置文件上动动手脚,让 NoneBot 表现出不同的行为。
|
||||
|
||||
在上一章节中,我们创建了默认的项目结构,其中 `.env`, `.env.*` 均为项目的配置文件,下面将介绍几种 NoneBot 配置方式。
|
||||
|
||||
:::danger 警告
|
||||
请勿将敏感信息写入配置文件并提交至开源仓库!
|
||||
:::
|
||||
|
||||
## .env 文件
|
||||
|
||||
NoneBot 在启动时将会从系统环境变量或者 `.env` 文件中寻找变量 `ENVIRONMENT` (大小写不敏感),默认值为 `prod`。
|
||||
这将引导 NoneBot 从系统环境变量或者 `.env.{ENVIRONMENT}` 文件中进一步加载具体配置。
|
||||
|
||||
现在,我们在 `.env` 文件中写入当前环境信息:
|
||||
|
||||
```bash
|
||||
# .env
|
||||
ENVIRONMENT=dev
|
||||
```
|
||||
|
||||
如你所想,之后 NoneBot 就会从 `.env.dev` 文件中加载环境变量。
|
||||
|
||||
## .env.\* 文件
|
||||
|
||||
NoneBot 使用 [pydantic](https://pydantic-docs.helpmanual.io/) 进行配置管理,会从 `.env.{ENVIRONMENT}` 文件中获悉环境配置。
|
||||
|
||||
可以在 NoneBot 初始化时指定加载某个环境配置文件: `nonebot.init(_env_file=".env.dev")`,这将忽略你在 `.env` 中设置的环境信息。
|
||||
|
||||
:::warning 提示
|
||||
由于 `pydantic` 使用 JSON 解析配置项,请确保配置项值为 JSON 格式的数据。如:
|
||||
|
||||
```bash
|
||||
list=["123456789", "987654321", 1]
|
||||
test={"hello": "world"}
|
||||
```
|
||||
|
||||
如果配置项值解析失败将作为字符串处理。
|
||||
:::
|
||||
|
||||
示例及说明:
|
||||
|
||||
```bash
|
||||
HOST=0.0.0.0 # 配置 NoneBot 监听的 IP/主机名
|
||||
PORT=8080 # 配置 NoneBot 监听的端口
|
||||
DEBUG=true # 开启 debug 模式 **请勿在生产环境开启**
|
||||
SUPERUSERS=["123456789", "987654321"] # 配置 NoneBot 超级用户
|
||||
NICKNAME=["awesome", "bot"] # 配置机器人的昵称
|
||||
COMMAND_START=["/", ""] # 配置命令起始字符
|
||||
COMMAND_SEP=["."] # 配置命令分割字符
|
||||
|
||||
# Custom Configs
|
||||
CUSTOM_CONFIG1="config in env file"
|
||||
CUSTOM_CONFIG2= # 留空则从系统环境变量读取,如不存在则为空字符串
|
||||
```
|
||||
|
||||
详细的配置项参考 [Config Reference](../api/config.md) 。
|
||||
|
||||
## 系统环境变量
|
||||
|
||||
如果在系统环境变量中定义了配置,则一样会被读取。
|
||||
|
||||
## bot.py 文件
|
||||
|
||||
配置项也可以在 NoneBot 初始化时传入。此处可以传入任意合法 Python 变量。当然也可以在初始化完成后修改或新增。
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
# bot.py
|
||||
import nonebot
|
||||
|
||||
nonebot.init(custom_config3="config on init")
|
||||
|
||||
config = nonebot.get_driver().config
|
||||
config.custom_config3 = "changed after init"
|
||||
config.custom_config4 = "new config after init"
|
||||
```
|
||||
|
||||
## 优先级
|
||||
|
||||
`bot.py init` > `system env` > `env file`
|
101
archive/2.0.0a8.post2/guide/cqhttp-guide.md
Normal file
101
archive/2.0.0a8.post2/guide/cqhttp-guide.md
Normal file
@ -0,0 +1,101 @@
|
||||
# CQHTTP 协议使用指南
|
||||
|
||||
## 配置 CQHTTP 协议端(以 QQ 为例)
|
||||
|
||||
单纯运行 NoneBot 实例并不会产生任何效果,因为此刻 QQ 这边还不知道 NoneBot 的存在,也就无法把消息发送给它,因此现在需要使用一个无头 QQ 来把消息等事件上报给 NoneBot。
|
||||
|
||||
QQ 协议端举例:
|
||||
|
||||
- [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) (基于 [MiraiGo](https://github.com/Mrs4s/MiraiGo))
|
||||
- [cqhttp-mirai-embedded](https://github.com/yyuueexxiinngg/cqhttp-mirai/tree/embedded)
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai)
|
||||
- [Mirai](https://github.com/mamoe/mirai) + [Mirai Native](https://github.com/iTXTech/mirai-native) + [CQHTTP](https://github.com/richardchien/coolq-http-api)
|
||||
- [OICQ-http-api](https://github.com/takayama-lily/onebot) (基于 [OICQ](https://github.com/takayama-lily/oicq))
|
||||
|
||||
这里以 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 为例
|
||||
|
||||
1. 下载 go-cqhttp 对应平台的 release 文件,[点此前往](https://github.com/Mrs4s/go-cqhttp/releases)
|
||||
2. 运行 exe 文件或者使用 `./go-cqhttp` 启动
|
||||
3. 生成默认配置文件并修改默认配置
|
||||
|
||||
```hjson{2,3,35-36,42}
|
||||
{
|
||||
uin: 机器人QQ号
|
||||
password: 机器人密码
|
||||
encrypt_password: false
|
||||
password_encrypted: ""
|
||||
enable_db: true
|
||||
access_token: ""
|
||||
relogin: {
|
||||
enabled: true
|
||||
relogin_delay: 3
|
||||
max_relogin_times: 0
|
||||
}
|
||||
_rate_limit: {
|
||||
enabled: false
|
||||
frequency: 1
|
||||
bucket_size: 1
|
||||
}
|
||||
ignore_invalid_cqcode: false
|
||||
force_fragmented: false
|
||||
heartbeat_interval: 0
|
||||
http_config: {
|
||||
enabled: false
|
||||
host: "0.0.0.0"
|
||||
port: 5700
|
||||
timeout: 0
|
||||
post_urls: {}
|
||||
}
|
||||
ws_config: {
|
||||
enabled: false
|
||||
host: "0.0.0.0"
|
||||
port: 6700
|
||||
}
|
||||
ws_reverse_servers: [
|
||||
{
|
||||
enabled: true
|
||||
reverse_url: ws://127.0.0.1:8080/cqhttp/ws
|
||||
reverse_api_url: ws://you_websocket_api.server
|
||||
reverse_event_url: ws://you_websocket_event.server
|
||||
reverse_reconnect_interval: 3000
|
||||
}
|
||||
]
|
||||
post_message_format: array
|
||||
use_sso_address: false
|
||||
debug: false
|
||||
log_level: ""
|
||||
web_ui: {
|
||||
enabled: false
|
||||
host: 127.0.0.1
|
||||
web_ui_port: 9999
|
||||
web_input: false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其中 `ws://127.0.0.1:8080/cqhttp/ws` 中的 `127.0.0.1` 和 `8080` 应分别对应 nonebot 配置的 HOST 和 PORT。
|
||||
|
||||
`cqhttp` 是前述 `register_adapter` 时传入的第一个参数,代表设置的 `CQHTTPBot` 适配器的路径,你可以对不同的适配器设置不同路径以作区别。
|
||||
|
||||
## 历史性的第一次对话
|
||||
|
||||
一旦新的配置文件正确生效之后,NoneBot 所在的控制台(如果正在运行的话)应该会输出类似下面的内容(两条访问日志):
|
||||
|
||||
```default
|
||||
09-14 21:31:16 [INFO] uvicorn | ('127.0.0.1', 12345) - "WebSocket /cqhttp/ws" [accepted]
|
||||
09-14 21:31:16 [INFO] nonebot | WebSocket Connection from CQHTTP Bot 你的QQ号 Accepted!
|
||||
```
|
||||
|
||||
这表示 CQHTTP 协议端已经成功地使用 CQHTTP 协议连接上了 NoneBot。
|
||||
|
||||
现在,尝试向你的机器人账号发送如下内容:
|
||||
|
||||
```default
|
||||
/echo 你好,世界
|
||||
```
|
||||
|
||||
到这里如果一切 OK,你应该会收到机器人给你回复了 `你好,世界`。这一历史性的对话标志着你已经成功地运行了一个 NoneBot 的最小实例,开始了编写更强大的 QQ 机器人的创意之旅!
|
||||
|
||||
<ClientOnly>
|
||||
<Messenger :messages="[{ position: 'right', msg: '/echo 你好,世界' }, { position: 'left', msg: '你好,世界' }]"/>
|
||||
</ClientOnly>
|
197
archive/2.0.0a8.post2/guide/creating-a-handler.md
Normal file
197
archive/2.0.0a8.post2/guide/creating-a-handler.md
Normal file
@ -0,0 +1,197 @@
|
||||
# 事件处理
|
||||
|
||||
在上一章中,我们已经注册了事件响应器,现在我们可以正式编写事件处理逻辑了!
|
||||
|
||||
## [事件处理函数](../api/typing.md#handler)
|
||||
|
||||
```python{1,2,8,9}
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: T_State):
|
||||
args = str(event.get_message()).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: T_State):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
```
|
||||
|
||||
在之前的样例中,我们定义了两个函数 `handle_first_receive`, `handle_city`,他们被事件响应器的装饰器装饰从而成为事件响应器的事件处理函数。
|
||||
|
||||
:::tip 提示
|
||||
在事件响应器中,事件处理函数是**顺序**执行的!
|
||||
:::
|
||||
|
||||
### 添加一个事件处理函数
|
||||
|
||||
事件响应器提供了三种装饰事件处理函数的装饰器,分别是:
|
||||
|
||||
1. [handle()](../api/matcher.md#classmethod-handle)
|
||||
2. [receive()](../api/matcher.md#classmethod-receive)
|
||||
3. [got(key, prompt, args_parser)](../api/matcher.md#classmethod-got-key-prompt-none-args-parser-none)
|
||||
|
||||
#### handle()
|
||||
|
||||
简单的为事件响应器添加一个事件处理函数,这个函数将会在上一个处理函数正常返回执行完毕后立即执行。
|
||||
|
||||
#### receive()
|
||||
|
||||
指示 NoneBot 接收一条新的用户消息后继续执行该处理函数。此时函数将会接收到新的消息而非前一条消息,之前相关信息可以存储在 state 中。
|
||||
|
||||
特别的,当装饰的函数前没有其他事件处理函数,那么 `receive()` 不会接收一条新的消息而是直接使用第一条接收到的消息。
|
||||
|
||||
#### got(key, prompt, args_parser)
|
||||
|
||||
指示 NoneBot 当 `state` 中不存在 `key` 时向用户发送 `prompt` 等待用户回复并赋值给 `state[key]`。
|
||||
|
||||
`prompt` 可以为 `str`, `Message`, `MessageSegment`,若为空则不会向用户发送,若不为空则会在 format 之后发送,即 `prompt.format(**state)`,注意对 `{}` 进行转义。示例:
|
||||
|
||||
```python
|
||||
@matcher.receive()
|
||||
async def handle(bot: Bot, event: Event, state: T_State):
|
||||
state["key"] = "hello"
|
||||
|
||||
|
||||
@matcher.got("key2", prompt="{key}!")
|
||||
async def handle2(bot: Bot, event: Event, state: T_State):
|
||||
pass
|
||||
```
|
||||
|
||||
`args_parser` 为参数处理函数,在这里传入一个新的函数以覆盖默认的参数处理。详情参照 [args_parser](#参数处理函数-args-parser)
|
||||
|
||||
特别的,这些装饰器都可以套娃使用:
|
||||
|
||||
```python
|
||||
@matcher.got("key1")
|
||||
@matcher.got("key2")
|
||||
async def handle(bot: Bot, event: Event, state: T_State):
|
||||
pass
|
||||
```
|
||||
|
||||
### 事件处理函数参数
|
||||
|
||||
事件处理函数类型为:
|
||||
|
||||
- `Callable[[Bot, Event, T_State, Matcher], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, Event, T_State], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, Event, Matcher], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, T_State, Matcher], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, Event], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, T_State], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot, Matcher], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
- `Callable[[Bot], Union[Awaitable[None], Awaitable[NoReturn]]]`
|
||||
|
||||
简单说就是:除了 `bot` 参数,其他都是可选的。
|
||||
|
||||
以下函数都是合法的事件处理函数(仅列举常用的):
|
||||
|
||||
```python
|
||||
async def handle(bot: Bot, event: Event, state: T_State):
|
||||
pass
|
||||
|
||||
async def handle(bot: Bot, event: Event, state: T_State, matcher: Matcher):
|
||||
pass
|
||||
|
||||
async def handle(bot: Bot, event: Event):
|
||||
pass
|
||||
|
||||
async def handle(bot: Bot, state: T_State):
|
||||
pass
|
||||
|
||||
async def handle(bot: Bot):
|
||||
pass
|
||||
```
|
||||
|
||||
:::danger 警告
|
||||
函数的参数名固定不能修改!
|
||||
:::
|
||||
|
||||
参数分别为:
|
||||
|
||||
1. [nonebot.adapters.Bot](../api/adapters/#class-bot): 即事件上报连接对应的 Bot 对象,为 BaseBot 的子类。特别注意,此处的类型注释可以替换为指定的 Bot 类型,例如:`nonebot.adapters.cqhttp.Bot`,只有在上报事件的 Bot 类型与类型注释相符时才会执行该处理函数!可用于多平台进行不同的处理。
|
||||
2. [nonebot.adapters.Event](../api/adapters/#class-event): 即上报事件对象,可以获取到上报的所有信息。
|
||||
3. [state](../api/typing.md#t-state): 状态字典,可以存储任意的信息,其中还包含一些特殊的值以获取 NoneBot 内部处理时的一些信息,如:
|
||||
|
||||
- `state["_current_key"]`: 存储当前 `got` 获取的参数名
|
||||
- `state["_prefix"]`, `state["_suffix"]`: 存储当前 TRIE 匹配的前缀/后缀,可以通过该值获取用户命令的原始命令
|
||||
|
||||
:::tip 提示
|
||||
NoneBot 会对不同类型的参数进行不同的操作,详情查看 [事件处理函数重载](../advanced/overloaded-handlers.md)
|
||||
:::
|
||||
|
||||
### 参数处理函数 args_parser
|
||||
|
||||
在使用 `got` 获取用户输入参数时,需要对用户的消息进行处理以转换为我们所需要的信息。在默认情况下,NoneBot 会把用户的消息字符串原封不动的赋值给 `state[key]` 。可以通过以下两种方式修改默认处理逻辑:
|
||||
|
||||
- `@matcher.args_parser` 装饰器:直接装饰一个函数作为参数处理器
|
||||
- `got(key, prompt, args_parser)`:直接把函数作为参数传入
|
||||
|
||||
参数处理函数类型为:`Callable[[Bot, Event, T_State], Union[Awaitable[None], Awaitable[NoReturn]]]`,即:
|
||||
|
||||
```python
|
||||
async def parser(bot: Bot, event: Event, state: T_State):
|
||||
state[state["_current_key"]] = str(event.get_message())
|
||||
```
|
||||
|
||||
特别的,`state["_current_key"]` 中存储了当前获取的参数名
|
||||
|
||||
### 逻辑控制
|
||||
|
||||
NoneBot 也为事件处理函数提供了一些便捷的逻辑控制函数:
|
||||
|
||||
#### `matcher.send`
|
||||
|
||||
这个函数用于发送一条消息给当前交互的用户。~~其实这并不是一个逻辑控制函数,只是不知道放在哪里……~~
|
||||
|
||||
#### `matcher.pause`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再运行**下一个消息处理函数**。
|
||||
|
||||
#### `matcher.reject`
|
||||
|
||||
这个函数用于结束当前事件处理函数,强制接收一条新的消息再**再次运行当前消息处理函数**。常用于用户输入信息不符合预期。
|
||||
|
||||
#### `matcher.finish`
|
||||
|
||||
这个函数用于直接结束当前事件处理。
|
||||
|
||||
以上三个函数都拥有一个参数 `message` / `prompt`,用于向用户发送一条消息。以及 `**kwargs` 直接传递给 `bot.send` 的额外参数。
|
||||
|
||||
## 常用事件处理结构
|
||||
|
||||
```python
|
||||
matcher = on_command("test")
|
||||
|
||||
# 修改默认参数处理
|
||||
@matcher.args_parser
|
||||
async def parse(bot: Bot, event: Event, state: T_State):
|
||||
print(state["_current_key"], ":", str(event.get_message()))
|
||||
state[state["_current_key"]] = str(event.get_message())
|
||||
|
||||
@matcher.handle()
|
||||
async def first_receive(bot: Bot, event: Event, state: T_State):
|
||||
# 获取用户原始命令,如:/test
|
||||
print(state["_prefix"]["raw_command"])
|
||||
# 处理用户输入参数,如:/test arg1 arg2
|
||||
raw_args = str(event.get_message()).strip()
|
||||
if raw_args:
|
||||
arg_list = raw_args.split()
|
||||
# 将参数存入state以阻止后续再向用户询问参数
|
||||
state["arg1"] = arg_list[0]
|
||||
|
||||
|
||||
@matcher.got("arg1", prompt="参数?")
|
||||
async def arg_handle(bot: Bot, event: Event, state: T_State):
|
||||
# 在这里对参数进行验证
|
||||
if state["arg1"] not in ["allow", "list"]:
|
||||
await matcher.reject("参数不正确!请重新输入")
|
||||
# 发送一些信息
|
||||
await bot.send(event, "message")
|
||||
await matcher.send("message")
|
||||
await matcher.finish("message")
|
||||
```
|
146
archive/2.0.0a8.post2/guide/creating-a-matcher.md
Normal file
146
archive/2.0.0a8.post2/guide/creating-a-matcher.md
Normal file
@ -0,0 +1,146 @@
|
||||
# 注册事件响应器
|
||||
|
||||
好了,现在插件已经创建完毕,我们可以开始编写实际代码了,下面将以一个简易单文件天气查询插件为例。
|
||||
|
||||
在插件目录下 `weather.py` 中添加如下代码:
|
||||
|
||||
```python
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters import Bot, Event
|
||||
|
||||
weather = on_command("天气", rule=to_me(), priority=5)
|
||||
|
||||
|
||||
@weather.handle()
|
||||
async def handle_first_receive(bot: Bot, event: Event, state: T_State):
|
||||
args = str(event.get_message()).strip() # 首次发送命令时跟随的参数,例:/天气 上海,则args为上海
|
||||
if args:
|
||||
state["city"] = args # 如果用户发送了参数则直接赋值
|
||||
|
||||
|
||||
@weather.got("city", prompt="你想查询哪个城市的天气呢?")
|
||||
async def handle_city(bot: Bot, event: Event, state: T_State):
|
||||
city = state["city"]
|
||||
if city not in ["上海", "北京"]:
|
||||
await weather.reject("你想查询的城市暂不支持,请重新输入!")
|
||||
city_weather = await get_weather(city)
|
||||
await weather.finish(city_weather)
|
||||
|
||||
|
||||
async def get_weather(city: str):
|
||||
return f"{city}的天气是..."
|
||||
```
|
||||
|
||||
为了简单起见,我们在这里的例子中没有接入真实的天气数据,但要接入也非常简单,你可以使用中国天气网、和风天气等网站提供的 API。
|
||||
|
||||
接下来我们来说明这段代码是如何工作的。
|
||||
|
||||
:::tip 提示
|
||||
从这里开始,你需要对 Python 的 asyncio 编程有所了解,因为 NoneBot 是完全基于 asyncio 的,具体可以参考 [廖雪峰的 Python 教程](https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152)
|
||||
:::
|
||||
|
||||
## [事件响应器](../api/matcher.md)
|
||||
|
||||
```python{5}
|
||||
from nonebot import on_command
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.permission import Permission
|
||||
|
||||
weather = on_command("天气", rule=to_me(), permission=Permission(), priority=5)
|
||||
```
|
||||
|
||||
在上方代码中,我们注册了一个事件响应器 `Matcher`,它由几个部分组成:
|
||||
|
||||
1. `on_command` 注册一个消息类型的命令处理器
|
||||
2. `"天气"` 指定 command 参数 - 命令名
|
||||
3. `rule` 补充事件响应器的匹配规则
|
||||
4. `priority` 事件响应器优先级
|
||||
5. `block` 是否阻止事件传递
|
||||
|
||||
其他详细配置可以参考 API 文档,下面我们详细说明各个部分:
|
||||
|
||||
### 事件响应器类型 type
|
||||
|
||||
事件响应器类型其实就是对应事件的类型 `Event.get_type()` ,NoneBot 提供了一个基础类型事件响应器 `on()` 以及一些其他内置的事件响应器。
|
||||
|
||||
以下所有类型的事件响应器都是由 `on(type, rule)` 的形式进行了简化封装。
|
||||
|
||||
- `on("事件类型")`: 基础事件响应器,第一个参数为事件类型,空字符串表示不限
|
||||
- `on_metaevent()` ~ `on("meta_event")`: 元事件响应器
|
||||
- `on_message()` ~ `on("message")`: 消息事件响应器
|
||||
- `on_request()` ~ `on("request")`: 请求事件响应器
|
||||
- `on_notice()` ~ `on("notice")`: 通知事件响应器
|
||||
- `on_startswith(str)` ~ `on("message", startswith(str))`: 消息开头匹配响应器,参考 [startswith](../api/rule.md#startswith-msg)
|
||||
- `on_endswith(str)` ~ `on("message", endswith(str))`: 消息结尾匹配响应器,参考 [endswith](../api/rule.md#endswith-msg)
|
||||
- `on_keyword(set)` ~ `on("message", keyword(str))`: 消息关键词匹配响应器,参考 [keyword](../api/rule.md#keyword-keywords)
|
||||
- `on_command(str|tuple)` ~ `on("message", command(str|tuple))`: 命令响应器,参考 [command](../api/rule.md#command-cmds)
|
||||
- `on_regex(pattern_str)` ~ `on("message", regex(pattern_str))`: 正则匹配处理器,参考 [regex](../api/rule.md#regex-regex-flags-0)
|
||||
|
||||
### 匹配规则 rule
|
||||
|
||||
事件响应器的匹配规则即 `Rule`,详细内容在下方介绍。[直达](#自定义-rule)
|
||||
|
||||
### 优先级 priority
|
||||
|
||||
事件响应器的优先级代表事件响应器的执行顺序,同一优先级的事件响应器会 **同时执行!**,优先级数字**越小**越先响应!优先级请从 `1` 开始排序!
|
||||
|
||||
:::tip 提示
|
||||
使用 `nonebot-plugin-test` 可以在网页端查看当前所有事件响应器的执行流程,有助理解事件响应流程!
|
||||
|
||||
```bash
|
||||
nb plugin install nonebot_plugin_test
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### 阻断 block
|
||||
|
||||
当有任意事件响应器发出了阻止事件传递信号时,该事件将不再会传递给下一优先级,直接结束处理。
|
||||
|
||||
NoneBot 内置的事件响应器中,所有 `message` 类的事件响应器默认会阻断事件传递,其他则不会。
|
||||
|
||||
## 自定义 rule
|
||||
|
||||
rule 的出现使得 nonebot 对事件的响应可以非常自由,nonebot 内置了一些规则:
|
||||
|
||||
- [startswith(msg)](../api/rule.md#startswith-msg)
|
||||
- [endswith(msg)](../api/rule.md#endswith-msg)
|
||||
- [keyword(\*keywords)](../api/rule.md#keyword-keywords)
|
||||
- [command(\*cmds)](../api/rule.md#command-cmds)
|
||||
- [regex(regex, flag)](../api/rule.md#regex-regex-flags-0)
|
||||
|
||||
以上规则都是返回类型为 `Rule` 的函数,`Rule` 由非负个 `RuleChecker` 组成,当所有 `RuleChecker` 返回 `True` 时匹配成功。这些 `Rule`, `RuleChecker` 的形式如下:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
from nonebot.typing import T_State
|
||||
|
||||
async def async_checker(bot: Bot, event: Event, state: T_State) -> bool:
|
||||
return True
|
||||
|
||||
def sync_checker(bot: Bot, event: Event, state: T_State) -> bool:
|
||||
return True
|
||||
|
||||
def check(arg1, args2):
|
||||
|
||||
async def _checker(bot: Bot, event: Event, state: T_State) -> bool:
|
||||
return bool(arg1 + arg2)
|
||||
|
||||
return Rule(_check)
|
||||
```
|
||||
|
||||
`Rule` 和 `RuleChecker` 之间可以使用 `与 &` 互相组合:
|
||||
|
||||
```python
|
||||
from nonebot.rule import Rule
|
||||
|
||||
Rule(async_checker1) & sync_checker & async_checker2
|
||||
```
|
||||
|
||||
**_请勿将事件处理的逻辑写入 `rule` 中,这会使得事件处理返回奇怪的响应。_**
|
||||
|
||||
:::danger 警告
|
||||
`Rule(*checkers)` 只接受 async function,或使用 `nonebot.utils.run_sync` 自行包裹 sync function。在使用 `与 &` 时,NoneBot 会自动包裹 sync function
|
||||
:::
|
119
archive/2.0.0a8.post2/guide/creating-a-plugin.md
Normal file
119
archive/2.0.0a8.post2/guide/creating-a-plugin.md
Normal file
@ -0,0 +1,119 @@
|
||||
# 创建插件
|
||||
|
||||
如果之前使用 `nb-cli` 生成了项目结构,那我们已经有了一个空的插件目录 `Awesome-Bot/awesome_bot/plugins`,并且它已在 `bot.py` 中被加载,我们现在可以开始创建插件了!
|
||||
|
||||
使用 `nb-cli` 创建包形式插件,或自行创建文件(夹)
|
||||
|
||||
```bash
|
||||
nb plugin new
|
||||
```
|
||||
|
||||
插件通常有两种形式,下面分别介绍
|
||||
|
||||
## 单文件形式
|
||||
|
||||
在插件目录下创建名为 `foo.py` 的 Python 文件,暂时留空,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `foo.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候它已经可以被称为一个插件了,尽管它还什么都没做。
|
||||
|
||||
## 包形式(推荐)
|
||||
|
||||
在插件目录下创建文件夹 `foo`,并在该文件夹下创建文件 `__init__.py`,此时目录结构如下:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── awesome_bot
|
||||
│ └── plugins
|
||||
│ └── `foo`
|
||||
│ └── `__init__.py`
|
||||
├── .env
|
||||
├── .env.dev
|
||||
├── .env.prod
|
||||
├── .gitignore
|
||||
├── bot.py
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pyproject.toml
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
这个时候 `foo` 就是一个合法的 Python 包了,同时也是合法的 NoneBot 插件,插件内容可以在 `__init__.py` 中编写。
|
||||
|
||||
### 推荐结构(仅供参考)
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
foo
|
||||
├── `__init__.py`
|
||||
├── `config.py`
|
||||
├── `data_source.py`
|
||||
└── `model.py`
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### \_\_init\_\_.py
|
||||
|
||||
在该文件中编写各类事件响应及处理逻辑。
|
||||
|
||||
#### config.py
|
||||
|
||||
在该文件中使用 `pydantic` 定义插件所需要的配置项以及类型。
|
||||
|
||||
示例:
|
||||
|
||||
```python
|
||||
from pydantic import BaseSettings
|
||||
|
||||
|
||||
class Config(BaseSettings):
|
||||
|
||||
# plugin custom config
|
||||
plugin_setting: str = "default"
|
||||
|
||||
class Config:
|
||||
extra = "ignore"
|
||||
```
|
||||
|
||||
并在 `__init__.py` 文件中添加以下行
|
||||
|
||||
```python
|
||||
import nonebot
|
||||
from .config import Config
|
||||
|
||||
global_config = nonebot.get_driver().config
|
||||
plugin_config = Config(**global_config.dict())
|
||||
```
|
||||
|
||||
此时就可以通过 `plugin_config.plugin_setting` 获取到插件所需要的配置项了。
|
||||
|
||||
#### data_source.py
|
||||
|
||||
在该文件中编写数据获取函数。
|
||||
|
||||
:::warning 警告
|
||||
数据获取应尽量使用**异步**处理!例如使用 [httpx](https://www.python-httpx.org/) 而非 [requests](https://requests.readthedocs.io/en/master/)
|
||||
:::
|
||||
|
||||
#### model.py
|
||||
|
||||
在该文件中编写数据库模型。
|
51
archive/2.0.0a8.post2/guide/creating-a-project.md
Normal file
51
archive/2.0.0a8.post2/guide/creating-a-project.md
Normal file
@ -0,0 +1,51 @@
|
||||
# 创建一个完整的项目
|
||||
|
||||
上一章中我们已经运行了一个简单的 NoneBot 实例,在这一章,我们将从零开始一个完整的项目。
|
||||
|
||||
## 目录结构
|
||||
|
||||
可以使用 `nb-cli` 或者自行创建完整的项目目录:
|
||||
|
||||
```bash
|
||||
nb create
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
AweSome-Bot
|
||||
├── `awesome_bot` _(**或是 src**)_
|
||||
│ └── `plugins`
|
||||
├── `.env` _(**可选的**)_
|
||||
├── `.env.dev` _(**可选的**)_
|
||||
├── `.env.prod` _(**可选的**)_
|
||||
├── .gitignore
|
||||
├── `bot.py`
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── `pyproject.toml`
|
||||
└── README.md
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
- `awesome_bot/plugins` 或 `src/plugins`: 用于存放编写的 bot 插件
|
||||
- `.env`, `.env.dev`, `.env.prod`: 各环境配置文件
|
||||
- `bot.py`: bot 入口文件
|
||||
- `pyproject.toml`: 项目依赖管理文件,默认使用 [poetry](https://python-poetry.org/)
|
||||
|
||||
## 启动 Bot
|
||||
|
||||
如果你使用 `nb-cli`
|
||||
|
||||
```bash
|
||||
nb run [--file=bot.py] [--app=app]
|
||||
```
|
||||
|
||||
或者使用
|
||||
|
||||
```bash
|
||||
python bot.py
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
如果在 bot 入口文件内定义了 asgi server, `nb-cli` 将会为你启动**冷重载模式**
|
||||
:::
|
3
archive/2.0.0a8.post2/guide/ding-guide.md
Normal file
3
archive/2.0.0a8.post2/guide/ding-guide.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 钉钉机器人使用指南
|
||||
|
||||
~~TODO~~
|
9
archive/2.0.0a8.post2/guide/end-or-start.md
Normal file
9
archive/2.0.0a8.post2/guide/end-or-start.md
Normal file
@ -0,0 +1,9 @@
|
||||
# 结语
|
||||
|
||||
至此,相信你已经能够写出一个基础的插件了。这里给出几个小提示:
|
||||
|
||||
- 请千万注意事件处理器的优先级设定
|
||||
- 在匹配规则中请勿使用耗时极长的函数
|
||||
- 同一个用户可以**跨群**(**私聊**)继续他的事件处理(除非做出权限限制,将在后续介绍)
|
||||
|
||||
如果「指南」还不能满足你,前往 [进阶](../advanced/README.md) 查看更多的功能信息。
|
86
archive/2.0.0a8.post2/guide/getting-started.md
Normal file
86
archive/2.0.0a8.post2/guide/getting-started.md
Normal file
@ -0,0 +1,86 @@
|
||||
# 开始使用
|
||||
|
||||
一切都安装成功后,你就已经做好了进行简单配置以运行一个最小的 NoneBot 实例的准备。
|
||||
|
||||
## 最小实例
|
||||
|
||||
如果你已经按照推荐方式安装了 `nb-cli`,使用脚手架创建一个空项目:
|
||||
|
||||
```bash
|
||||
nb create
|
||||
```
|
||||
|
||||
根据脚手架引导,将在当前目录下创建一个项目目录,项目目录内包含 `bot.py`。
|
||||
|
||||
如果未安装 `nb-cli`,使用你最熟悉的编辑器或 IDE,创建一个名为 `bot.py` 的文件,内容如下(这里以 CQHTTP 为例):
|
||||
|
||||
```python{4,6,7,10}
|
||||
import nonebot
|
||||
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
|
||||
|
||||
nonebot.init()
|
||||
driver = nonebot.get_driver()
|
||||
driver.register_adapter("cqhttp", CQHTTPBot)
|
||||
nonebot.load_builtin_plugins()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
## 解读
|
||||
|
||||
在上方 `bot.py` 中,这几行高亮代码将依次:
|
||||
|
||||
1. 使用默认配置初始化 NoneBot
|
||||
2. 加载 NoneBot 内置的 CQHTTP 协议适配组件
|
||||
`register_adapter` 的第一个参数我们传入了一个字符串,该字符串将会在后文 [配置 CQHTTP 协议端](#配置-cqhttp-协议端-以-qq-为例) 时使用。
|
||||
3. 加载 NoneBot 内置的插件
|
||||
4. 在地址 `127.0.0.1:8080` 运行 NoneBot
|
||||
|
||||
在命令行使用如下命令即可运行这个 NoneBot 实例:
|
||||
|
||||
```bash
|
||||
# nb-cli
|
||||
nb run
|
||||
# 其他
|
||||
python bot.py
|
||||
```
|
||||
|
||||
运行后会产生如下日志:
|
||||
|
||||
```plain
|
||||
09-14 21:02:00 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-14 21:02:00 [INFO] nonebot | Running NoneBot...
|
||||
09-14 21:02:00 [INFO] uvicorn | Started server process [1234]
|
||||
09-14 21:02:00 [INFO] uvicorn | Waiting for application startup.
|
||||
09-14 21:02:00 [INFO] uvicorn | Application startup complete.
|
||||
09-14 21:02:00 [INFO] uvicorn | Uvicorn running on http://127.0.0.1:8080 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
## 配置协议端上报
|
||||
|
||||
在 `bot.py` 文件中使用 `register_adapter` 注册协议适配之后即可配置协议端来完成与 NoneBot 的通信,详细配置方法参考:
|
||||
|
||||
- [配置 CQHTTP](./cqhttp-guide.md)
|
||||
- [配置钉钉](./ding-guide.md)
|
||||
|
||||
NoneBot 接受的上报地址与 `Driver` 有关,默认使用的 `FastAPI Driver` 所接受的上报地址有:
|
||||
|
||||
- `/{adapter name}/`: HTTP POST 上报
|
||||
- `/{adapter name}/http/`: HTTP POST 上报
|
||||
- `/{adapter name}/ws`: WebSocket 上报
|
||||
- `/{adapter name}/ws/`: WebSocket 上报
|
||||
|
||||
:::warning 注意
|
||||
如果到这一步你没有在 NoneBot 看到连接成功日志,比较常见的出错点包括:
|
||||
|
||||
- NoneBot 监听 `0.0.0.0`,然后在协议端上报配置中填了 `ws://0.0.0.0:8080/***/ws`
|
||||
- 在 Docker 容器内运行协议端,并通过 `127.0.0.1` 访问宿主机上的 NoneBot
|
||||
- 想从公网访问,但没有修改云服务商的安全组策略或系统防火墙
|
||||
- NoneBot 所监听的端口存在冲突,已被其它程序占用
|
||||
- 弄混了 NoneBot 的 `host`、`port` 参数与协议端上报配置中的 `host`、`port` 参数
|
||||
- `ws://` 错填为 `http://`
|
||||
- 协议端或 NoneBot 启动时遭到外星武器干扰
|
||||
|
||||
请尝试重启协议端 NoneBot、更换端口、修改防火墙、重启系统、仔细阅读前面的文档及提示、更新协议端 和 NoneBot 到最新版本等方式来解决。
|
||||
:::
|
91
archive/2.0.0a8.post2/guide/installation.md
Normal file
91
archive/2.0.0a8.post2/guide/installation.md
Normal file
@ -0,0 +1,91 @@
|
||||
# 安装
|
||||
|
||||
## NoneBot
|
||||
|
||||
:::warning 注意
|
||||
请确保你的 Python 版本 >= 3.7。
|
||||
:::
|
||||
|
||||
:::warning 注意
|
||||
请在安装 nonebot2 之前卸载 nonebot 1.x
|
||||
|
||||
```bash
|
||||
pip uninstall nonebot
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### 通过脚手架安装(推荐安装方式)
|
||||
|
||||
1. (推荐)使用你喜欢的 Python 环境管理工具(如 `poetry`)创建新的虚拟环境。
|
||||
2. 使用 `pip` (或其他包管理工具) 安装 nb-cli,nonebot2 作为其依赖会一起被安装。
|
||||
|
||||
```bash
|
||||
pip install nb-cli
|
||||
```
|
||||
|
||||
3. 点个 star 吧
|
||||
|
||||
nonebot2: [](https://github.com/nonebot/nonebot2)
|
||||
|
||||
nb-cli: [](https://github.com/nonebot/nb-cli)
|
||||
|
||||
### 不使用脚手架(纯净安装)
|
||||
|
||||
```bash
|
||||
pip install nonebot2
|
||||
# 也可以通过 poetry 安装
|
||||
poetry add nonebot2
|
||||
```
|
||||
|
||||
如果你需要使用最新的(可能**尚未发布**的)特性,可以直接从 GitHub 仓库安装:
|
||||
|
||||
:::warning 注意
|
||||
直接从 Github 仓库中安装意味着你将使用最新提交的代码,它们并没有进行充分的稳定性测试
|
||||
在任何情况下请不要将其应用于生产环境!
|
||||
:::
|
||||
|
||||
```bash
|
||||
# master分支
|
||||
poetry add git+https://github.com/nonebot/nonebot2.git#master
|
||||
# dev分支
|
||||
poetry add git+https://github.com/nonebot/nonebot2.git#dev
|
||||
```
|
||||
|
||||
或者在克隆 Git 仓库后手动安装:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nonebot/nonebot2.git
|
||||
cd nonebot2
|
||||
poetry install --no-dev # 推荐
|
||||
pip install . # 不推荐
|
||||
```
|
||||
|
||||
## 安装插件
|
||||
|
||||
插件可以通过 `nb-cli` 进行安装,也可以自行安装并加载插件。
|
||||
|
||||
```bash
|
||||
# 列出所有的插件
|
||||
nb plugin list
|
||||
# 搜索插件
|
||||
nb plugin search xxx
|
||||
# 安装插件
|
||||
nb plugin install xxx
|
||||
```
|
||||
|
||||
如果急于上线 Bot 或想要使用现成的插件,以下插件可作为参考:
|
||||
|
||||
### 官方插件
|
||||
|
||||
~~自用插件~~ ~~确信~~
|
||||
|
||||
- [NoneBot-Plugin-Docs](https://github.com/nonebot/nonebot2/tree/master/packages/nonebot-plugin-docs) 离线文档插件
|
||||
- [NoneBot-Plugin-Test](https://github.com/nonebot/plugin-test) 本地机器人测试前端插件
|
||||
- [NoneBot-Plugin-APScheduler](https://github.com/nonebot/plugin-apscheduler) 定时任务插件
|
||||
- [NoneBot-Plugin-Sentry](https://github.com/cscs181/QQ-GitHub-Bot/tree/master/src/plugins/nonebot_plugin_sentry) Sentry 在线日志分析插件
|
||||
- [NoneBot-Plugin-Status](https://github.com/cscs181/QQ-GitHub-Bot/tree/master/src/plugins/nonebot_plugin_status) 服务器状态查看插件
|
||||
|
||||
### 其他插件
|
||||
|
||||
还有更多的插件在 [这里](/plugin-store.md) 等着你发现~
|
116
archive/2.0.0a8.post2/guide/loading-a-plugin.md
Normal file
116
archive/2.0.0a8.post2/guide/loading-a-plugin.md
Normal file
@ -0,0 +1,116 @@
|
||||
# 加载插件
|
||||
|
||||
在 [创建一个完整的项目](creating-a-project) 一章节中,我们已经创建了插件目录 `awesome_bot/plugins`,现在我们在机器人入口文件中加载它。当然,你也可以单独加载一个插件。
|
||||
|
||||
## 加载内置插件
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载 nonebot 内置插件
|
||||
nonebot.load_builtin_plugins()
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
这将会加载 nonebot 内置的插件,它包含:
|
||||
|
||||
- 命令 `say`:可由**superuser**使用,可以将消息内容由特殊纯文本转为富文本
|
||||
- 命令 `echo`:可由任何人使用,将消息原样返回
|
||||
|
||||
以上命令均需要指定机器人,即私聊、群聊内@机器人、群聊内称呼机器人昵称。参考 [Rule: to_me](../api/rule.md#to-me)
|
||||
|
||||
## 加载插件目录
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载插件目录,该目录下为各插件,以下划线开头的插件将不会被加载
|
||||
nonebot.load_plugins("awesome_bot/plugins")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
:::tip 提示
|
||||
加载插件目录时,目录下以 `_` 下划线开头的插件将不会被加载!
|
||||
:::
|
||||
|
||||
:::warning 提示
|
||||
**不能存在相同名称的插件!**
|
||||
:::
|
||||
|
||||
:::danger 警告
|
||||
插件间不应该存在过多的耦合,如果确实需要导入某个插件内的数据,可以参考 [进阶-跨插件访问](../advanced/export-and-require.md)
|
||||
:::
|
||||
|
||||
## 加载单个插件
|
||||
|
||||
在 `bot.py` 文件中添加以下行:
|
||||
|
||||
```python{5,7}
|
||||
import nonebot
|
||||
|
||||
nonebot.init()
|
||||
# 加载一个 pip 安装的插件
|
||||
nonebot.load_plugin("nonebot_plugin_status")
|
||||
# 加载本地的单独插件
|
||||
nonebot.load_plugin("awesome_bot.plugins.xxx")
|
||||
|
||||
app = nonebot.get_asgi()
|
||||
|
||||
if __name__ == "__main__":
|
||||
nonebot.run()
|
||||
```
|
||||
|
||||
## 子插件(嵌套插件)
|
||||
|
||||
在插件中同样可以加载子插件,例如如下插件目录结构:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
:::vue
|
||||
foo_plugin
|
||||
├── `plugins`
|
||||
│ ├── `sub_plugin1`
|
||||
│ │ └── \_\_init\_\_.py
|
||||
│ └── `sub_plugin2.py`
|
||||
├── `__init__.py`
|
||||
└── config.py
|
||||
:::
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
在插件目录下的 `__init__.py` 中添加如下代码:
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
|
||||
# store all subplugins
|
||||
_sub_plugins = set()
|
||||
# load sub plugins
|
||||
_sub_plugins |= nonebot.load_plugins(
|
||||
str((Path(__file__).parent / "plugins").resolve()))
|
||||
```
|
||||
|
||||
插件将会被加载并存储于 `_sub_plugins` 中。
|
||||
|
||||
## 运行结果
|
||||
|
||||
尝试运行 `nb run` 或者 `python bot.py`,可以看到日志输出了类似如下内容:
|
||||
|
||||
```plain
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "nonebot.plugins.base"
|
||||
09-19 21:51:59 [INFO] nonebot | Succeeded to import "plugin_in_folder"
|
||||
```
|
Reference in New Issue
Block a user