Skip to content

Commit 832875e

Browse files
authored
🔀 Merge pull request #462
Release: 2.0.0a14
2 parents 8680695 + 73762e6 commit 832875e

File tree

188 files changed

+18817
-3200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+18817
-3200
lines changed

.github/ISSUE_TEMPLATE/bug-report.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ A clear and concise description of what you expected to happen.
2828
- Python Version: [e.g. 3.8]
2929
- Nonebot Version: [e.g. 2.0.0]
3030

31-
**截图**
31+
**协议端信息:**
32+
33+
- 协议端: [e.g. go-cqhttp]
34+
- 协议端版本: [e.g. 1.0.0]
35+
36+
**截图或日志**
3237

3338
If applicable, add screenshots to help explain your problem.

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
blank_issues_enabled: false
22
contact_links:
3+
- name: Question
4+
url: https://github.com/nonebot/discussions/discussions/new
5+
about: Ask questions about nonebot
36
- name: Plugin Publish
47
url: https://v2.nonebot.dev/store.html
58
about: Publish your plugin to nonebot homepage and nb-cli

.github/ISSUE_TEMPLATE/document.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Document improvement
3+
about: Feedback on documentation, including errors and ideas
4+
title: 'Docs: some description'
5+
labels: documentation
6+
assignees: ''
7+
8+
---
9+
10+
**描述问题或主题:**
11+
12+
13+
**需做出的修改:**
14+
15+
* [ ] 一些修改
16+
* [ ] 一些修改
17+
* [ ] 一些修改

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,5 @@ dev
189189
docs_build/_build
190190
!tests/.env
191191
*.xmind
192+
yarn.lock
193+
.DS_Store

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"tabWidth": 2,
3+
"useTabs": false,
4+
"endOfLine": "lf",
5+
"arrowParens": "always",
6+
"singleQuote": false,
7+
"trailingComma": "es5",
8+
"semi": true
9+
}

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# NoneBot
88

9-
_✨ Python 异步机器人框架 ✨_
9+
_跨平台 Python 异步机器人框架 ✨_
1010

1111
</div>
1212

@@ -17,7 +17,7 @@ _✨ Python 异步机器人框架 ✨_
1717
<a href="https://pypi.python.org/pypi/nonebot2">
1818
<img src="https://img.shields.io/pypi/v/nonebot2" alt="pypi">
1919
</a>
20-
<img src="https://img.shields.io/badge/python-3.7+-blue" alt="python"><br />
20+
<img src="https://img.shields.io/badge/python-3.7.3+-blue" alt="python"><br />
2121
<a href="https://github.com/howmanybots/onebot/blob/master/README.md">
2222
<img src="https://img.shields.io/badge/OneBot-v11-black?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAIVBMVEUAAAAAAAADAwMHBwceHh4UFBQNDQ0ZGRkoKCgvLy8iIiLWSdWYAAAAAXRSTlMAQObYZgAAAQVJREFUSMftlM0RgjAQhV+0ATYK6i1Xb+iMd0qgBEqgBEuwBOxU2QDKsjvojQPvkJ/ZL5sXkgWrFirK4MibYUdE3OR2nEpuKz1/q8CdNxNQgthZCXYVLjyoDQftaKuniHHWRnPh2GCUetR2/9HsMAXyUT4/3UHwtQT2AggSCGKeSAsFnxBIOuAggdh3AKTL7pDuCyABcMb0aQP7aM4AnAbc/wHwA5D2wDHTTe56gIIOUA/4YYV2e1sg713PXdZJAuncdZMAGkAukU9OAn40O849+0ornPwT93rphWF0mgAbauUrEOthlX8Zu7P5A6kZyKCJy75hhw1Mgr9RAUvX7A3csGqZegEdniCx30c3agAAAABJRU5ErkJggg==" alt="cqhttp">
2323
</a>
@@ -34,14 +34,11 @@ _✨ Python 异步机器人框架 ✨_
3434
<a href="https://jq.qq.com/?_wv=1027&k=5OFifDh">
3535
<img src="https://img.shields.io/badge/qq%E7%BE%A4-768887710-orange?style=flat-square" alt="QQ Chat">
3636
</a>
37-
<a href="https://t.me/cqhttp">
38-
<img src="https://img.shields.io/badge/telegram-chat-blue?style=flat-square" alt="Telegram Chat">
37+
<a href="https://t.me/botuniverse">
38+
<img src="https://img.shields.io/badge/telegram-botuniverse-blue?style=flat-square" alt="Telegram Channel">
3939
</a>
40-
<a href="https://jq.qq.com/?_wv=1027&k=5Nl0zhE">
41-
<img src="https://img.shields.io/badge/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E7%BE%A4-218529254-green?style=flat-square" alt="QQ Release">
42-
</a>
43-
<a href="https://t.me/cqhttp_release">
44-
<img src="https://img.shields.io/badge/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83%E9%A2%91%E9%81%93-join-green?style=flat-square" alt="Telegram Release">
40+
<a href="https://discord.gg/VKtE6Gdc4h">
41+
<img src="https://discordapp.com/api/guilds/847819937858584596/widget.png?style=shield" alt="Discord Server">
4542
</a>
4643
</p>
4744

