XZCLOUD/开发文档
下载 .md 文档中心 返回首页
文档中心

插件开发文档

docs/插件开发文档.md · 9.6 KB · 更新于 2026-10-14 20:45

XZCLOUD · 插件开发文档

版本 v1.0.1 · 本平台支持两类插件:PHP 插件(原生)与 Python 插件(AstrBot 原生写法,强兼容) 每次插件能力变更必须同步更新本文档

1. 插件布局

text
plugins/            # PHP 插件
└── <作者>/<插件名>/
    ├── main.php            # 入口(必须)
    ├── metadata.json       # 元数据(必须)
    └── _conf_schema.json   # 配置 schema(可选,后台自动渲染表单)

plugins_py/         # Python 插件(AstrBot 原生写法)
└── <作者>/<插件名>/
    ├── main.py             # 入口(必须)
    ├── metadata.json       # 元数据(必须)
    └── _conf_schema.json   # 配置 schema(可选)

创建后在后台「插件管理 → 重新扫描目录」即可看到并启用。也可以打成 zip 在「插件市场」在线安装。

metadata.json

json
{
  "name": "HelloWorld",
  "desc": "打招呼示例插件",
  "version": "1.0.0",
  "author": "XZQQ",
  "repo": "https://github.com/your/repo"
}

_conf_schema.json(可选)

json
{
  "reply_prefix": { "type": "string", "description": "回复前缀", "default": "【XZCLOUD】" },
  "max_len":      { "type": "int",    "description": "最大长度", "default": 100 },
  "enabled_extra":{ "type": "bool",   "description": "附加功能", "default": true }
}

支持 type: string|int|float|bool,后台「插件管理 → 配置」自动生成表单,保存后热加载。

2. PHP 插件

2.1 最小示例(plugins/XZQQ/HelloWorld/main.php)

php
<?php
declare(strict_types=1);

use XZQQ\Event\MessageChain;
use XZQQ\Event\MessageEvent;
use XZQQ\Plugin\Filter;
use XZQQ\Plugin\PluginBase;

return new class extends PluginBase {

    #[Filter\Command('hello', alias: ['hi', '你好'],
        description: '打招呼',
        usage: '/hello [名字]')]
    public function onHello(MessageEvent $event): MessageChain
    {
        $name = $event->arg('name', '世界');       // 带参指令自动注入
        return MessageChain::plain($this->config('reply_prefix', '【XZCLOUD】') . " 你好,{$name}!");
    }

    #[Filter\Command('dice')]
    public function onDice(MessageEvent $event): MessageChain
    {
        return MessageChain::plain('🎲 你掷出了 ' . random_int(1, 6) . ' 点');
    }

    #[Filter\Command('admin', permission: 'admin')]
    #[Filter\PermissionType('admin')]
    public function onAdmin(MessageEvent $event): MessageChain
    {
        return MessageChain::plain('管理员专属指令');
    }

    #[Filter\Regex('/天气|下雨|气温/u')]
    public function onWeather(MessageEvent $event): MessageChain
    {
        return MessageChain::plain('今天晴,25℃');
    }

    #[Filter\EventMessageType('GROUP_MESSAGE')]
    public function onGroup(MessageEvent $event): MessageChain
    {
        if (!$event->isAtBot()) return MessageChain::empty();  // 未@不处理
        return MessageChain::at($event->senderId)->plain(' 在的');
    }
};

要点:

  • main.php return 一个 PluginBase 子类实例(匿名类即可)
  • 指令参数:带参方法(除 MessageEvent 外的形参)自动从消息文本按顺序注入
  • 返回值:MessageChain(也可 void 不回复)
  • $this->config('key', $default) 读取 _conf_schema.json 配置

2.2 过滤器(PHP 属性)

属性参数(按序)说明
#[Filter\Command]name, alias[], description, usage, needAt, permission指令;前缀 / ! ! # # . .;needAt 群聊需@
#[Filter\CommandGroup]name, alias[]指令组(子指令 group sub)
#[Filter\Regex]pattern正则匹配,捕获组注入形参
#[Filter\EventMessageType]GROUP_MESSAGE/PRIVATE_MESSAGE/ALL事件类型过滤
#[Filter\PlatformAdapterType]napcat/qqofficial/telegram/discord平台过滤
#[Filter\PermissionType]admin/everyone/...权限过滤
#[Filter\CustomFilter]自定义过滤器类高级扩展

2.3 MessageChain 常用构造

php
MessageChain::plain('文本');
MessageChain::image($url, $name);
MessageChain::video($url, $name);
MessageChain::record($url);                 // 语音
MessageChain::file($url, $name);
MessageChain::face(123);                    // QQ 表情 ID
MessageChain::at($userId);
MessageChain::atAll();
MessageChain::reply($messageId);
MessageChain::empty();                      // 不回复

2.4 生命周期与调试

  • onLoad(array $meta):插件加载时(每次进程启动)
  • onInit():配置注入后
  • 后台「插件管理」显示 plugins.error(加载异常会写入,便于定位)
  • CLI:php bin/xzqq plugin list 查看已加载插件与指令

