diff --git a/website/src/pages/changelog.md b/website/src/pages/changelog.md
index 446cb1fb..f5f72907 100644
--- a/website/src/pages/changelog.md
+++ b/website/src/pages/changelog.md
@@ -5,7 +5,7 @@ toc_max_heading_level: 2
# 更新日志
-## 最近更新
+## v2.0.0-beta.5
### 🚀 新功能
diff --git a/website/versioned_docs/version-2.0.0-beta.5/README.md b/website/versioned_docs/version-2.0.0-beta.5/README.md
new file mode 100644
index 00000000..9e864dff
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/README.md
@@ -0,0 +1,49 @@
+---
+sidebar_position: 0
+id: index
+slug: /
+---
+
+# 概览
+
+NoneBot2 是一个现代、跨平台、可扩展的 Python 聊天机器人框架,它基于 Python 的类型注解和异步特性,能够为你的需求实现提供便捷灵活的支持。
+
+需要注意的是,NoneBot2 仅支持 **Python 3.7.3 以上版本**
+
+## 特色
+
+### 异步优先
+
+NoneBot2 基于 Python [asyncio](https://docs.python.org/3/library/asyncio.html) 编写,并在异步机制的基础上进行了一定程度的同步函数兼容。
+
+### 完整的类型注解
+
+NoneBot2 参考 [PEP 484](https://www.python.org/dev/peps/pep-0484/) 等 PEP 完整实现了类型注解,通过 `pyright`/`pylance` 检查。配合编辑器的类型推导功能,能将绝大多数的 Bug 杜绝在编辑器中([编辑器支持](./start/editor-support))。
+
+### 开箱即用
+
+NoneBot2 提供了使用便捷、具有交互式功能的命令行工具--`nb-cli`,使得初次接触 NoneBot2 时更容易上手。详细使用方法请参考各文档章节以及[使用脚手架](./start/nb-cli)。
+
+### 插件系统
+
+插件系统是 NoneBot2 的核心,通过它可以实现机器人的模块化以及功能扩展,便于维护和管理。
+
+### 依赖注入系统
+
+NoneBot2 采用了一套自行定义的依赖注入系统,可以让事件的处理过程更加的简洁、清晰,增加代码的可读性,减少代码冗余。
+
+#### 什么是依赖注入
+
+[**“依赖注入”**](https://zh.m.wikipedia.org/wiki/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC)意思是,在编程中,有一种方法可以让你的代码声明它工作和使用所需要的东西,即**“依赖”**。
+
+系统(在这里是指 NoneBot2)将负责做任何需要的事情,为你的代码提供这些必要依赖(即**“注入”**依赖性)
+
+这在你有以下情形的需求时非常有用:
+
+- 这部分代码拥有共享的逻辑(同样的代码逻辑多次重复)
+- 共享数据库以及网络请求连接会话
+ - 比如 `httpx.AsyncClient`、`aiohttp.ClientSession` 和 `sqlalchemy.Session`
+- 用户权限检查以及认证
+- 还有更多...
+
+它在完成上述工作的同时,还能尽量减少代码的耦合和重复
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/README.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/README.md
new file mode 100644
index 00000000..a96efe70
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/README.md
@@ -0,0 +1,207 @@
+---
+id: index
+sidebar_position: 0
+description: 深入了解 NoneBot2 运行机制
+slug: /advanced/
+
+options:
+ menu:
+ weight: 10
+ category: advanced
+---
+
+# 深入
+
+:::danger 警告
+进阶部分尚未更新完成
+:::
+
+## 它如何工作?
+
+如同[概览](../README.md)所言:
+
+> NoneBot2 是一个可扩展的 Python 异步机器人框架,它会对机器人收到的事件进行解析和处理,并以插件化的形式,按优先级分发给事件所对应的事件响应器,来完成具体的功能。
+
+NoneBot2 是一个可以对机器人上报的事件进行处理并完成具体功能的机器人框架,在这里,我们将简要讲述它的工作内容。
+
+**便捷起见,以下内容对 NoneBot2 会被称为 NoneBot,与 NoneBot2 交互的机器人实现会被称为协议端**。
+
+在实际应用中,NoneBot 会充当一个高性能,轻量级的 Python 微服务框架。协议端可以通过 http、websocket 等方式与之通信,这个通信往往是双向的:一方面,协议端可以上报数据给 NoneBot,NoneBot 会处理数据并返回响应给协议端;另一方面,NoneBot 可以主动推送数据给协议端。而 NoneBot 便是围绕双向通信进行工作的。
+
+在开始工作之前,NoneBot 需要进行准备工作:
+
+1. **运行 `nonebot.init` 初始化函数**,它会读取配置文件,并初始化 NoneBot 和后端驱动 `Driver` 对象。
+2. **注册协议适配器 `Adapter`**。
+3. **加载插件**。
+
+准备工作完成后,NoneBot 会利用 uvicorn 启动,并运行 `on_startup` 钩子函数。
+
+随后,倘若一个协议端与 NoneBot 进行了连接,NoneBot 的后端驱动 `Driver` 就会将数据交给 `Adapter`,然后会实例化 `Bot`,NoneBot 便会利用 `Bot` 开始工作,它的工作内容分为两个方面:
+
+1. **事件处理**,`Bot` 会将协议端上报的数据转化为 `Event`(事件),之后 NoneBot 会根据一套既定流程来处理事件。
+
+2. **调用 `API`**,在**事件处理**的过程中,NoneBot 可以通过 `Bot` 调用协议端指定的 `API` 来获取更多数据,或者反馈响应给协议端;NoneBot 也可以通过调用 `API` 向协议端主动请求数据或者主动推送数据。
+
+在**指南**模块,我们已经叙述了[如何配置 NoneBot](../tutorial/configuration.md)、[如何注册协议适配器](../tutorial/register-adapter.md)以及[如何加载插件](../tutorial/plugin/load-plugin.md),这里便不再赘述。
+
+下面,我们将对**事件处理**,**调用 API** 进行说明。
+
+## 事件处理
+
+我们可以先看事件处理的流程图:
+
+![handle-event](./images/Handle-Event.png)
+
+在流程图里,我们可以看到,NoneBot 会有三个阶段来处理事件:
+
+1. **Driver 接收上报数据**
+2. **Adapter 处理原始数据**
+3. **NoneBot 处理 Event**
+
+我们将顺序说明这三个阶段。其中,会将第三个阶段拆分成**概念解释**,**处理 Event**,**特殊异常处理**三个部分来说明。
+
+### Driver 接收上报数据
+
+1. 协议端会通过 websocket 或 http 等方式与 NoneBot 的后端驱动 `Driver` 连接,协议端上报数据后,`Driver` 会将原始数据交给 `Adapter` 处理。
+
+:::warning
+连接之前必须要注册 `Adapter`
+:::
+
+### Adapter 处理原始数据
+
+1. `Adapter` 检查授权许可,并获取 `self-id` 作为唯一识别 id 。
+
+:::tip
+如果协议端通过 websocket 上报数据,这个步骤只会在建立连接时进行,并在之后运行 `on_bot_connect` 钩子函数;通过 http 方式连接时,会在协议端每次上报数据时都进行这个步骤。
+:::
+
+:::warning
+`self-id` 是帐号的唯一识别 ID ,这意味着不能出现相同的 `self-id`。
+:::
+
+2. 根据 `self-id` 实例化 `Adapter` 相应的 `Bot` 。
+
+3. 根据 `Event Model` 将原始数据转化为 NoneBot 可以处理的 `Event` 对象。
+
+:::tip
+`Adapter` 在转换数据格式的同时可以进行一系列的特殊操作,例如 OneBot 适配器会对 reply 信息进行提取。
+:::
+
+4. `Bot` 和 `Event` 交由 NoneBot 进一步处理。
+
+### NoneBot 处理 Event
+
+在讲述这个阶段之前,我们需要先对几个概念进行解释。
+
+#### 概念解释
+
+1. **hook** ,或者说**钩子函数**,它们可以在 NoneBot 处理 `Event` 的不同时刻进行拦截,修改或者扩展,在 NoneBot 中,事件钩子函数分为`事件预处理 hook`、`运行预处理 hook`、`运行后处理 hook` 和`事件后处理 hook`。
+
+:::tip
+关于 `hook` 的更多信息,可以查阅[这里](./runtime-hook.md)。
+:::
+
+2. **Matcher** 与 **matcher**,在**指南**中,我们讲述了[如何注册事件响应器](../tutorial/plugin/create-matcher.md),这里的事件响应器或者说 `Matcher` 并不是一个具体的实例 `instance`,而是一个具有特定属性的类 `class`。只有当 `Matcher` **响应事件**时,才会实例化为具体的 `instance`,也就是 `matcher` 。`matcher` 可以认为是 NoneBot 处理 `Event` 的基本单位,运行 `matcher` 是 NoneBot 工作的主要内容。
+
+3. **handler**,或者说**事件处理函数**,它们可以认为是 NoneBot 处理 `Event` 的最小单位。在不考虑 `hook` 的情况下,**运行 matcher 就是顺序运行 matcher.handlers**,这句话换种表达方式就是,`handler` 只有添加到 `matcher.handlers` 时,才可以参与到 NoneBot 的工作中来。
+
+:::tip
+如何让 `handler` 添加到 `matcher.handlers`?
+
+一方面,我们可以参照[这里](../tutorial/plugin/create-handler.md)利用装饰器来添加;另一方面,我们在用 `on()` 或者 `on_*()` 注册事件响应器时,可以添加 `handlers=[handler1, handler2, ...]` 这样的关键词参数来添加。
+:::
+
+#### 处理 Event
+
+1. **执行事件预处理 hook**, NoneBot 接收到 `Event` 后,会传入到 `事件预处理 hook` 中进行处理。
+
+:::warning
+需要注意的是,执行多个 `事件预处理 hook` 时并无顺序可言,它们是**并发运行**的。这个原则同样适用于其他的 `hook`。
+:::
+
+2. **按优先级升序选出同一优先级的 Matcher**,NoneBot 提供了一个全局字典 `matchers`,这个字典的 `key` 是优先级 `priority`,`value` 是一个 `list`,里面存放着同一优先级的 `Matcher`。在注册 `Matcher` 时,它和优先级 `priority` 会添加到里面。
+
+ 在执行 `事件预处理 hook` 后,NoneBot 会对 `matchers` 的 `key` 升序排序并选择出当前最小优先级的 `Matcher`。
+
+3. **根据 Matcher 定义的 Rule、Permission 判断是否运行**,在选出 `Matcher` 后,NoneBot 会将 `bot`,`Event` 传入到 `Matcher.check_rule` 和 `Matcher.check_perm` 两个函数中,两个函数分别对 Matcher 定义的 `Rule`、`Permission` 进行 check,当 check 通过后,这个 `Matcher` 就会响应事件。当同一个优先级的所有 `Matcher` 均没有响应时,NoneBot 会返回到上一个步骤,选择出下一优先级的 `Matcher`。
+
+4. **实例化 matcher 并执行运行预处理 hook**,当 `Matcher` 响应事件后,它便会实例化为 `matcher`,并执行 `运行预处理 hook`。
+
+5. **顺序运行 matcher 的所有 handlers**,`运行预处理 hook` 执行完毕后,便会运行 `matcher`,也就是**顺序运行**它的 `handlers`。
+
+:::tip
+`matcher` 运行 `handlers` 的顺序是:先运行该 `matcher` 的类 `Matcher` 注册时添加的 `handlers`(如果有的话),再按照装饰器装饰顺序运行装饰的 `handlers`。
+:::
+
+6. **执行运行后处理 hook**,`matcher` 的 `handlers` 运行完毕后,会执行 `运行后处理 hook`。
+
+7. **判断是否停止事件传播**,NoneBot 会根据当前优先级所有 `matcher` 的 `block` 参数或者 `StopPropagation` 异常判断是否停止传播 `Event`,如果事件没有停止传播,NoneBot 便会返回到第 2 步, 选择出下一优先级的 `Matcher`。
+
+8. **执行事件后处理 hook**,在 `Event` 停止传播或执行完所有响应的 `Matcher` 后,NoneBot 会执行 `事件后处理 hook`。
+
+ 当 `事件后处理 hook` 执行完毕后,当前 `Event` 的处理周期就顺利结束了。
+
+#### 特殊异常处理
+
+在这个阶段,NoneBot 规定了几个特殊的异常,当 NoneBot 捕获到它们时,会用特定的行为来处理它们。
+
+1. **IgnoredException**
+
+ 这个异常可以在 `事件预处理 hook` 和 `运行预处理 hook` 抛出。
+
+ 当 `事件预处理 hook` 抛出它时,NoneBot 会忽略当前的 `Event`,不进行处理。
+
+ 当 `运行预处理 hook` 抛出它时,NoneBot 会忽略当前的 `matcher`,结束当前 `matcher` 的运行。
+
+:::warning
+当 `hook` 需要抛出这个异常时,要写明原因。
+:::
+
+2. **PausedException**
+
+ 这个异常可以在 `handler` 中由 `Matcher.pause` 抛出。
+
+ 当 NoneBot 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行,并将后续的 `handler` 交给一个临时 `Matcher` 来响应当前交互用户的下一个消息事件,当临时 `Matcher` 响应时,临时 `Matcher` 会运行后续的 `handler`。
+
+3. **RejectedException**
+
+ 这个异常可以在 `handler` 中由 `Matcher.reject` 抛出。
+
+ 当 NoneBot 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行,并将当前 handler 和后续 `handler` 交给一个临时 `Matcher` 来响应当前交互用户的下一个消息事件,当临时 `Matcher` 响应时,临时 `Matcher` 会运行当前 `handler` 和后续的 `handler` 。
+
+4. **FinishedException**
+
+ 这个异常可以在 `handler` 中由 `Matcher.finish` 抛出。
+
+ 当 NoneBot 捕获到它时,会停止运行当前 `handler` 并结束当前 `matcher` 的运行。
+
+5. **StopPropagation**
+
+ 这个异常一般会在执行 `运行后处理 hook` 后抛出。
+
+ 当 NoneBot 捕获到它时, 会停止传播当前 `Event` ,不再寻找下一优先级的 `Matcher` ,直接执行 `事件后处理 hook` 。
+
+## 调用 API
+
+NoneBot 可以通过 `bot` 来调用 `API`,`API` 可以向协议端发送数据,也可以向协议端请求更多的数据。
+
+NoneBot 调用 `API` 会有如下过程:
+
+1. 调用 `calling_api_hook` 预处理钩子。
+
+2. `adapter` 将信息处理为原始数据,并转交 `driver`,`driver` 交给协议端处理。
+
+3. `driver` 接收协议端的结果,交给`adapter` 处理之后将结果反馈给 NoneBot 。
+
+4. 调用 `called_api_hook` 后处理钩子。
+
+在调用 `API` 时同样规定了特殊的异常,叫做 `MockApiException` 。该异常会由预处理钩子和后处理钩子触发,当预处理钩子触发时,NoneBot 会跳过之后的调用过程,直接执行后处理钩子。
+
+:::tip
+不同 `adapter` 规定了不同的 API,对应的 API 列表请参照协议规范。
+:::
+
+一般来说,我们可以用 `bot.*` 来调用 `API`(\*是 `API` 的 `action` 或者 `endpoint`)。
+
+对于发送消息而言,一方面可以调用既有的 `API` ;另一方面 NoneBot 实现了两个便捷方法,`bot.send(event, message, **kwargs)` 方法和可以在 `handler` 中使用的 `Matcher.send(message, **kwargs)` 方法,来向事件主体发送消息。
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/di/_category_.json b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/_category_.json
new file mode 100644
index 00000000..60e7734e
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "依赖注入",
+ "position": 5
+}
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/di/dependency-injection.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/dependency-injection.md
new file mode 100644
index 00000000..66645709
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/dependency-injection.md
@@ -0,0 +1,243 @@
+---
+sidebar_position: 1
+description: 依赖注入简介
+
+options:
+ menu:
+ weight: 60
+ category: advanced
+---
+
+# 简介
+
+受 [FastAPI](https://fastapi.tiangolo.com/tutorial/dependencies/) 启发,NoneBot 同样编写了一个简易的依赖注入模块,使得开发者可以通过事件处理函数参数的类型标注来自动注入依赖。
+
+## 什么是依赖注入?
+
+[依赖注入](https://zh.wikipedia.org/wiki/%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5)
+
+> 在软件工程中,**依赖注入**(dependency injection)的意思为,给予调用方它所需要的事物。 “依赖”是指可被方法调用的事物。依赖注入形式下,调用方不再直接使用“依赖”,取而代之是“注入” 。“注入”是指将“依赖”传递给调用方的过程。在“注入”之后,调用方才会调用该“依赖。 传递依赖给调用方,而不是让让调用方直接获得依赖,这个是该设计的根本需求。
+
+依赖注入往往起到了分离依赖和调用方的作用,这样一方面能让代码更为整洁可读,一方面可以提升代码的复用性。
+
+## 使用依赖注入
+
+以下通过一个简单的例子来说明依赖注入的使用方法:
+
+```python {2,7-8,11}
+from nonebot import on_command
+from nonebot.params import Depends # 1.引用 Depends
+from nonebot.adapters.onebot.v11 import MessageEvent
+
+test = on_command("123")
+
+async def depend(event: MessageEvent): # 2.编写依赖函数
+ return {"uid": event.get_user_id(), "nickname": event.sender.nickname}
+
+@test.handle()
+async def _(x: dict = Depends(depend)): # 3.在事件处理函数里声明依赖项
+ print(x["uid"], x["nickname"])
+```
+
+如注释所言,可以用三步来说明依赖注入的使用过程:
+
+1. 引用 `Depends` 。
+
+2. 编写依赖函数。依赖函数和普通的事件处理函数并无区别,同样可以接收 `bot`, `event`, `state` 等参数,你可以把它当作一个普通的事件处理函数,但是去除了装饰器(没有使用 `matcher.handle()` 等来装饰),并且可以返回任何类型的值。
+
+ 在这里我们接受了 `event`,并以 `onebot` 的 `MessageEvent` 作为类型标注,返回一个新的字典,包括 `uid` 和 `nickname` 两个键值。
+
+3. 在事件处理函数中声明依赖项。依赖项必须要 `Depends` 包裹依赖函数作为默认值。
+
+:::tip
+请注意,参数 `x` 的类型标注将会影响到事件处理函数的运行,与类型标注不符的值将会导致事件处理函数被跳过。
+:::
+
+:::tip
+事实上,bot、event、state 它们本身只是依赖注入的一个特例,它们无需声明这是依赖即可注入。
+:::
+
+虽然声明依赖项的方式和其他参数如 `bot`, `event` 并无二样,但他的参数有一些限制,必须是**可调用对象**,函数自然是可调用对象,类和生成器也是,我们会在接下来的小节说明。
+
+一般来说,当接收到事件时,`NoneBot2` 会进行以下处理:
+
+1. 准备依赖函数所需要的参数。
+2. 调用依赖函数并获得返回值。
+3. 将返回值作为事件处理函数中的参数值传入。
+
+## 依赖缓存
+
+在使用 `Depends` 包裹依赖函数时,有一个参数 `use_cache` ,它默认为 `True` ,这个参数会决定 `Nonebot2` 在依赖注入的处理中是否使用缓存。
+
+```python {11}
+import random
+from nonebot import on_command
+from nonebot.params import Depends
+
+test = on_command("123")
+
+async def always_run():
+ return random.randint(1, 100)
+
+@test.handle()
+async def _(x: int = Depends(always_run, use_cache=False)):
+ print(x)
+```
+
+:::tip
+缓存是针对单次事件处理来说的,在事件处理中 `Depends` 第一次被调用时,结果存入缓存,在之后都会直接返回缓存中的值,在事件处理结束后缓存就会被清除。
+:::
+
+当使用缓存时,依赖注入会这样处理:
+
+1. 查询缓存,如果缓存中有相应的值,则直接返回。
+2. 准备依赖函数所需要的参数。
+3. 调用依赖函数并获得返回值。
+4. 将返回值存入缓存。
+5. 将返回值作为事件处理函数中的参数值传入。
+
+## 同步支持
+
+我们在编写依赖函数时,可以简单地用同步函数,`NoneBot2` 的内部流程会进行处理:
+
+```python {2,8-9,12}
+from nonebot.log import logger
+from nonebot.params import Depends # 1.引用 Depends
+from nonebot import on_command, on_message
+from nonebot.adapters.onebot.v11 import MessageEvent
+
+test = on_command("123")
+
+def depend(event: MessageEvent): # 2.编写同步依赖函数
+ return {"uid": event.get_user_id(), "nickname": event.sender.nickname}
+
+@test.handle()
+async def _(x: dict = Depends(depend)): # 3.在事件处理函数里声明依赖项
+ print(x["uid"], x["nickname"])
+```
+
+## Class 作为依赖
+
+我们可以看下面的代码段:
+
+```python
+class A:
+ def __init__(self):
+ pass
+a = A()
+```
+
+在我们实例化类 `A` 的时候,其实我们就在**调用**它,类本身也是一个**可调用对象**,所以类可以被 `Depends` 包裹成为依赖项。
+
+因此我们对第一节的代码段做一下改造:
+
+```python {2,7-10,13}
+from nonebot import on_command
+from nonebot.params import Depends # 1.引用 Depends
+from nonebot.adapters.onebot.v11 import MessageEvent
+
+test = on_command("123")
+
+class DependClass: # 2.编写依赖类
+ def __init__(self, event: MessageEvent):
+ self.uid = event.get_user_id()
+ self.nickname = event.sender.nickname
+
+@test.handle()
+async def _(x: DependClass = Depends(DependClass)): # 3.在事件处理函数里声明依赖项
+ print(x.uid, x.nickname)
+```
+
+依然可以用三步说明如何用类作为依赖项:
+
+1. 引用 `Depends` 。
+2. 编写依赖类。类的 `__init__` 函数可以接收 `bot`, `event`, `state` 等参数,在这里我们接受了 `event`,并以 `onebot` 的 `MessageEvent` 作为类型标注。
+3. 在事件处理函数中声明依赖项。当用类作为依赖项时,它会是一个对应的实例,在这里 `x` 就是 `DependClass` 实例。
+
+### 另一种依赖项声明方式
+
+当使用类作为依赖项时,`Depends` 的参数可以为空,`NoneBot2` 会根据参数的类型标注进行推断并进行依赖注入。
+
+```python
+@test.handle()
+async def _(x: DependClass = Depends()): # 在事件处理函数里声明依赖项
+ print(x.uid, x.nickname)
+```
+
+## 生成器作为依赖
+
+:::warning
+`yield` 语句只能写一次,否则会引发异常。
+如果对此有疑问并想探究原因,可以看 [contextmanager](https://docs.python.org/zh-cn/3/library/contextlib.html#contextlib.contextmanager) 和 [asynccontextmanager](https://docs.python.org/zh-cn/3/library/contextlib.html#contextlib.asynccontextmanager) 文档,实际上,`Nonebot2` 的内部就使用了这两个装饰器。
+:::
+
+:::tips
+生成器是 `Python` 高级特性,如果你对此处文档感到疑惑那说明暂时你还用不上这个功能。
+:::
+
+与 `FastAPI` 一样,`NoneBot2` 的依赖注入支持依赖项在事件处理结束后进行一些额外的工作,比如数据库 session 或者网络 IO 的关闭,互斥锁的解锁等等。
+
+要实现上述功能,我们可以用生成器函数作为依赖项,我们用 `yield` 关键字取代 `return` 关键字,并在 `yield` 之后进行额外的工作。
+
+我们可以看下述代码段, 使用 `httpx.AsyncClient` 异步网络 IO:
+
+```python {3,7-10,13}
+import httpx
+from nonebot import on_command
+from nonebot.params import Depends # 1.引用 Depends
+
+test = on_command("123")
+
+async def get_client(): # 2.编写异步生成器函数
+ async with httpx.AsyncClient() as client:
+ yield client
+ print("调用结束")
+
+@test.handle()
+async def _(x: httpx.AsyncClient = Depends(get_client)): # 3.在事件处理函数里声明依赖项
+ resp = await x.get("https://v2.nonebot.dev")
+ # do something
+```
+
+我们用 `yield` 代码段作为生成器函数的“返回”,在事件处理函数里用返回出来的 `client` 做自己需要的工作。在 `NoneBot2` 结束事件处理时,会执行 `yield` 之后的代码。
+
+## 创造可调用对象作为依赖
+
+:::tips
+魔法方法 `__call__` 是 `Python` 高级特性,如果你对此处文档感到疑惑那说明暂时你还用不上这个功能。
+:::
+
+在 `Python` 的里,类的 `__call__` 方法会让类的实例变成**可调用对象**,我们可以利用这个魔法方法做一个简单的尝试:
+
+```python{3,9-14,16,19}
+from typing import Type
+from nonebot.log import logger
+from nonebot.params import Depends # 1.引用 Depends
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
+
+test = on_command("123")
+
+class EventChecker: # 2.编写需要的类
+ def __init__(self, EventClass: Type[MessageEvent]):
+ self.event_class = EventClass
+
+ def __call__(self, event: MessageEvent) -> bool:
+ return isinstance(event, self.event_class)
+
+checker = EventChecker(GroupMessageEvent) # 3.将类实例化
+
+@test.handle()
+async def _(x: bool = Depends(checker)): # 4.在事件处理函数里声明依赖项
+ if x:
+ print("这是群聊消息")
+ else:
+ print("这不是群聊消息")
+```
+
+这是判断 `onebot` 的消息事件是不是群聊消息事件的一个例子,我们可以用四步来说明这个例子:
+
+1. 引用 `Depends` 。
+2. 编写需要的类。类的 `__init__` 函数接收参数 `EventClass`,它将接收事件类本身。类的 `__call__` 函数将接受消息事件对象,并返回一个 `bool` 类型的判定结果。
+3. 将类实例化。我们传入群聊消息事件作为参数实例化 `checker` 。
+4. 在事件处理函数里声明依赖项。`NoneBot2` 将会调用 `checker` 的 `__call__` 方法,返回给参数 `x` 相应的判断结果。
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/di/overload.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/overload.md
new file mode 100644
index 00000000..47dd7299
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/di/overload.md
@@ -0,0 +1,76 @@
+---
+sidebar_position: 2
+description: 重载事件处理函数
+
+options:
+ menu:
+ weight: 61
+ category: advanced
+---
+
+# 事件处理函数重载
+
+当我们在编写 NoneBot2 应用时,常常会遇到这样一个问题:该怎么让同一类型的不同事件执行不同的响应逻辑?又或者如何让不同的 `bot` 针对同一类型的事件作出不同响应?
+
+针对这个问题, NoneBot2 提供一个便捷而高效的解决方案:事件处理函数重载机制。简单地说,`handler`(事件处理函数)会根据其参数的 `type hints`([PEP484 类型标注](https://www.python.org/dev/peps/pep-0484/))来对相对应的 `bot` 和 `event` 进行响应,并且会忽略不符合其参数类型标注的情况。
+
+
+
+:::tip 提示
+如果想了解更多关于 `inspect` 标准库的信息,可以查看[官方文档](https://docs.python.org/zh-cn/3.9/library/inspect.html)。
+:::
+
+下面,我们会以 OneBot 适配器中的群聊消息事件和私聊消息事件为例,对该机制的应用进行简单的介绍。
+
+## 一个例子
+
+首先,我们需要导入需要的方法、类型。
+
+```python
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent
+```
+
+之后,我们可以注册一个 `Matcher` 来响应消息事件。
+
+```python
+matcher = on_command("test_overload")
+```
+
+最后,我们编写不同的 `handler` 并编写不同的类型标注来实现事件处理函数重载:
+
+```python
+@matcher.handle()
+async def _(bot: Bot, event: GroupMessageEvent):
+ await matcher.send("群聊消息事件响应成功!")
+
+
+@matcher.handle()
+async def _(bot: Bot, event: PrivateMessageEvent):
+ await matcher.send("私聊消息事件响应成功!")
+```
+
+此时,我们可以在群聊或私聊中对我们的机器人发送 `test_overload`,它会在不同的场景做出不同的应答。
+
+这样一个简单的事件处理函数重载就完成了。
+
+## 进阶
+
+事件处理函数重载机制同样支持被 `matcher.got` 等装饰器装饰的函数。例如:
+
+```python
+@matcher.got("key1", prompt="群事件提问")
+async def _(bot: Bot, event: GroupMessageEvent):
+ await matcher.send("群聊消息事件响应成功!")
+
+
+@matcher.got("key2", prompt="私聊事件提问")
+async def _(bot: Bot, event: PrivateMessageEvent):
+ await matcher.send("私聊消息事件响应成功!")
+```
+
+只有触发事件符合的函数才会触发装饰器。
+
+:::warning 注意
+bot 和 event 参数具有最高的检查优先级,因此,如果参数类型不符合,所有的依赖项 `Depends` 等都不会被执行。
+:::
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/images/Handle-Event.png b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/Handle-Event.png
new file mode 100644
index 00000000..ab63c489
Binary files /dev/null and b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/Handle-Event.png differ
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish.png b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish.png
new file mode 100644
index 00000000..ae83861f
Binary files /dev/null and b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish.png differ
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish_2.png b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish_2.png
new file mode 100644
index 00000000..eb250b1f
Binary files /dev/null and b/website/versioned_docs/version-2.0.0-beta.5/advanced/images/plugin_store_publish_2.png differ
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/permission.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/permission.md
new file mode 100644
index 00000000..8159329a
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/permission.md
@@ -0,0 +1,95 @@
+---
+sidebar_position: 3
+description: 自定义事件响应器的响应权限
+
+options:
+ menu:
+ weight: 40
+ category: advanced
+---
+
+# 权限控制
+
+**权限控制**是机器人在实际应用中需要解决的重点问题之一,NoneBot2 提供了灵活的权限控制机制——`Permission`,接下来我们将简单说明。
+
+## 应用
+
+如同 `Rule` 一样,`Permission` 可以在[定义事件响应器](../tutorial/plugin/create-matcher.md)时添加 `permission` 参数来加以应用,这样 NoneBot2 会在事件响应时检测事件主体的权限。下面我们以 `SUPERUSER` 为例,对该机制的应用做一下介绍。
+
+```python
+from nonebot.permission import SUPERUSER
+from nonebot import on_command
+
+matcher = on_command("测试超管", permission=SUPERUSER)
+
+
+@matcher.handle()
+async def _():
+ await matcher.send("超管命令测试成功")
+
+
+@matcher.got("key1", "超管提问")
+async def _():
+ await matcher.send("超管命令 got 成功")
+```
+
+在这段代码中,我们事件响应器指定了 `SUPERUSER` 这样一个权限,那么机器人只会响应超级管理员的 `测试超管` 命令,并且会响应该超级管理员的连续对话。
+
+:::tip 提示
+在这里需要强调的是,`Permission` 与 `Rule` 的表现并不相同, `Rule` 只会在初次响应时生效,在余下的对话中并没有限制事件;但是 `Permission` 会持续生效,在连续对话中一直对事件主体加以限制。
+:::
+
+## 进阶
+
+`Permission` 除了可以在注册事件响应器时加以应用,还可以在编写事件处理函数 `handler` 时主动调用,我们可以利用这个特性在一个 `handler` 里对不同权限的事件主体进行区别响应,下面我们以 OneBot 适配器中的 `GROUP_ADMIN`(普通管理员非群主)和 `GROUP_OWNER` 为例,说明下怎么进行主动调用。
+
+```python
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
+from nonebot.adapters.onebot.v11 import GROUP_ADMIN, GROUP_OWNER
+
+matcher = on_command("测试权限")
+
+@matcher.handle()
+async def _(bot: Bot, event: GroupMessageEvent):
+ if await GROUP_ADMIN(bot, event):
+ await matcher.send("管理员测试成功")
+ elif await GROUP_OWNER(bot, event):
+ await matcher.send("群主测试成功")
+ else:
+ await matcher.send("群员测试成功")
+```
+
+在这段代码里,我们并没有对命令的权限指定,这个命令会响应所有在群聊中的 `测试权限` 命令,但是在 `handler` 里,我们对两个 `Permission` 进行主动调用,从而可以对不同的角色进行不同的响应。
+
+## 自定义
+
+如同 `Rule` 一样,`Permission` 也是由非负数个 `PermissionChecker` 组成的,但只需其中一个返回 `True` 时就会匹配成功。下面是自定义 `PermissionChecker` 和 `Permission` 的示例:
+
+```python
+from nonebot.adapters import Bot, Event
+from nonebot.permission import Permission
+
+async def async_checker(bot: Bot, event: Event) -> bool:
+ return True
+
+def sync_checker(bot: Bot, event: Event) -> bool:
+ return True
+
+def check(arg1, arg2):
+
+ async def _checker(bot: Bot, event: Event) -> bool:
+ return bool(arg1 + arg2)
+
+ return Permission(_checker)
+```
+
+`Permission` 和 `PermissionChecker` 之间可以使用 `|`(或符号)互相组合:
+
+```python
+from nonebot.permission import Permission
+
+Permission(async_checker1) | sync_checker | async_checker2
+```
+
+同样地,如果想用 `Permission(*checkers)` 包裹构造 `Permission`,函数必须是异步的;但是在利用 `|`(或符号)连接构造时,NoneBot2 会自动包裹同步函数为异步函数。
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/publish-plugin.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/publish-plugin.md
new file mode 100644
index 00000000..9416d483
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/publish-plugin.md
@@ -0,0 +1,72 @@
+---
+sidebar_position: 7
+description: 发布插件到 NoneBot2 商店
+
+options:
+ menu:
+ weight: 80
+ category: advanced
+---
+
+# 发布插件
+
+## 前注
+
+本章节仅包含插件发布流程指导,插件开发请查阅[**创建插件**](../tutorial/plugin/introduction.md)章节与[**Plugin API 文档**](../api/plugin/index.md)。
+
+## 插件发布流程
+
+### 发布到 PyPI
+
+您可以选择自己喜欢的方式将插件发布到 [**PyPI**](https://pypi.org/),如使用 [**setuptools**](https://pypi.org/project/setuptools/) 或 [**Poetry**](https://pypi.org/project/poetry/)。
+
+发布时,请您为自己的插件取一个清晰易懂的名字。通常而言,一款 NoneBot2 插件名称使用 `nonebot-plugin-` 作为前缀(如`nonebot-plugin-foo`),以 `nonebot_plugin_` 作为包名的前缀(如`nonebot_plugin_foo`),这并非强制规范,而是为了防止与其他 PyPI 包产生冲突,所以我们推荐您在没有特殊需求的情况下这样做。
+
+发布后,请确保您的插件已能公开的从 PyPI 访问到,试着检查您的插件在 PyPI 的地址,如 `https://pypi.org/project/<您的 NoneBot2 插件项目名>`。
+
+### 托管您的插件源代码
+
+将插件源代码及相关构建文件(如 `pyproject.toml` 或 `setup.py` 等与 PyPI 包构建相关的文件)托管在公开代码仓。
+
+请确保您的代码仓库地址能够被正确的访问,检查您的插件在代码仓的地址,如 `https://github.com/<您的 Github 用户名>/<您的插件 Github 项目名>`。
+
+### 申请发布到 NoneBot2 插件商店
+
+完成在 PyPI 的插件发布流程与源代码托管流程后,请您前往 [**NoneBot2 商店**](https://v2.nonebot.dev/store.html)页面,切换到**插件**页签,点击**发布插件**按钮。
+
+![插件发布界面](./images/plugin_store_publish.png)
+
+如图所示,在弹出的插件信息提交表单内,填入您所要发布的相应插件信息:
+
+```text
+插件名称:您的 NoneBot2 插件名称
+插件介绍:为您的插件提供的简短介绍信息
+PyPI 项目名:您的插件所在的 PyPI Project 名,如 nonebot-plugin-xxxx
+import 包名:您的插件通过 Python 导入时使用的包名,如 nonebot_plugin_xxxx
+仓库/主页:您的插件托管地址,如 https://github.com/<您的 Github 用户名>/nonebot-plugin-xxxx
+标签:一个或多个可选颜色的 TAG,每填写一个点击添加标签,若要删除,点击标签即可;标签长度不超过 10 字符,标签个数不超过 3 个
+特定标签内容 Adapter:点击 Type 的 Adapter,将创建一个 a: 开头的标签,填入内容以指定您插件使用的 adapter
+特定标签内容 Topic:点击 Type 的 Topic,将创建一个 t: 开头的标签,填入内容以指定您插件的主题
+```
+
+![插件信息填写](./images/plugin_store_publish_2.png)
+
+完成填写后,请点击**发布**按钮,这将自动在[**NoneBot2**](https://github.com/nonebot/nonebot2)代码仓内创建发布您的插件的对应 Issue。
+
+### 等待插件发布处理
+
+您的插件发布 Issue 创建后,将会经过 _NoneBot2 Publish Bot_ 的检查,以确保插件信息正确无误。
+
+若您的插件发布 Issue 未通过检查,您可以**直接修改** Issue 内容以更新发布请求。_NoneBot2 Publish Bot_ 在您修改 Issue 内容后将会自动重新执行检查。您无需关闭、重新提交发布申请。
+
+之后,NoneBot2 的维护者们将会对插件进行进一步的检查,以确保用户能够正常安装并使用该插件。
+
+完成这些步骤后,您的插件将会被合并到 [**NoneBot2 商店**](https://v2.nonebot.dev/store.html),而您也将成为 [**NoneBot2 贡献者**](https://github.com/nonebot/nonebot2/graphs/contributors)中的一员。
+
+## 完成
+
+恭喜您,经过上述的发布流程,您的插件已经成功发布到 NoneBot2 商店了。
+
+此时,您可以在 [**NoneBot2 商店**](https://v2.nonebot.dev/store.html)的插件页签查找到您的插件。同时,欢迎您成为 [**NoneBot2 贡献者**](https://github.com/nonebot/nonebot2/graphs/contributors)!
+
+**Congratulations!**
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/rule.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/rule.md
new file mode 100644
index 00000000..cd173104
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/rule.md
@@ -0,0 +1,75 @@
+---
+sidebar_position: 2
+description: 自定义事件响应器的响应规则
+
+options:
+ menu:
+ weight: 30
+ category: advanced
+---
+
+# 自定义匹配规则
+
+机器人在实际应用中,往往会接收到多种多样的事件类型,NoneBot2 提供了可自定义的匹配规则 ── `Rule`。在[定义事件响应器](../tutorial/plugin/create-matcher.md#创建事件响应器)中,已经介绍了多种内置的事件响应器,接下来我们将说明自定义匹配规则的基本用法。
+
+## 创建匹配规则
+
+匹配规则可以是一个 `Rule` 对象,也可以是一个 `RuleChecker` 类型。`Rule` 是多个 `RuleChecker` 的集合,只有当所有 `RuleChecker` 检查通过时匹配成功。`RuleChecker` 是一个返回值为 `Bool` 类型的依赖函数,即,`RuleChecker` 支持依赖注入。
+
+### 创建 `RuleChecker`
+
+```python {1-2}
+async def user_checker(event: Event) -> bool:
+ return event.get_user_id() == "123123"
+
+matcher = on_message(rule=user_checker)
+```
+
+在上面的代码中,我们定义了一个函数 `user_checker`,它检查事件的用户 ID 是否等于 `"123123"`。这个函数 `user_checker` 即为一个 `RuleChecker`。
+
+### 创建 `Rule`
+
+```python {1-2,4-5,7}
+async def user_checker(event: Event) -> bool:
+ return event.get_user_id() == "123123"
+
+async def message_checker(event: Event) -> bool:
+ return event.get_plaintext() == "hello"
+
+rule = Rule(user_checker, message_checker)
+matcher = on_message(rule=rule)
+```
+
+在上面的代码中,我们定义了两个函数 `user_checker` 和 `message_checker`,它们检查事件的用户 ID 是否等于 `"123123"`,以及消息的内容是否等于 `"hello"`。随后,我们定义了一个 `Rule` 对象,它包含了这两个函数。
+
+## 注册匹配规则
+
+在[定义事件响应器](../tutorial/plugin/create-matcher.md#创建事件响应器)中,我们已经了解了如何事件响应器的组成。现在,我们仅需要将匹配规则注册到事件响应器中。
+
+```python {4}
+async def user_checker(event: Event) -> bool:
+ return event.get_user_id() == "123123"
+
+matcher = on_message(rule=user_checker)
+```
+
+在定义事件响应器的辅助函数中,都有一个 `rule` 参数,用于指定自定义的匹配规则。辅助函数会为你将自定义匹配规则与内置规则组合,并注册到事件响应器中。
+
+## 合并匹配规则
+
+在定义匹配规则时,我们往往希望将规则进行细分,来更好地复用规则。而在使用时,我们需要合并多个规则。除了使用 `Rule` 对象来组合多个 `RuleChecker` 外,我们还可以对 `Rule` 对象进行合并。
+
+```python {4-6}
+rule1 = Rule(foo_checker)
+rule2 = Rule(bar_checker)
+
+rule = rule1 & rule2
+rule = rule1 & bar_checker
+rule = foo_checker & rule2
+```
+
+同时,你也无需担心合并了一个 `None` 值,`Rule` 会忽略 `None` 值。
+
+```python
+assert (rule & None) is rule
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/runtime-hook.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/runtime-hook.md
new file mode 100644
index 00000000..e12f496e
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/runtime-hook.md
@@ -0,0 +1,171 @@
+---
+sidebar_position: 4
+description: 在 NoneBot2 框架中添加 Hook 函数
+
+options:
+ menu:
+ weight: 50
+ category: advanced
+---
+
+# 钩子函数
+
+[钩子编程](https://zh.wikipedia.org/wiki/%E9%92%A9%E5%AD%90%E7%BC%96%E7%A8%8B)
+
+> 钩子编程(hooking),也称作“挂钩”,是计算机程序设计术语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术。处理被拦截的函数调用、事件、消息的代码,被称为钩子(hook)。
+
+在 NoneBot2 中有一系列预定义的钩子函数,分为两类:**全局钩子函数**和**事件钩子函数**,这些钩子函数可以用装饰器的形式来使用。
+
+## 全局钩子函数
+
+全局钩子函数是指 NoneBot2 针对其本身运行过程的钩子函数。
+
+这些钩子函数是由其后端驱动 `Driver` 来运行的,故需要先获得全局 `Driver` 对象:
+
+```python
+from nonebot import get_driver
+
+
+driver=get_driver()
+```
+
+共分为六种函数:
+
+### 启动准备
+
+这个钩子函数会在 NoneBot2 启动时运行。
+
+```python
+@driver.on_startup
+async def do_something():
+ pass
+```
+
+### 终止处理
+
+这个钩子函数会在 NoneBot2 终止时运行。
+
+```python
+@driver.on_shutdown
+async def do_something():
+ pass
+```
+
+### Bot 连接处理
+
+这个钩子函数会在 `Bot` 通过 websocket 连接到 NoneBot2 时运行。
+
+```python
+@driver.on_bot_connect
+async def do_something(bot: Bot):
+ pass
+```
+
+### bot 断开处理
+
+这个钩子函数会在 `Bot` 断开与 NoneBot2 的 websocket 连接时运行。
+
+```python
+@driver.on_bot_disconnect
+async def do_something(bot: Bot):
+ pass
+```
+
+### bot api 调用钩子
+
+这个钩子函数会在 `Bot` 调用 API 时运行。
+
+```python
+from nonebot.adapters import Bot
+
+@Bot.on_calling_api
+async def handle_api_call(bot: Bot, api: str, data: Dict[str, Any]):
+ pass
+```
+
+### bot api 调用后钩子
+
+这个钩子函数会在 `Bot` 调用 API 后运行。
+
+```python
+from nonebot.adapters import Bot
+
+@Bot.on_called_api
+async def handle_api_result(bot: Bot, exception: Optional[Exception], api: str, data: Dict[str, Any], result: Any):
+ pass
+```
+
+## 事件钩子函数
+
+这些钩子函数指的是影响 NoneBot2 进行**事件处理**的函数, 这些函数可以认为跟普通的事件处理函数一样,接受相应的参数。
+
+:::tip 提示
+关于**事件处理**的流程,可以在[这里](./README.md)查阅。
+:::
+
+:::warning
+
+1.在事件处理钩子函数中,与 `matcher` 运行状态相关的函数将不可用,如 `matcher.finish()`
+
+2.如果需要在事件处理钩子函数中打断整个对话的执行,请参考以下范例:
+
+```python
+from nonebot.exception import IgnoredException
+
+
+@event_preprocessor
+async def do_something():
+ raise IgnoredException("reason")
+```
+
+:::
+
+共分为四种函数:
+
+### 事件预处理
+
+这个钩子函数会在 `Event` 上报到 NoneBot2 时运行
+
+```python
+from nonebot.message import event_preprocessor
+
+@event_preprocessor
+async def do_something():
+ pass
+```
+
+### 事件后处理
+
+这个钩子函数会在 NoneBot2 处理 `Event` 后运行
+
+```python
+from nonebot.message import event_postprocessor
+
+@event_postprocessor
+async def do_something():
+ pass
+```
+
+### 运行预处理
+
+这个钩子函数会在 NoneBot2 运行 `matcher` 前运行。
+
+```python
+from nonebot.message import run_preprocessor
+
+@run_preprocessor
+async def do_something():
+ pass
+```
+
+### 运行后处理
+
+这个钩子函数会在 NoneBot2 运行 `matcher` 后运行。
+
+```python
+from nonebot.message import run_postprocessor
+
+@run_postprocessor
+async def do_something():
+ pass
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/scheduler.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/scheduler.md
new file mode 100644
index 00000000..2b533cd6
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/scheduler.md
@@ -0,0 +1,147 @@
+---
+sidebar_position: 1
+description: 在 NoneBot2 中使用定时任务
+
+options:
+ menu:
+ weight: 20
+ category: advanced
+---
+
+# 定时任务
+
+[APScheduler](https://apscheduler.readthedocs.io/en/3.x/) —— Advanced Python Scheduler
+
+> Advanced Python Scheduler (APScheduler) is a Python library that lets you schedule your Python code to be executed later, either just once or periodically. You can add new jobs or remove old ones on the fly as you please. If you store your jobs in a database, they will also survive scheduler restarts and maintain their state. When the scheduler is restarted, it will then run all the jobs it should have run while it was offline.
+
+## 从 NoneBot v1 迁移
+
+`APScheduler` 作为 NoneBot v1 的可选依赖,为众多 bot 提供了方便的定时任务功能。NoneBot2 已将 `APScheduler` 独立为 nonebot_plugin_apscheduler 插件,你可以在[商店](/store)中找到它。
+
+相比于 NoneBot v1,NoneBot v2 只需要安装插件并修改 `scheduler` 的导入方式即可完成迁移。
+
+## 安装插件
+
+### 通过 nb-cli
+
+如正在使用 nb-cli 构建项目,你可以从插件市场复制安装命令或手动输入以下命令以添加 nonebot_plugin_apscheduler。
+
+```bash
+nb plugin install nonebot_plugin_apscheduler
+```
+
+:::tip 提示
+nb-cli 默认通过 PyPI 安装,你可以添加命令参数 `-i [mirror]` 或 `--index [mirror]` 以使用镜像源安装。
+:::
+
+### 通过 Poetry
+
+执行以下命令以添加 nonebot_plugin_apscheduler
+
+```bash
+poetry add nonebot-plugin-apscheduler
+```
+
+:::tip 提示
+由于稍后我们将使用 `nonebot.require()` 方法进行声明依赖,所以无需额外的 `nonebot.load_plugin()`
+:::
+
+## 快速上手
+
+1. 在需要设置定时任务的插件中,通过 `nonebot.require` 声明插件依赖
+2. 从 nonebot_plugin_apscheduler 导入 `scheduler` 对象
+3. 在该对象的基础上,根据 `APScheduler` 的使用方法进一步配置定时任务
+
+将上述步骤归纳为最小实现的代码如下:
+
+```python {3,5}
+from nonebot import require
+
+require("nonebot_plugin_apscheduler")
+
+from nonebot_plugin_apscheduler import scheduler
+
+@scheduler.scheduled_job("cron", hour="*/2", id="xxx", args=[1], kwargs={"arg2": 2})
+async def run_every_2_hour(arg1, arg2):
+ pass
+
+scheduler.add_job(run_every_day_from_program_start, "interval", days=1, id="xxx")
+```
+
+## 分步进行
+
+### 导入 scheduler 对象
+
+为了使插件能够实现定时任务,需要先将 `scheduler` 对象导入插件。
+
+NoneBot2 提供了 `nonebot.require` 方法来实现声明插件依赖,确保 `nonebot_plugin_apscheduler` 插件可以在使用之前被导入。声明完成即可直接通过 import 导入 `scheduler` 对象。
+
+NoneBot2 使用的 `scheduler` 对象为 `AsyncIOScheduler` 。
+
+```python {3,5}
+from nonebot import require
+
+require("nonebot_plugin_apscheduler")
+
+from nonebot_plugin_apscheduler import scheduler
+```
+
+### 编写定时任务
+
+由于本部分为标准的通过 `APScheduler` 配置定时任务,有关指南请参阅 [APScheduler 官方文档](https://apscheduler.readthedocs.io/en/3.x/userguide.html#adding-jobs)。
+
+### 配置插件选项
+
+根据项目的 `.env` 文件设置,向 `.env.*` 或 `bot.py` 文件添加 nonebot_plugin_apscheduler 的可选配置项
+
+:::warning 注意
+`.env.*` 文件的编写应遵循 NoneBot2 对 `.env.*` 文件的编写要求
+:::
+
+#### `apscheduler_autostart`
+
+类型:`bool`
+
+默认值:`True`
+
+是否自动启动 `APScheduler`。
+
+对于大多数情况,我们需要在 NoneBot2 项目被启动时启动定时任务,则此处设为 `true`
+
+##### 在 `.env` 中添加
+
+```bash
+APSCHEDULER_AUTOSTART=true
+```
+
+##### 在 `bot.py` 中添加
+
+```python
+nonebot.init(apscheduler_autostart=True)
+```
+
+#### `apscheduler_config`
+
+类型:`dict`
+
+默认值:`{"apscheduler.timezone": "Asia/Shanghai"}`
+
+`APScheduler` 相关配置。修改/增加其中配置项需要确保 `prefix: apscheduler`。
+
+对于 `APScheduler` 的相关配置,请参阅 [scheduler-config](https://apscheduler.readthedocs.io/en/3.x/userguide.html#scheduler-config) 和 [BaseScheduler](https://apscheduler.readthedocs.io/en/3.x/modules/schedulers/base.html#apscheduler.schedulers.base.BaseScheduler)
+
+> 官方文档在绝大多数时候能提供最准确和最具时效性的指南
+
+##### 在 `.env` 中添加
+
+```bash
+APSCHEDULER_CONFIG={"apscheduler.timezone": "Asia/Shanghai"}
+```
+
+##### 在 `bot.py` 中添加
+
+```python
+nonebot.init(apscheduler_config={
+ "apscheduler.timezone": "Asia/Shanghai"
+})
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/README.mdx b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/README.mdx
new file mode 100644
index 00000000..a5ace0d3
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/README.mdx
@@ -0,0 +1,106 @@
+---
+sidebar_position: 1
+description: 使用 NoneBug 测试机器人
+slug: /advanced/unittest/
+
+options:
+ menu:
+ weight: 70
+ category: advanced
+---
+
+import CodeBlock from "@theme/CodeBlock";
+
+# 单元测试
+
+[单元测试](https://zh.wikipedia.org/wiki/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95)
+
+> 在计算机编程中,单元测试(Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。
+
+NoneBot2 使用 [Pytest](https://docs.pytest.org) 单元测试框架搭配 [NoneBug](https://github.com/nonebot/nonebug) 插件进行单元测试,通过直接与事件响应器/适配器等交互简化测试流程,更易于编写。
+
+## 安装 NoneBug
+
+安装 NoneBug 时,Pytest 会作为依赖被一起安装。
+
+要运行 NoneBug,还需要额外安装 Pytest 异步插件 `pytest-asyncio` 或 `anyio`,文档将以 `pytest-asyncio` 为例。
+
+```bash
+poetry add nonebug pytest-asyncio --dev
+# 也可以通过 pip 安装
+pip install nonebug pytest-asyncio
+```
+
+:::tip 提示
+建议首先阅读 [Pytest 文档](https://docs.pytest.org) 理解相关术语。
+:::
+
+## 加载插件
+
+我们可以使用 Pytest **Fixtures** 来加载插件,下面是一个示例:
+
+```python title=conftest.py
+from pathlib import Path
+from typing import TYPE_CHECKING, Set
+
+import pytest
+
+if TYPE_CHECKING:
+ from nonebot.plugin import Plugin
+
+
+@pytest.fixture
+def load_plugins(nonebug_init: None) -> Set["Plugin"]:
+ import nonebot # 这里的导入必须在函数内
+
+ # 加载插件
+ return nonebot.load_plugins("awesome_bot/plugins")
+```
+
+此 Fixture 的 [`nonebug_init`](https://github.com/nonebot/nonebug/blob/master/nonebug/fixture.py) 形参也是一个 Fixture,用于初始化 NoneBug。
+
+Fixture 名称 `load_plugins` 可以修改为其他名称,文档以 `load_plugins` 为例。需要加载插件时,在测试函数添加形参 `load_plugins` 即可。加载完成后即可使用 `import` 导入事件响应器。
+
+## 测试流程
+
+Pytest 会在函数开始前通过 Fixture `app`(nonebug_app) **初始化 NoneBug** 并返回 `App` 对象。
+
+:::warning 警告
+所有从 `nonebot` 导入模块的函数都需要首先初始化 NoneBug App,否则会发生不可预料的问题。
+
+在每个测试函数结束时,NoneBug 会自动销毁所有与 NoneBot 相关的资源。所有与 NoneBot 相关的 import 应在函数内进行导入。
+:::
+
+随后使用 `test_matcher` 等测试方法获取到 `Context` 上下文,通过上下文管理提供的方法(如 `should_call_send` 等)预定义行为。
+
+在上下文管理器关闭时,`Context` 会调用 `run_test` 方法按照预定义行为对事件响应器进行断言(如:断言事件响应和 API 调用等)。
+
+## 测试样例
+
+:::tip 提示
+将从 `utils` 导入的 `make_fake_message`,`make_fake_event` 替换为对应平台的消息/事件类型。
+
+将 `load_example` 替换为加载插件的 Fixture 名称。
+:::
+
+使用 NoneBug 的 `test_matcher` 可以模拟出一个事件流程。如下是一个简单的示例:
+
+import WeatherSource from "!!raw-loader!@site/../tests/examples/weather.py";
+import WeatherTest from "!!raw-loader!@site/../tests/test_examples/test_weather.py";
+
+
+ {WeatherTest}
+
+
+
+ 示例插件
+
+ {WeatherSource}
+
+
+
+在测试用例编写完成后 ,可以使用下面的命令运行单元测试。
+
+```bash
+pytest test_weather.py
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/_category_.json b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/_category_.json
new file mode 100644
index 00000000..08695121
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "单元测试",
+ "position": 6
+}
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-adapters.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-adapters.md
new file mode 100644
index 00000000..04f7c743
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-adapters.md
@@ -0,0 +1,162 @@
+---
+sidebar_position: 4
+description: 测试适配器
+---
+
+# 测试适配器
+
+通常来说,测试适配器需要测试这三项。
+
+1. 测试连接
+2. 测试事件转化
+3. 测试 API 调用
+
+## 注册适配器
+
+任何的适配器都需要注册才能起作用。
+
+我们可以使用 Pytest 的 Fixtures,在测试开始前初始化 NoneBot 并**注册适配器**。
+
+我们假设适配器为 `nonebot.adapters.test`。
+
+```python {20,21} title=conftest.py
+from pathlib import Path
+
+import pytest
+from nonebug import App
+
+# 如果适配器采用 nonebot.adapters monospace 则需要使用此hook方法正确添加路径
+@pytest.fixture
+def import_hook():
+ import nonebot.adapters
+
+ nonebot.adapters.__path__.append( # type: ignore
+ str((Path(__file__).parent.parent / "nonebot" / "adapters").resolve())
+ )
+
+@pytest.fixture
+async def init_adapter(app: App, import_hook):
+ import nonebot
+ from nonebot.adapters.test import Adapter
+
+ driver = nonebot.get_driver()
+ driver.register_adapter(Adapter)
+```
+
+## 测试连接
+
+任何的适配器的连接方式主要有以下 4 种:
+
+1. 反向 HTTP(WebHook)
+2. 反向 WebSocket
+3. ~~正向 HTTP(尚未实现)~~
+4. ~~正向 WebSocket(尚未实现)~~
+
+NoneBug 的 `test_server` 方法可以供我们测试反向连接方式。
+
+`test_server` 的 `get_client` 方法可以获取 HTTP/WebSocket 客户端。
+
+我们假设适配器 HTTP 上报地址为 `/test/http`,反向 WebSocket 地址为 `/test/ws`,上报机器人 ID
+使用请求头 `Bot-ID` 来演示如何通过 NoneBug 测试适配器。
+
+```python {8,16,17,19-22,26,34,36-39} title=test_connection.py
+from pathlib import Path
+
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+ "endpoints", ["/test/http"]
+)
+async def test_http(app: App, init_adapter, endpoints: str):
+ import nonebot
+
+ async with app.test_server() as ctx:
+ client = ctx.get_client()
+
+ body = {"post_type": "test"}
+ headers = {"Bot-ID": "test"}
+
+ resp = await client.post(endpoints, json=body, headers=headers)
+ assert resp.status_code == 204 # 检测状态码是否正确
+ bots = nonebot.get_bots()
+ assert "test" in bots # 检测是否连接成功
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+ "endpoints", ["/test/ws"]
+)
+async def test_ws(app: App, init_adapter, endpoints: str):
+ import nonebot
+
+ async with app.test_server() as ctx:
+ client = ctx.get_client()
+
+ headers = {"Bot-ID": "test"}
+
+ async with client.websocket_connect(endpoints, headers=headers) as ws:
+ bots = nonebot.get_bots()
+ assert "test" in bots # 检测是否连接成功
+```
+
+## 测试事件转化
+
+事件转化就是将原始数据反序列化为 `Event` 对象的过程。
+
+测试事件转化就是测试反序列化是否按照预期转化为对应 `Event` 类型。
+
+下面将以 `dict_to_event` 作为反序列化方法,`type` 为 `test` 的事件类型为 `TestEvent` 来演示如何测试事件转化。
+
+```python {8,9} title=test_event.py
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_event(app: App, init_adapter):
+ from nonebot.adapters.test import Adapter, TestEvent
+
+ event = Adapter.dict_to_event({"post_type": "test"}) # 反序列化原始数据
+ assert isinstance(event, TestEvent) # 断言类型是否与预期一致
+```
+
+## 测试 API 调用
+
+将消息序列化为原始数据并由适配器发送到协议端叫做 API 调用。
+
+测试 API 调用就是调用 API 并验证返回与预期返回是否一致。
+
+```python {16-18,23-32} title=test_call_api.py
+import asyncio
+from pathlib import Path
+
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_ws(app: App, init_adapter):
+ import nonebot
+
+ async with app.test_server() as ctx:
+ client = ctx.get_client()
+
+ headers = {"Bot-ID": "test"}
+
+ async def call_api():
+ bot = nonebot.get_bot("test")
+ return await bot.test_api()
+
+ async with client.websocket_connect("/test/ws", headers=headers) as ws:
+ task = asyncio.create_task(call_api())
+
+ # received = await ws.receive_text()
+ # received = await ws.receive_bytes()
+ received = await ws.receive_json()
+ assert received == {"action": "test_api"} # 检测调用是否与预期一致
+ response = {"result": "test"}
+ # await ws.send_text(...)
+ # await ws.send_bytes(...)
+ await ws.send_json(response, mode="bytes")
+ result = await task
+ assert result == response # 检测返回是否与预期一致
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher-operation.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher-operation.md
new file mode 100644
index 00000000..0452cd10
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher-operation.md
@@ -0,0 +1,122 @@
+---
+sidebar_position: 3
+description: 测试事件响应处理
+---
+
+# 测试事件响应处理行为
+
+除了 `send`,事件响应器还有其他的操作,我们也需要对它们进行测试,下面我们将定义如下事件响应器操作的预期行为对对应的事件响应器操作进行测试。
+
+## should_finished
+
+定义事件响应器预期结束当前事件的整个处理流程。
+
+适用事件响应器操作:[`finish`](../../tutorial/plugin/matcher-operation.md#finish)。
+
+
+
+ 示例插件
+
+```python title=example.py
+from nonebot import on_message
+
+foo = on_message()
+
+@foo.handle()
+async def _():
+ await foo.finish("test")
+```
+
+
+
+```python {13}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_call_send(event, "test", True)
+ ctx.should_finished()
+```
+
+## should_paused
+
+定义事件响应器预期立即结束当前事件处理依赖并等待接收一个新的事件后进入下一个事件处理依赖。
+
+适用事件响应器操作:[`pause`](../../tutorial/plugin/matcher-operation.md#pause)。
+
+
+ 示例插件
+
+```python title=example.py
+from nonebot import on_message
+
+foo = on_message()
+
+@foo.handle()
+async def _():
+ await foo.pause("test")
+```
+
+
+
+```python {13}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_call_send(event, "test", True)
+ ctx.should_paused()
+```
+
+## should_rejected
+
+定义事件响应器预期立即结束当前事件处理依赖并等待接收一个新的事件后再次执行当前事件处理依赖。
+
+适用事件响应器操作:[`reject`](../../tutorial/plugin/matcher-operation.md#reject)
+、[`reject_arg`](../../tutorial/plugin/matcher-operation.md#reject_arg)
+和 [`reject_receive`](../../tutorial/plugin/matcher-operation.md#reject_receive)。
+
+
+ 示例插件
+
+```python title=example.py
+from nonebot import on_message
+
+foo = on_message()
+
+@foo.got("key")
+async def _():
+ await foo.reject("test")
+```
+
+
+
+```python {13}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_call_send(event, "test", True)
+ ctx.should_rejected()
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher.md b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher.md
new file mode 100644
index 00000000..9733d93c
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/advanced/unittest/test-matcher.md
@@ -0,0 +1,159 @@
+---
+sidebar_position: 2
+description: 测试事件响应和 API 调用
+---
+
+# 测试事件响应和 API 调用
+
+事件响应器通过 `Rule` 和 `Permission` 来判断当前事件是否触发事件响应器,通过 `send` 发送消息或使用 `call_api` 调用平台 API,这里我们将对上述行为进行测试。
+
+## 定义预期响应行为
+
+NoneBug 提供了六种定义 `Rule` 和 `Permission` 的预期行为的方法来进行测试:
+
+- `should_pass_rule`
+- `should_not_pass_rule`
+- `should_ignore_rule`
+- `should_pass_permission`
+- `should_not_pass_permission`
+- `should_ignore_permission`
+
+以下为示例代码
+
+
+
+ 示例插件
+
+```python title=example.py
+from nonebot import on_message
+
+async def always_pass():
+ return True
+
+async def never_pass():
+ return False
+
+foo = on_message(always_pass)
+bar = on_message(never_pass, permission=never_pass)
+```
+
+
+
+```python {12,13,19,20,27,28}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo, bar
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_pass_rule()
+ ctx.should_pass_permission()
+
+ async with app.test_matcher(bar) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_not_pass_rule()
+ ctx.should_not_pass_permission()
+
+ # 如需忽略规则/权限不通过
+ async with app.test_matcher(bar) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_ignore_rule()
+ ctx.should_ignore_permission()
+```
+
+## 定义预期 API 调用行为
+
+在[事件响应器操作](../../tutorial/plugin/matcher-operation.md)和[调用平台 API](../../tutorial/call-api.md) 中,我们已经了解如何向发送消息或调用平台 `API`。接下来对 [`send`](../../tutorial/plugin/matcher-operation.md#send) 和 [`call_api`](../../api/adapters/index.md#Bot-call_api) 进行测试。
+
+### should_call_send
+
+定义事件响应器预期发送消息,包括使用 [`send`](../../tutorial/plugin/matcher-operation.md#send)、[`finish`](../../tutorial/plugin/matcher-operation.md#finish)、[`pause`](../../tutorial/plugin/matcher-operation.md#pause)、[`reject`](../../tutorial/plugin/matcher-operation.md#reject) 以及 [`got`](../../tutorial/plugin/create-handler.md#使用-got-装饰器) 的 prompt 等方法发送的消息。
+
+`should_call_send` 需要提供四个参数:
+
+- `event`:事件对象。
+- `message`:预期的消息对象,可以是`str`、[`Message`](../../api/adapters/index.md#Message) 或 [`MessageSegment`](../../api/adapters/index.md#MessageSegment)。
+- `result`:`send` 的返回值,将会返回给插件。
+- `**kwargs`:`send` 方法的额外参数。
+
+
+ 示例插件
+
+```python title=example.py
+from nonebot import on_message
+
+foo = on_message()
+
+@foo.handle()
+async def _():
+ await foo.send("test")
+```
+
+
+
+```python {12}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_call_send(event, "test", True)
+```
+
+### should_call_api
+
+定义事件响应器预期调用机器人 API 接口,包括使用 `call_api` 或者直接使用 `bot.some_api` 的方式调用 API。
+
+`should_call_api` 需要提供四个参数:
+
+- `api`:API 名称。
+- `data`:预期的请求数据。
+- `result`:`call_api` 的返回值,将会返回给插件。
+- `**kwargs`:`call_api` 方法的额外参数。
+
+
+ 示例插件
+
+```python
+from nonebot import on_message
+from nonebot.adapters import Bot
+
+foo = on_message()
+
+
+@foo.handle()
+async def _(bot: Bot):
+ await bot.example_api(test="test")
+```
+
+
+
+```python {12}
+import pytest
+from nonebug import App
+
+@pytest.mark.asyncio
+async def test_matcher(app: App, load_plugins):
+ from awesome_bot.plugins.example import foo
+
+ async with app.test_matcher(foo) as ctx:
+ bot = ctx.create_bot()
+ event = make_fake_event()() # 此处替换为平台事件
+ ctx.receive_event(bot, event)
+ ctx.should_call_api("example_api", {"test": "test"}, True)
+```
diff --git a/website/versioned_docs/version-2.0.0-beta.5/api/.gitkeep b/website/versioned_docs/version-2.0.0-beta.5/api/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/website/versioned_docs/version-2.0.0-beta.5/api/adapters/_category_.json b/website/versioned_docs/version-2.0.0-beta.5/api/adapters/_category_.json
new file mode 100644
index 00000000..a2253e3d
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/api/adapters/_category_.json
@@ -0,0 +1,3 @@
+{
+ "position": 15
+}
diff --git a/website/versioned_docs/version-2.0.0-beta.5/api/adapters/index.md b/website/versioned_docs/version-2.0.0-beta.5/api/adapters/index.md
new file mode 100644
index 00000000..2e7fd501
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/api/adapters/index.md
@@ -0,0 +1,619 @@
+---
+sidebar_position: 0
+description: nonebot.adapters 模块
+---
+
+# nonebot.adapters
+
+本模块定义了协议适配基类,各协议请继承以下基类。
+
+使用 [Driver.register_adapter](../drivers/index.md#Driver-register_adapter) 注册适配器。
+
+## _abstract class_ `Bot(adapter, self_id)` {#Bot}
+
+- **说明**
+
+ Bot 基类。
+
+ 用于处理上报消息,并提供 API 调用接口。
+
+- **参数**
+
+ - `adapter` (Adapter): 协议适配器实例
+
+ - `self_id` (str): 机器人 ID
+
+### _property_ `config` {#Bot-config}
+
+- **类型:** [Config](../config.md#Config)
+
+- **说明:** 全局 NoneBot 配置
+
+### _property_ `type` {#Bot-type}
+
+- **类型:** str
+
+- **说明:** 协议适配器名称
+
+### _async method_ `call_api(self, api, **data)` {#Bot-call_api}
+
+- **说明**
+
+ 调用机器人 API 接口,可以通过该函数或直接通过 bot 属性进行调用
+
+- **参数**
+
+ - `api` (str): API 名称
+
+ - `**data` (Any): API 数据
+
+- **返回**
+
+ - Any
+
+- **用法**
+
+ ```python
+ await bot.call_api("send_msg", message="hello world")
+ await bot.send_msg(message="hello world")
+ ```
+
+### _classmethod_ `on_called_api(cls, func)` {#Bot-on_called_api}
+
+- **说明**
+
+ 调用 api 后处理。
+
+ 钩子函数参数:
+
+ - bot: 当前 bot 对象
+ - exception: 调用 api 时发生的错误
+ - api: 调用的 api 名称
+ - data: api 调用的参数字典
+ - result: api 调用的返回
+
+- **参数**
+
+ - `func` ((Bot, Exception | None, str, dict[str, Any], Any) -> Awaitable[Any])
+
+- **返回**
+
+ - (Bot, Exception | None, str, dict[str, Any], Any) -> Awaitable[Any]
+
+### _classmethod_ `on_calling_api(cls, func)` {#Bot-on_calling_api}
+
+- **说明**
+
+ 调用 api 预处理。
+
+ 钩子函数参数:
+
+ - bot: 当前 bot 对象
+ - api: 调用的 api 名称
+ - data: api 调用的参数字典
+
+- **参数**
+
+ - `func` ((Bot, str, dict[str, Any]) -> Awaitable[Any])
+
+- **返回**
+
+ - (Bot, str, dict[str, Any]) -> Awaitable[Any]
+
+### _abstract async method_ `send(self, event, message, **kwargs)` {#Bot-send}
+
+- **说明**
+
+ 调用机器人基础发送消息接口
+
+- **参数**
+
+ - `event` (Event): 上报事件
+
+ - `message` (str | Message | MessageSegment): 要发送的消息
+
+ - `**kwargs` (Any): 任意额外参数
+
+- **返回**
+
+ - Any
+
+## _abstract class_ `Event(**extra_data)` {#Event}
+
+- **说明**
+
+ Event 基类。提供获取关键信息的方法,其余信息可直接获取。
+
+- **参数**
+
+ - `**extra_data` (Any)
+
+### _abstract method_ `get_event_description(self)` {#Event-get_event_description}
+
+- **说明**
+
+ 获取事件描述的方法,通常为事件具体内容。
+
+- **返回**
+
+ - str
+
+### _abstract method_ `get_event_name(self)` {#Event-get_event_name}
+
+- **说明**
+
+ 获取事件名称的方法。
+
+- **返回**
+
+ - str
+
+### _method_ `get_log_string(self)` {#Event-get_log_string}
+
+- **说明**
+
+ 获取事件日志信息的方法。
+
+ 通常你不需要修改这个方法,只有当希望 NoneBot 隐藏该事件日志时,可以抛出 `NoLogException` 异常。
+
+- **返回**
+
+ - str
+
+- **异常**
+
+ NoLogException
+
+### _abstract method_ `get_message(self)` {#Event-get_message}
+
+- **说明**
+
+ 获取事件消息内容的方法。
+
+- **返回**
+
+ - Message
+
+### _method_ `get_plaintext(self)` {#Event-get_plaintext}
+
+- **说明**
+
+ 获取消息纯文本的方法。
+
+ 通常不需要修改,默认通过 `get_message().extract_plain_text` 获取。
+
+- **返回**
+
+ - str
+
+### _abstract method_ `get_session_id(self)` {#Event-get_session_id}
+
+- **说明**
+
+ 获取会话 id 的方法,用于判断当前事件属于哪一个会话,通常是用户 id、群组 id 组合。
+
+- **返回**
+
+ - str
+
+### _abstract method_ `get_type(self)` {#Event-get_type}
+
+- **说明**
+
+ 获取事件类型的方法,类型通常为 NoneBot 内置的四种类型。
+
+- **返回**
+
+ - str
+
+### _abstract method_ `get_user_id(self)` {#Event-get_user_id}
+
+- **说明**
+
+ 获取事件主体 id 的方法,通常是用户 id 。
+
+- **返回**
+
+ - str
+
+### _abstract method_ `is_tome(self)` {#Event-is_tome}
+
+- **说明**
+
+ 获取事件是否与机器人有关的方法。
+
+- **返回**
+
+ - bool
+
+### _classmethod_ `validate(cls, value)` {#Event-validate}
+
+- **参数**
+
+ - `value` (Any)
+
+- **返回**
+
+ - E
+
+## _abstract class_ `Adapter(driver, **kwargs)` {#Adapter}
+
+- **说明**
+
+ 协议适配器基类。
+
+ 通常,在 Adapter 中编写协议通信相关代码,如: 建立通信连接、处理接收与发送 data 等。
+
+- **参数**
+
+ - `driver` (nonebot.internal.driver.driver.Driver): [Driver](../drivers/index.md#Driver) 实例
+
+ - `**kwargs` (Any): 其他由 [Driver.register_adapter](../drivers/index.md#Driver-register_adapter) 传入的额外参数
+
+### _property_ `config` {#Adapter-config}
+
+- **类型:** [Config](../config.md#Config)
+
+- **说明:** 全局 NoneBot 配置
+
+### _method_ `bot_connect(self, bot)` {#Adapter-bot_connect}
+
+- **说明**
+
+ 告知 NoneBot 建立了一个新的 [Bot](#Bot) 连接。
+
+ 当有新的 [Bot](#Bot) 实例连接建立成功时调用。
+
+- **参数**
+
+ - `bot` (nonebot.internal.adapter.bot.Bot): [Bot](#Bot) 实例
+
+- **返回**
+
+ - None
+
+### _method_ `bot_disconnect(self, bot)` {#Adapter-bot_disconnect}
+
+- **说明**
+
+ 告知 NoneBot [Bot](#Bot) 连接已断开。
+
+ 当有 [Bot](#Bot) 实例连接断开时调用。
+
+- **参数**
+
+ - `bot` (nonebot.internal.adapter.bot.Bot): [Bot](#Bot) 实例
+
+- **返回**
+
+ - None
+
+### _abstract classmethod_ `get_name(cls)` {#Adapter-get_name}
+
+- **说明**
+
+ 当前协议适配器的名称
+
+- **返回**
+
+ - str
+
+### _async method_ `request(self, setup)` {#Adapter-request}
+
+- **说明**
+
+ 进行一个 HTTP 客户端请求
+
+- **参数**
+
+ - `setup` (nonebot.internal.driver.model.Request)
+
+- **返回**
+
+ - nonebot.internal.driver.model.Response
+
+### _method_ `setup_http_server(self, setup)` {#Adapter-setup_http_server}
+
+- **说明**
+
+ 设置一个 HTTP 服务器路由配置
+
+- **参数**
+
+ - `setup` (nonebot.internal.driver.model.HTTPServerSetup)
+
+- **返回**
+
+ - Unknown
+
+### _method_ `setup_websocket_server(self, setup)` {#Adapter-setup_websocket_server}
+
+- **说明**
+
+ 设置一个 WebSocket 服务器路由配置
+
+- **参数**
+
+ - `setup` (nonebot.internal.driver.model.WebSocketServerSetup)
+
+- **返回**
+
+ - Unknown
+
+### _method_ `websocket(self, setup)` {#Adapter-websocket}
+
+- **说明**
+
+ 建立一个 WebSocket 客户端连接请求
+
+- **参数**
+
+ - `setup` (nonebot.internal.driver.model.Request)
+
+- **返回**
+
+ - AsyncGenerator[nonebot.internal.driver.model.WebSocket, NoneType]
+
+## _abstract class_ `Message(message=None)` {#Message}
+
+- **说明**
+
+ 消息数组
+
+- **参数**
+
+ - `message` (str | NoneType | Iterable[(~ TMS)] | (~ TMS)): 消息内容
+
+### _method_ `append(self, obj)` {#Message-append}
+
+- **说明**
+
+ 添加一个消息段到消息数组末尾。
+
+- **参数**
+
+ - `obj` (str | (~ TMS)): 要添加的消息段
+
+- **返回**
+
+ - (~ TM)
+
+### _method_ `copy(self)` {#Message-copy}
+
+- **返回**
+
+ - (~ TM)
+
+### _method_ `count(self, value)` {#Message-count}
+
+- **参数**
+
+ - `value` ((~ TMS) | str)
+
+- **返回**
+
+ - int
+
+### _method_ `extend(self, obj)` {#Message-extend}
+
+- **说明**
+
+ 拼接一个消息数组或多个消息段到消息数组末尾。
+
+- **参数**
+
+ - `obj` ((~ TM) | Iterable[(~ TMS)]): 要添加的消息数组
+
+- **返回**
+
+ - (~ TM)
+
+### _method_ `extract_plain_text(self)` {#Message-extract_plain_text}
+
+- **说明**
+
+ 提取消息内纯文本消息
+
+- **返回**
+
+ - str
+
+### _method_ `get(self, type_, count=None)` {#Message-get}
+
+- **参数**
+
+ - `type_` (str)
+
+ - `count` (int | None)
+
+- **返回**
+
+ - (~ TM)
+
+### _abstract classmethod_ `get_segment_class(cls)` {#Message-get_segment_class}
+
+- **说明**
+
+ 获取消息段类型
+
+- **返回**
+
+ - Type[(~ TMS)]
+
+### _method_ `index(self, value, *args)` {#Message-index}
+
+- **参数**
+
+ - `value` ((~ TMS) | str)
+
+ - `*args`
+
+- **返回**
+
+ - int
+
+### _classmethod_ `template(cls, format_string)` {#Message-template}
+
+- **说明**
+
+ 创建消息模板。
+
+ 用法和 `str.format` 大致相同, 但是可以输出消息对象, 并且支持以 `Message` 对象作为消息模板
+
+ 并且提供了拓展的格式化控制符, 可以用适用于该消息类型的 `MessageSegment` 的工厂方法创建消息
+
+- **参数**
+
+ - `format_string` (str | (~ TM)): 格式化模板
+
+- **返回**
+
+ - nonebot.internal.adapter.template.MessageTemplate[(~ TM)]: 消息格式化器
+
+## _abstract class_ `MessageSegment(type, data=)` {#MessageSegment}
+
+- **说明**
+
+ 消息段基类
+
+- **参数**
+
+ - `type` (str)
+
+ - `data` (dict[str, Any])
+
+### _method_ `copy(self)` {#MessageSegment-copy}
+
+- **返回**
+
+ - (~ T)
+
+### _method_ `get(self, key, default=None)` {#MessageSegment-get}
+
+- **参数**
+
+ - `key` (str)
+
+ - `default` (Any)
+
+- **返回**
+
+ - Unknown
+
+### _abstract classmethod_ `get_message_class(cls)` {#MessageSegment-get_message_class}
+
+- **说明**
+
+ 获取消息数组类型
+
+- **返回**
+
+ - Type[(~ TM)]
+
+### _abstract method_ `is_text(self)` {#MessageSegment-is_text}
+
+- **说明**
+
+ 当前消息段是否为纯文本
+
+- **返回**
+
+ - bool
+
+### _method_ `items(self)` {#MessageSegment-items}
+
+- **返回**
+
+ - Unknown
+
+### _method_ `keys(self)` {#MessageSegment-keys}
+
+- **返回**
+
+ - Unknown
+
+### _method_ `values(self)` {#MessageSegment-values}
+
+- **返回**
+
+ - Unknown
+
+## _class_ `MessageTemplate(template, factory=str)` {#MessageTemplate}
+
+- **说明**
+
+ 消息模板格式化实现类。
+
+- **参数**
+
+ - `template`: 模板
+
+ - `factory`: 消息类型工厂,默认为 `str`
+
+### _method_ `add_format_spec(self, spec, name=None)` {#MessageTemplate-add_format_spec}
+
+- **参数**
+
+ - `spec` ((~ FormatSpecFunc_T))
+
+ - `name` (str | None)
+
+- **返回**
+
+ - (~ FormatSpecFunc_T)
+
+### _method_ `format(self, *args, **kwargs)` {#MessageTemplate-format}
+
+- **说明**
+
+ 根据传入参数和模板生成消息对象
+
+- **参数**
+
+ - `*args`
+
+ - `**kwargs`
+
+- **返回**
+
+ - Unknown
+
+### _method_ `format_field(self, value, format_spec)` {#MessageTemplate-format_field}
+
+- **参数**
+
+ - `value` (Any)
+
+ - `format_spec` (str)
+
+- **返回**
+
+ - Any
+
+### _method_ `format_map(self, mapping)` {#MessageTemplate-format_map}
+
+- **说明**
+
+ 根据传入字典和模板生成消息对象, 在传入字段名不是有效标识符时有用
+
+- **参数**
+
+ - `mapping` (Mapping[str, Any])
+
+- **返回**
+
+ - (~ TF)
+
+### _method_ `vformat(self, format_string, args, kwargs)` {#MessageTemplate-vformat}
+
+- **参数**
+
+ - `format_string` (str)
+
+ - `args` (Sequence[Any])
+
+ - `kwargs` (Mapping[str, Any])
+
+- **返回**
+
+ - (~ TF)
diff --git a/website/versioned_docs/version-2.0.0-beta.5/api/config.md b/website/versioned_docs/version-2.0.0-beta.5/api/config.md
new file mode 100644
index 00000000..25ef2f9d
--- /dev/null
+++ b/website/versioned_docs/version-2.0.0-beta.5/api/config.md
@@ -0,0 +1,194 @@
+---
+sidebar_position: 1
+description: nonebot.config 模块
+---
+
+# nonebot.config
+
+本模块定义了 NoneBot 本身运行所需的配置项。
+
+NoneBot 使用 [`pydantic`](https://pydantic-docs.helpmanual.io/) 以及 [`python-dotenv`](https://saurabh-kumar.com/python-dotenv/) 来读取配置。
+
+配置项需符合特殊格式或 json 序列化格式。详情见 [`pydantic Field Type`](https://pydantic-docs.helpmanual.io/usage/types/) 文档。
+
+## _class_ `Env(_env_file='