mirror of
				https://github.com/nonebot/nonebot2.git
				synced 2025-10-31 06:56:39 +00:00 
			
		
		
		
	🔀 Merge pull request #204
This commit is contained in:
		
							
								
								
									
										117
									
								
								archive/2.0.0a10/advanced/export-and-require.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								archive/2.0.0a10/advanced/export-and-require.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | |||||||
|  | # 跨插件访问 | ||||||
|  |  | ||||||
|  | 由于 `nonebot2` 独特的插件加载机制,在使用 python 原有的 import 机制来进行插件之间的访问时,很可能会有奇怪的或者意料以外的情况发生。为了避免这种情况的发生,您可以有两种方法来实现跨插件访问: | ||||||
|  |  | ||||||
|  | 1. 将插件间的要使用的公共代码剥离出来,作为公共文件或者文件夹,提供给插件加以调用。 | ||||||
|  | 2. 使用 `nonebot2` 提供的 `export` 和 `require` 机制,来实现插件间的互相调用。 | ||||||
|  |  | ||||||
|  | 第一种方法比较容易理解和实现,这里不再赘述,但需要注意的是,请不要将公共文件或者公共文件夹作为**插件**被 `nonebot2` 加载。 | ||||||
|  |  | ||||||
|  | 下面将介绍第二种方法—— `export` 和 `require` 机制: | ||||||
|  |  | ||||||
|  | ## 使用 export and require | ||||||
|  |  | ||||||
|  | 现在,假定有两个插件 `pluginA` 和 `pluginB`,需要在 `pluginB` 中调用 `pluginA` 中的一个变量 `varA` 和一个函数 `funcA`。 | ||||||
|  |  | ||||||
|  | 在上面的条件中涉及到了两种操作:一种是在 `pluginA` 的 `导出对象` 操作;而另一种是在 `pluginB` 的 `导入对象` 操作。在 `nonebot2` 中,`导出对象` 的操作用 `export` 机制来实现,`导入对象` 的操作用 `require` 机制来实现。下面,我们将逐一进行介绍。 | ||||||
|  |  | ||||||
|  | :::warning 警告 | ||||||
|  |  | ||||||
|  | 使用这个方法进行跨插件访问时,**需要先加载`导出对象`的插件,再加载`导入对象`的插件。** | ||||||
|  |  | ||||||
|  | ::: | ||||||
|  |  | ||||||
|  | ### 使用 export | ||||||
|  |  | ||||||
|  | 在 `pluginA` 中,我们调用 `export` 机制 `导出对象`。 | ||||||
|  |  | ||||||
|  | 在 `export` 机制调用前,我们需要保证导出的对象已经被定义,比如: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | varA = "varA" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def funcA(): | ||||||
|  |     return "funcA" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 在确保定义之后,我们可以从 `nonebot.plugin` 导入 `export()` 方法, `export()` 方法会返回一个特殊的字典 `export`: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | from nonebot.plugin import export | ||||||
|  |  | ||||||
|  | export=export() | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 这个字典可以用来装载导出的对象,它的 key 是对象导出后的命名,value 是对象本身,我们可以直接创建新的 `key` - `value` 对导出对象: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | export.vA = varA | ||||||
|  | export.fA = funcA | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 除此之外,也支持 `嵌套` 导出对象: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | export.sub.vA = varA | ||||||
|  | export.sub.fA = funcA | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 特别地,对于 `函数对象` 而言,`export` 支持用 `装饰器` 的方法来导出,因此,我们可以这样定义 `funcA`: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | @export.sub | ||||||
|  | def funcA(): | ||||||
|  |     return "funcA" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 或者: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | @export | ||||||
|  | def funcA(): | ||||||
|  |     return "funcA" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 通过 `装饰器` 的方法导出函数时,命名固定为函数的命名,也就是说,上面的两个例子等同于: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | export.sub.funcA = funcA | ||||||
|  |  | ||||||
|  | export.funcA = funcA | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 这样,我们就成功导出 `varA` 和 `funcA` 对象了。 | ||||||
|  |  | ||||||
|  | 下面我们将介绍如何在 `pluginB` 中导入这些对象。 | ||||||
|  |  | ||||||
|  | ### 使用 require | ||||||
|  |  | ||||||
|  | 在 `pluginB` 中,我们调用 `require` 机制 `导入对象`。 | ||||||
|  |  | ||||||
|  | :::warning 警告 | ||||||
|  |  | ||||||
|  | 在导入来自其他插件的对象时, 请确保导出该对象的插件在引用该对象的插件之前加载。如果该插件并未被加载,则会尝试加载,加载失败则会返回 `None`。 | ||||||
|  |  | ||||||
|  | ::: | ||||||
|  |  | ||||||
|  | 我们可以从 `nonebot.plugin` 中导入 `require()` 方法: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | from nonebot.plugin import require | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | `require()` 方法的参数是插件名, 它会返回在指定插件中,用 `export()` 方法创建的字典。 | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | require_A = require('pluginA') | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 在之前,这个字典已经存入了 `'vA'` - `varA`, `'fA'` - `funcA` 或 `'funcA'` - `funcA` 这样的 `key` - `value` 对。因此在这里我们直接用 `属性` 的方法来获取导入对象: | ||||||
|  |  | ||||||
|  | ```python | ||||||
|  | varA = require_A.vA | ||||||
|  | funcA = require_A.fA or require_A.funcA | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | 这样,我们就在 `pluginB` 中成功导入了 `varA` 和 `funcA` 对象了。 | ||||||
| @@ -43,6 +43,9 @@ | |||||||
|     * [nonebot.drivers.fastapi](drivers/fastapi.html) |     * [nonebot.drivers.fastapi](drivers/fastapi.html) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     * [nonebot.drivers.quart](drivers/quart.html) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     * [nonebot.adapters](adapters/) |     * [nonebot.adapters](adapters/) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -965,15 +965,40 @@ CQHTTP 协议 MessageSegment 适配。具体方法参考 [mirai-api-http 消息 | |||||||
| 
 | 
 | ||||||
| 基类:[`nonebot.adapters.Message`](README.md#nonebot.adapters.Message) | 基类:[`nonebot.adapters.Message`](README.md#nonebot.adapters.Message) | ||||||
| 
 | 
 | ||||||
| Mirai 协议 Messaqge 适配 | Mirai 协议 Message 适配 | ||||||
| 
 | 
 | ||||||
| 由于Mirai协议的Message实现较为特殊, 故使用MessageChain命名 | 由于Mirai协议的Message实现较为特殊, 故使用MessageChain命名 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | ### `reduce()` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | * **说明** | ||||||
|  | 
 | ||||||
|  |     忽略为空的消息段, 合并相邻的纯文本消息段 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ### `export()` | ### `export()` | ||||||
| 
 | 
 | ||||||
| 导出为可以被正常json序列化的数组 | 导出为可以被正常json序列化的数组 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | ### `extract_first(*type)` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | * **说明** | ||||||
|  | 
 | ||||||
|  |     弹出该消息链的第一个消息 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | * **参数** | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |     * \*type: MessageType: 指定的消息类型, 当指定后如类型不匹配不弹出 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # NoneBot.adapters.mirai.utils 模块 | # NoneBot.adapters.mirai.utils 模块 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -1070,20 +1095,6 @@ mirai-api-http 协议事件,字段与 mirai-api-http 一致。各事件字段 | |||||||
| > * `MEMBER`: 普通群成员 | > * `MEMBER`: 普通群成员 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ## _class_ `MessageChain` |  | ||||||
| 
 |  | ||||||
| 基类:[`nonebot.adapters.Message`](README.md#nonebot.adapters.Message) |  | ||||||
| 
 |  | ||||||
| Mirai 协议 Messaqge 适配 |  | ||||||
| 
 |  | ||||||
| 由于Mirai协议的Message实现较为特殊, 故使用MessageChain命名 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ### `export()` |  | ||||||
| 
 |  | ||||||
| 导出为可以被正常json序列化的数组 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ## _class_ `MessageEvent` | ## _class_ `MessageEvent` | ||||||
| 
 | 
 | ||||||
| 基类:`nonebot.adapters.mirai.event.base.Event` | 基类:`nonebot.adapters.mirai.event.base.Event` | ||||||
							
								
								
									
										62
									
								
								archive/2.0.0a10/api/drivers/quart.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								archive/2.0.0a10/api/drivers/quart.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | --- | ||||||
|  | contentSidebar: true | ||||||
|  | sidebarDepth: 0 | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | # NoneBot.drivers.quart 模块 | ||||||
|  |  | ||||||
|  | ## Quart 驱动适配 | ||||||
|  |  | ||||||
|  | 后端使用方法请参考: [Quart 文档](https://pgjones.gitlab.io/quart/index.html) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## _class_ `Driver` | ||||||
|  |  | ||||||
|  | 基类:[`nonebot.drivers.Driver`](README.md#nonebot.drivers.Driver) | ||||||
|  |  | ||||||
|  | Quart 驱动框架 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | * **上报地址** | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     * `/{adapter name}/http`: HTTP POST 上报 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     * `/{adapter name}/ws`: WebSocket 上报 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### _property_ `type` | ||||||
|  |  | ||||||
|  | 驱动名称: `quart` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### _property_ `server_app` | ||||||
|  |  | ||||||
|  | `Quart` 对象 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### _property_ `asgi` | ||||||
|  |  | ||||||
|  | `Quart` 对象 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### _property_ `logger` | ||||||
|  |  | ||||||
|  | fastapi 使用的 logger | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### `on_startup(func)` | ||||||
|  |  | ||||||
|  | 参考文档: [Startup and Shutdown](https://pgjones.gitlab.io/quart/how_to_guides/startup_shutdown.html) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### `on_shutdown(func)` | ||||||
|  |  | ||||||
|  | 参考文档: [Startup and Shutdown](https://pgjones.gitlab.io/quart/how_to_guides/startup_shutdown.html) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### `run(host=None, port=None, *, app=None, **kwargs)` | ||||||
|  |  | ||||||
|  | 使用 `uvicorn` 启动 Quart | ||||||
| @@ -123,7 +123,7 @@ async def async_checker(bot: Bot, event: Event, state: T_State) -> bool: | |||||||
| def sync_checker(bot: Bot, event: Event, state: T_State) -> bool: | def sync_checker(bot: Bot, event: Event, state: T_State) -> bool: | ||||||
|     return True |     return True | ||||||
| 
 | 
 | ||||||
| def check(arg1, args2): | def check(arg1, arg2): | ||||||
| 
 | 
 | ||||||
|     async def _checker(bot: Bot, event: Event, state: T_State) -> bool: |     async def _checker(bot: Bot, event: Event, state: T_State) -> bool: | ||||||
|         return bool(arg1 + arg2) |         return bool(arg1 + arg2) | ||||||
| @@ -6,12 +6,15 @@ | |||||||
| 
 | 
 | ||||||
| 在 `bot.py` 文件中添加以下行: | 在 `bot.py` 文件中添加以下行: | ||||||
| 
 | 
 | ||||||
| ```python{5} | ```python{8} | ||||||
| import nonebot | import nonebot | ||||||
|  | from nonebot.adapters.cqhttp import Bot | ||||||
| 
 | 
 | ||||||
| nonebot.init() | nonebot.init() | ||||||
| # 加载 nonebot 内置插件 | 
 | ||||||
| nonebot.load_builtin_plugins() | driver = nonebot.get_driver() | ||||||
|  | driver.register_adapter("cqhttp", Bot) # 注册 CQHTTP 的 Adapter | ||||||
|  | nonebot.load_builtin_plugins() # 加载 nonebot 内置插件 | ||||||
| 
 | 
 | ||||||
| app = nonebot.get_asgi() | app = nonebot.get_asgi() | ||||||
| 
 | 
 | ||||||
| @@ -19,6 +22,12 @@ if __name__ == "__main__": | |||||||
|     nonebot.run() |     nonebot.run() | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ::: warning | ||||||
|  | 目前, 内建插件仅支持 CQHTTP 的 Adapter | ||||||
|  | 
 | ||||||
|  | 如果您使用的是其他 Adapter, 请移步该 Adapter 相应的文档 | ||||||
|  | ::: | ||||||
|  | 
 | ||||||
| 这将会加载 nonebot 内置的插件,它包含: | 这将会加载 nonebot 内置的插件,它包含: | ||||||
| 
 | 
 | ||||||
| - 命令 `say`:可由**superuser**使用,可以将消息内容由特殊纯文本转为富文本 | - 命令 `say`:可由**superuser**使用,可以将消息内容由特殊纯文本转为富文本 | ||||||
| @@ -193,3 +193,36 @@ Mirai-API-HTTP 的适配器以 [AGPLv3 许可](https://opensource.org/licenses/A | |||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| 恭喜你, 你的配置已经成功! | 恭喜你, 你的配置已经成功! | ||||||
|  | 
 | ||||||
|  | 现在, 我们可以写一个简单的插件来测试一下 | ||||||
|  | 
 | ||||||
|  | ```python | ||||||
|  | from nonebot.plugin import on_keyword, on_command | ||||||
|  | from nonebot.rule import to_me | ||||||
|  | from nonebot.adapters.mirai import Bot, MessageEvent | ||||||
|  | 
 | ||||||
