插件系统的使用¶
匿名插件¶
在之前的例子中,我们通过实例化 PluginPlanner
创建了一个插件管理器,并向其中添加“处理流”(我们的函数经过绑定方法装饰后将会生成“处理流对象”)。随后又使用 load_plugin()
将插件加载在 bot 中:
from melobot import PluginPlanner
@on_start_match(".sayhi")
async def echo_hi() -> None:
await send_text("Hello, melobot!")
# echo_hi 这个事件处理函数,经过 on_xxx 方法装饰,实际上变为一个“处理流”对象
test_plugin = PluginPlanner(version="1.0.0", flows=[echo_hi])
if __name__ == "__main__":
# 此处省略创建 bot 等代码
...
bot.load_plugin(test_plugin)
这实际上是创建了“匿名插件”并加载。一般用作临时性调试用途。在复杂的实际项目中,可能有很多功能要分别写到不同的插件中,方便管理和维护。此时再这样创建插件就不再合适。
下面我们将介绍如何通过模块为载体,来声明和加载插件。
提示
关于“处理流”的更多内容,未来的教程我们将会详细说明。
模块级插件的声明¶
在任意目录中,创建子目录作为“插件目录”,例如下面例子中的 test_plugin
:
./
└── test_plugin
插件目录的名称,将被 melobot 识别为插件的名称,同时也是加载时的唯一 id。因此请不要为一个 bot 加载两个同目录名的插件,这将会导致加载错误异常。
随后,插件管理器对象,需要存在于该目录中的 __plugin__.py
文件(一般称为插件入口文件)中:
./
└── test_plugin
└── __plugin__.py
# __plugin__.py 内:
from melobot import PluginPlanner
@on_start_match(".sayhi")
async def echo_hi() -> None:
...
# 变量命名为任意名称都可以,这并不影响加载过程
# 但我们建议使用常量命名规范,并为:"XXX_PLUGIN" 或 "PLUGIN"
ECHO_PLUGIN = PluginPlanner(version="1.0.0", flows=[echo_hi])
除了 插件目录中必须存在 __plugin__.py
,插件管理器对象必须存在于 __plugin__.py
中 这两条规则,其余的组件可以自由地划分到插件目录的其他模块中,甚至任意深度子目录中的子模块也没有问题。
./
├── flow2.py
├── more_flows
│ └── flow3.py
└── __plugin__.py
# __plugin__.py 内:
from melobot import PluginPlanner
from .flow2 import another_echo_hi
from .more_flows.flow3 import third_echo_hi
@on_start_match(".sayhi")
async def echo_hi() -> None:
...
ECHO_PLUGIN = PluginPlanner(
version="1.0.0",
# 如果需要,就加到插件管理器中;不需要就甚至不用导入咯~
flows=[echo_hi, another_echo_hi, third_echo_hi]
)
在某些情况下,先通过 PluginPlanner
创建插件管理器对象,再使用会较为方便。
但问题是,如果先创建插件管理器,此时处理流显然尚未就位。因此我们提供了 use()
装饰器用于解决此问题:
# __plugin__.py 内:
from melobot import PluginPlanner
ECHO_PLUGIN = PluginPlanner(version="1.0.0")
@ECHO_PLUGIN.use
@on_start_match(".sayhi")
async def echo_hi() -> None:
...
提示
一般情况下,请勿在插件目录内手动创建 __init__.py
文件。
在之后的教程中会详细说明为什么不要这样做,以及与此相关的插件加载机制与插件高级用法。
模块级插件的加载¶
在目前阶段,只需要学会通过插件目录的路径加载插件,就可以了:
# 在创建 bot 后使用,提供插件目录的相对或绝对路径:
bot.load_plugin("test_plugin")
# 或
bot.load_plugin("./test_plugin")
# 或
bot.load_plugin("/home/test_user/my_bot/test_plugin")
总结¶
本篇主要说明了插件系统的简单使用方法。
下一篇将重点说明:简单的交互式事件处理与会话。