3. Python 插件(AstrBot 原生写法 · 强兼容)

3.1 兼容原理

平台内置 bridge/shim/astrbot/,提供与 AstrBot 同名同路径 的 API 包(from astrbot.api import star 等)。桥接进程把它放在 sys.path[0],因此 AstrBot 插件源码几乎原样可运行,无需改造、无需安装 AstrBot 依赖。

桥接进程通过 ws://127.0.0.1:9527/ws?role=bridge&token=<bridge_token> 与 PHP 守护进程互联:

  • 插件加载/卸载/启用态由 PHP 侧 plugins 表驱动(3 秒 diff 推送)
  • 插件回复经 result 帧回传,由 PHP 侧重建消息链并发送

3.2 最小示例(plugins_py/XZQQ/HelloWorldPy/main.py)

python
from astrbot.api import star
from astrbot.api.event import filter, AstrMessageEvent

@star.register(name="helloworld_py", desc="打招呼示例", version="1.0.0", author="XZQQ")
class Main(star.Star):
    '''插件主类:类名建议叫 Main;可带 (context) 形参接收上下文'''

    def __init__(self, context):
        super().__init__(context)
        self.prefix = self.context.get_config().get("reply_prefix", "【XZCLOUD】")

    @filter.command("hello", alias={"你好", "hi"})
    async def hello(self, event: AstrMessageEvent, name: str = "世界"):
        '''带参指令:name 自动从指令参数注入;默认值支持'''
        yield event.plain_result(f"{self.prefix} 你好,{name}!")

    @filter.command("ping")
    async def ping(self, event: AstrMessageEvent):
        event.stop_event()            # 阻止后续插件处理
        yield event.plain_result("pong")

    @filter.regex(r"^(?:今天|明天)?天气.*")
    async def weather(self, event: AstrMessageEvent):
        yield event.plain_result("今天晴,25℃")

    @filter.permission_type(filter.PermissionType.ADMIN)
    @filter.command("pyinfo")
    async def pyinfo(self, event: AstrMessageEvent):
        yield event.plain_result("管理员信息")

    async def initialize(self):   # 生命周期:加载完成后调用
        pass

    async def terminate(self):    # 生命周期:卸载/停用时调用
        pass

3.3 兼容 API 速查

AstrBot 原生写法本平台状态
from astrbot.api import star / @star.register✅
from astrbot.api.event import filter, AstrMessageEvent✅
@filter.command(name, alias={...}) / command_group / regex✅
@filter.event_message_type(EventMessageType.X)✅
@filter.platform_adapter_type(PlatformAdapterType.X)✅(napcat→AIOCQHTTP 等已映射)
@filter.permission_type(PermissionType.ADMIN)✅(管理员名单在后台 settings.admin_ids)
GreedyStr(吃掉剩余全部参数)✅
event.send(chain) / event.plain_result() / event.chain_result() / event.make_result()✅
event.image_result()/at_result()/reply_result()/face_result()✅
event.stop_event() / 返回 EventResultType✅
from astrbot.core.star... 等 core 导入路径✅(已做 re-export)
消息组件 Plain/Image/At/Reply/Face/Node/Json...✅
initialize()/terminate() 生命周期✅
self.context.get_config()✅(读取本插件配置 + 全局配置)
LLM / Provider / TTS 等 AI 能力❌ 本平台未内置,需自行实现 HTTP 调用
自定义 filter 类⚠️ 可运行,但指令无法静态上报到后台

3.4 指令前缀与参数

  • 前缀:/ ! ! # # . .(与 AstrBot 一致)
  • 匹配逻辑与 PHP 侧 PluginManager::matchCommand() 完全一致
  • 参数按方法签名注入:字符串按空格切分;缺失必填参数则不触发;GreedyStr 聚合剩余
  • 指令元数据(名称/别名/说明)通过 AST 静态扫描在 hello 时上报,后台「指令管理」可见并可同步到 QQ 官方

3.5 调试

bash
cd bridge
python3 astrbot_bridge.py --selftest      # 本地自检:强制加载插件并回放 3 条测试消息
python3 astrbot_bridge.py --verbose       # 前台运行并打印收发帧

桥接配置 bridge/config.json:daemon_host/daemon_port/path/bridge_token/plugins_dir/handler_timeout;令牌须与 PHP 侧 config/app.php 的 plugin.bridge_token 一致。

4. 推荐实践

  1. 指令必须写 description/usage,后台指令面板与 /help 才能正常展示
  2. 敏感配置放 _conf_schema.json,由后台表单管理,勿硬编码密钥
  3. 网络请求加超时(插件 handler 有 30s 总超时,见 handler_timeout)
  4. 群聊指令建议 needAt: true,避免打扰
  5. 插件的重活放后台线程/队列,勿阻塞事件循环(Python 侧用 await,PHP 侧同步执行需自行控制耗时)