|  | message_test = on_keyword({'reply'}, rule=to_me()) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @message_test.handle() | ||||||
|  | async def _message(bot: Bot, event: MessageEvent): | ||||||
|  |     text = event.get_plaintext() | ||||||
|  |     await bot.send(event, text, at_sender=True) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | command_test = on_command('miecho') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @command_test.handle() | ||||||
|  | async def _echo(bot: Bot, event: MessageEvent): | ||||||
|  |     text = event.get_plaintext() | ||||||
|  |     await bot.send(event, text, at_sender=True) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 它具有两种行为 | ||||||
|  | 
 | ||||||
|  | - 在指定机器人,即私聊、群聊内@机器人、群聊内称呼机器人昵称的情况下 (即 [Rule: to_me](../api/rule.md#to-me)), 如果消息内包含 `reply` 字段, 则该消息会被机器人重复一次 | ||||||
|  | 
 | ||||||
|  | - 在执行指令`miecho xxx`时, 机器人会发送回参数`xxx` | ||||||
|  | 
 | ||||||
|  | 至此, 你已经初步掌握了如何使用 Mirai Adapter | ||||||
| @@ -151,6 +151,10 @@ | |||||||
|                 "title": "nonebot.drivers.fastapi 模块", |                 "title": "nonebot.drivers.fastapi 模块", | ||||||
|                 "path": "drivers/fastapi" |                 "path": "drivers/fastapi" | ||||||
|               }, |               }, | ||||||
|  |               { | ||||||
|  |                 "title": "nonebot.drivers.quart 模块", | ||||||
|  |                 "path": "drivers/quart" | ||||||
|  |               }, | ||||||
|               { |               { | ||||||
|                 "title": "nonebot.adapters 模块", |                 "title": "nonebot.adapters 模块", | ||||||
|                 "path": "adapters/" |                 "path": "adapters/" | ||||||
| @@ -1 +0,0 @@ | |||||||
| # 跨插件访问 |  | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| [ | [ | ||||||
|   "2.0.0a9.post1", |   "2.0.0a10", | ||||||
|   "2.0.0a8.post2", |   "2.0.0a8.post2", | ||||||
|   "2.0.0a7" |   "2.0.0a7" | ||||||
| ] | ] | ||||||
		Reference in New Issue
	
	Block a user