@@ -100,7 +97,13 @@ NoneBot2 的驱动框架 `Driver` 以及通信协议 `Adapter` 均可**自定义
10097
nb create
10198
```
10299

103-
## 插件
100+
## 社区资源
101+
102+
### 教程/实际项目/经验分享
103+
104+
- [awesome-nonebot](https://github.com/nonebot/awesome-nonebot)
105+
106+
### 插件
104107

105108
此外,NoneBot2 还有丰富的官方以及第三方现成的插件供大家使用:
106109

@@ -110,7 +113,9 @@ NoneBot2 的驱动框架 `Driver` 以及通信协议 `Adapter` 均可**自定义
110113
nb plugin install nonebot_plugin_docs
111114
```
112115

113-
或者尝试 [文档镜像](https://nonebot2-vercel-mirror.vercel.app)
116+
或者尝试以下镜像:
117+
- [文档镜像(中国境内)](https://nb2.baka.icu)
118+
- [文档镜像(vercel)](https://nonebot2-vercel-mirror.vercel.app)
114119

115120
- 其他插件请查看 [商店](https://v2.nonebot.dev/store.html)
116121

archive/2.0.0a10/advanced/scheduler.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
## 从 NoneBot v1 迁移
88

9-
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [插件广场](https://v2.nonebot.dev/plugin-store.html) 中找到它。
9+
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [插件广场](https://v2.nonebot.dev/store.html) 中找到它。
1010

1111
相比于 `nonebot` v1 ,只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
1212

archive/2.0.0a13.post1/advanced/scheduler.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
77
## 从 NoneBot v1 迁移
88

9-
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [插件广场](https://v2.nonebot.dev/plugin-store.html) 中找到它。
9+
`APScheduler` 作为 `nonebot` v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。`nonebot2` 已将 `APScheduler` 独立为 `nonebot_plugin_apscheduler` 插件,你可以在 [插件广场](https://v2.nonebot.dev/store.html) 中找到它。
1010

11-
相比于 `nonebot` v1,`nonebot` v2只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
11+
相比于 `nonebot` v1,`nonebot` v2 只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
1212

1313
## 安装插件
1414

archive/2.0.0a14/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
home: true
3+
heroImage: /logo.png
4+
tagline: 跨平台 Python 异步机器人框架
5+
actionText: 开始使用
6+
actionLink: guide/
7+
features:
8+
- title: 简洁
9+
details: 提供极其简洁易懂的 API,使你可以毫无压力地开始验证你的绝佳创意,只需编写最少量的代码,即可实现丰富的功能。
10+
- title: 易于扩展
11+
details: 精心设计的消息处理流程使得你可以很方便地将原型扩充为具有大量实用功能的完整聊天机器人,并持续保证扩展性。
12+
- title: 高性能
13+
details: 采用异步 I/O,利用 WebSocket 进行通信,以获得极高的性能;同时,支持使用多账号同时接入,减少业务宕机的可能。
14+
footer: MIT Licensed | Copyright © 2018 - 2021 NoneBot Team
15+
---
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# 深入
2+
3+
## 它如何工作?
4+
5+
如同[概览](../guide/README.md)所言:
6+
7+
> NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的事件进行解析和处理,并以插件化的形式,按优先级分发给事件所对应的事件响应器,来完成具体的功能。
8+
9+
`Nonebot2` 是一个可以对机器人上报的事件进行处理并完成具体功能的机器人框架,在这里,我们将简要讲述它的工作内容。
10+
11+
**便捷起见,以下内容对 `Nonebot2` 会被称为 `nonebot`,与 `Nonebot2` 交互的机器人实现会被称为 `协议端`**
12+
13+
在实际应用中,`nonebot` 会充当一个高性能,轻量级的 Python 微服务框架。协议端可以通过 `http`, `websocket` 等方式与之通信,这个通信往往是双向的:一方面,协议端可以上报数据给 `nonebot``nonebot` 会处理数据并返回响应给协议端;另一方面,`nonebot` 可以主动推送数据给协议端。而 `nonebot` 便是围绕双向通信进行工作的。
14+
15+
在开始工作之前,`nonebot` 需要进行准备工作:
16+
17+
1. **运行 `nonebot.init` 初始化函数**,它会读取配置文件,并初始化 `nonebot` 和后端驱动 `driver` 对象。
18+
2. **注册协议适配器 `adapter`**
19+
3. **加载插件**
20+
21+
准备工作完成后,`nonebot` 会利用 `uvicorn` 启动,并运行 `on_startup` 钩子函数。
22+
23+
随后,倘若一个协议端与 `nonebot` 进行了连接,`nonebot` 的后端驱动 `driver` 就会将 `adapter` 实例化为 `bot``nonebot` 便会利用 `bot` 开始工作,它的工作内容分为两个方面:
24+
25+
1. **事件处理**`bot` 会将协议端上报的数据转化为 `事件`(`Event`),之后 `nonebot` 会根据一套既定流程来处理 `事件`
26+
27+
2. **调用 `API`**, 在**事件处理**的过程中,`nonebot` 可以通过 `bot` 调用协议端指定的 `API` 来获取更多数据,或者反馈响应给协议端; `nonebot` 也可以通过调用 `API` 向协议端主动请求数据或者主动推送数据。
28+
29+
**指南**模块, 我们已经叙述了[如何配置 nonebot](../guide/basic-configuration.md), [如何注册协议适配器](../guide/getting-started.md)[如何加载插件](../guide/loading-a-plugin.md), 在这里便不再赘述。
30+
31+
下面,我们将对**事件处理****调用 API**进行说明。
32+
33+
## 事件处理
34+
35+
我们可以先看事件处理的流程图:
36+
37+
![handle-event](../guide/images/Handle-Event.png)
38+
39+
在流程图里,我们可以看到,`nonebot` 会有三个阶段来处理事件:
40+
41+
1. **driver 处理上报数据**
42+
2. **adapter 处理原始数据**
43+
3. **nonebot 处理 Event**
44+
45+
我们将顺序说明这三个阶段。其中,会将第三个阶段拆分成**概念解释****处理 Event****特殊异常处理**三个部分来说明。
46+
47+
### driver 处理上报数据
48+
49+
1. 协议端会通过 `websocket` 或者 `http` 等方式与 `nonebot` 的后端驱动 `driver` 连接,`driver` 会根据之前注册的 `adapter` 和配置文件的内容来进行鉴权,从而获得这个连接的唯一识别 id `self-id`,随后 `adapter` 就会利用 `self-id` 实例化为 `bot` 对象。
50+
51+
::: tip
52+
需要注意的是,如果协议端通过 `websocket``nonebot` 连接,这个步骤只会在建立连接时进行,并在之后运行 `on_bot_connect` 钩子函数;通过 `http` 方式连接时,会在协议端每次上报数据时都进行这个步骤。
53+
:::
54+
55+
::: warning
56+
连接之前必须要注册 `adapter`
57+
:::
58+
59+
::: warning
60+
`self-id` 是帐号的唯一识别 ID,这意味着不能出现相同的 `self-id`
61+
:::
62+
63+
2. `driver` 会将接收到的数据转交给 `bot` 对象进一步处理。
64+
65+
### adapter 处理原始数据
66+
67+
1. `bot` 会利用事先定义好的 `Event Model` 对上报的数据进行分析处理,将数据转化为 `nonebot` 可以处理的 `Event` 对象。
68+
69+
::: tip
70+
`adapter` 在转换数据格式的同时可以进行一系列的特殊操作,例如 `CQHTTP` 会对 `reply` 信息进行提取。
71+
:::
72+
73+
2. `Event` 会传入 `nonebot` 做进一步处理。
74+
75+
### nonebot 处理 Event
76+
77+
在讲述这个阶段之前,我们需要先对几个概念进行解释。
78+
79+
#### 概念解释
80+
81+
1. **hook**,或者说**钩子函数**,它们可以在 `nonebot` 处理 `Event` 的不同时刻进行拦截,修改或者扩展,在 `nonebot` 中,钩子函数分为 `事件预处理hook``运行预处理hook``运行后处理hook``事件后处理hook`
82+
83+
::: tip
84+
关于`hook`的更多信息,可以查阅[这里](./runtime-hook.md)
85+
:::
86+
87+
2. **Matcher****matcher**,在**指南**中,我们讲述了[如何注册事件响应器](../guide/creating-a-matcher),这里的事件响应器或者说 `Matcher` 并不是一个具体的实例 `instance`,而是一个具有特定属性的类 `class`。只有当 `Matcher` **响应事件**时,才会实例化为具体的 `instance`,也就是 `matcher``matcher` 可以认为是 `nonebot` 处理 `Event` 的基本单位,运行 `matcher``nonebot`工作的主要内容。
88+
89+
3. **handler**,或者说**事件处理函数**, 它们可以认为是 `nonebot` 处理 `Event` 的最小单位。在不考虑 `hook` 的情况下,**运行 matcher 就是顺序运行 matcher.handlers**,这句话换种表达方式就是,`handler` 只有添加到 `matcher.handlers` 时,才可以参与到 `nonebot` 的工作中来。
90+
91+
::: tip
92+
如何让 `handler` 添加到 `matcher.handlers`
93+
94+
一方面,我们可以参照[这里](../guide/creating-a-handler)利用装饰器来添加;另一方面,我们在用 `on()` 或者 `on_*()` 注册事件响应器时,可以添加 `handlers=[handler1, handler2, ...]` 这样的关键词参数来添加。
95+
:::
96+
97+
#### 处理 Event
98+
99+
1. **执行事件预处理 hook**`nonebot` 接收到 `Event` 后,会传入到 `事件预处理hook` 中进行处理。
100+
101+
::: warning
102+
需要注意的是,执行多个 `事件预处理hook` 时并无顺序可言,它们是**并行运行**的。这个原则同样适用于其他的 `hook`
103+
:::
104+
105+
2. **按优先级升序选出同一优先级的 Matcher**`nonebot` 提供了一个全局字典 `matchers`,这个字典的 `key` 是优先级 `priority``value` 是一个 `list`,里面存放着同一优先级的 `Matcher`。在注册 `Matcher` 时,它和优先级 `priority` 会添加到里面。
106+
107+
在执行 `事件预处理hook` 后,`nonebot` 会对 `matchers``key` 升序排序并选择出当前最小优先级的 `Matcher`
108+
109+
3. **根据 Matcher 定义的 Rule, Permission 判断是否运行**,在选出 `Matcher` 后,`nonebot` 会将 `bot``Event` 传入到 `Matcher.check_rule``Matcher.check_perm` 两个函数中,两个函数分别对 Matcher 定义的 Rule, Permission 进行 check,当 check 通过后,这个 `Matcher` 就会响应事件。但是当同一个优先级的所有 `Matcher` 均没有响应时,`nonebot` 会返回到上一个步骤,选择出下一优先级的 `Matcher`
110+
111+
4. **实例化 matcher 并执行运行预处理 hook**,当 `Matcher` 响应事件后,它便会实例化为 `matcher`,并执行 `运行预处理hook`
112+
113+
5. **顺序运行 matcher 的所有 handlers**`运行预处理hook` 执行完毕后,便会运行 `matcher`,也就是**顺序运行**它的 `handlers`
114+
115+
::: tip
116+
`matcher` 运行 `handlers` 的顺序是: 先运行该 `matcher` 的类 `Matcher` 注册时添加的 `handlers`(如果有的话),再按照装饰器装饰顺序运行装饰的 `handlers`
117+
:::
118+
119+
6. **执行运行后处理 hook**`matcher``handlers` 运行完毕后,会执行 `运行后处理hook`
120+
121+
7. **判断是否停止事件传播**`nonebot` 会根据当前优先级所有 `matcher``block` 参数或者 `StopPropagation` 异常判断是否停止传播 `Event`,如果事件没有停止传播,`nonebot` 便会返回到第 2 步, 选择出下一优先级的 `Matcher`
122+
123+
8. **执行事件后处理 hook**,在 `Event` 停止传播或执行完所有响应的 `Matcher` 后,`nonebot` 会执行 `事件后处理hook`
124+
125+
`事件后处理hook` 执行完毕后,当前`Event`的处理周期就顺利结束了。
126+
127+
#### 特殊异常处理
128+
129+
在这个阶段,`nonebot` 规定了几个特殊的异常,当 `nonebot` 捕获到它们时,会用特定的行为来处理它们。
130+
131+
1. **IgnoredException**
132+
133+
这个异常可以在 `事件预处理hook``运行预处理hook` 抛出。
134+
135+
`事件预处理hook` 抛出它时,`nonebot` 会忽略当前的 `Event`,不进行处理。
136+
137+
`运行预处理hook` 抛出它时,`nonebot` 会忽略当前的 `matcher`,结束当前 `matcher` 的运行。
138+
139+
::: warning
140+
`hook` 需要抛出这个异常时,要写明原因。
141+
:::
142+
143+
2. **PausedException**
144+
145+
这个异常可以在 `handler` 中由 `Matcher.pause` 抛出。
146+
147+
`nonebot` 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行,并将后续的 `handler` 交给一个临时 `Matcher` 来响应当前交互用户的下一个消息事件,当临时 `Matcher` 响应时,临时 `Matcher` 会运行后续的 handlers。
148+
149+
3. **RejectedException**
150+
151+
这个异常可以在 `handler` 中由 `Matcher.reject` 抛出。
152+
153+
`nonebot` 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行,并将当前 handler 和后续 `handler` 交给一个临时 `Matcher` 来响应当前交互用户的下一个消息事件,当临时 `Matcher` 响应时,临时 `Matcher` 会运行当前 `handler` 和后续的 `handler`
154+
155+
4. **FinishedException**
156+
157+
这个异常可以在 `handler` 中由 `Matcher.finish` 抛出。
158+
159+
`nonebot` 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行。
160+
161+
5. **StopPropagation**
162+
163+
这个异常一般会在执行 `运行后处理hook` 后抛出。
164+
165+
`nonebot` 捕获到它时, 会停止传播当前 `Event`,不再寻找下一优先级的 `Matcher`,直接执行 `事件后处理hook`
166+
167+
## 调用 API
168+
169+
`nonebot` 可以通过 `bot` 来调用 `API``API` 可以向协议端发送数据,也可以向协议端请求更多的数据。
170+
171+
::: tip
172+
不同 `adapter` 规定了不同的 API,对应的 API 列表请参照协议规范。
173+
:::
174+
175+
一般来说,我们可以用 `bot.*` 来调用 `API`(\*`API``action` 或者 `endpoint`)。
176+
177+
对于发送消息而言,一方面可以调用既有的 API;另一方面 `nonebot` 实现了两个便捷方法,`bot.send(event, message, **kwargs)` 方法和可以在 `handler` 中使用的 `Matcher.send(message, **kwargs)` 方法,来向事件主体发送消息。

0 commit comments

Comments
 (0)