LinkZone 机器人框架使用指南

nanxiafenglai
29
2025-12-18

前言

LinkZone 是一个现代化的机器人框架,采用核心 + 生态系统的架构设计。它支持 Node.js 开发插件和适配器,具有热重载、定时任务、多平台适配等特性。本文将带你从零开始,快速上手 LinkZone。

目录

1. [项目结构](# 项目结构)

2. [快速开始](# 快速开始)

3. [配置说明](# 配置说明)

4. [插件开发](# 插件开发)

5. [适配器开发](# 适配器开发)

6. [SDK API 参考](#sdk-api- 参考)

7. [常见问题](# 常见问题)

---

项目结构

linkzone/

├── data/ # 数据目录

│ ├── config.yaml # 系统配置文件

│ ├── badger/ # 数据库文件

│ └── runtime/ # 运行时文件 (socket 等)

├── ecosystems/ # 生态系统

│ └── nodejs/ # Node.js 运行时

│ ├── adapters/ # 适配器目录

│ ├── plugins/ # 插件目录

│ ├── sdk/ # SDK 库

│ └── runtime.js # Node.js 运行时入口

├── logs/ # 日志目录

└── public/ # 静态文件目录

快速开始

1. 环境要求

- Node.js 16+

- LinkZone 主程序

2. 安装依赖

```bash

cd ecosystems/nodejs

npm install

```

3. 启动框架

启动 LinkZone 主程序后,Node.js 运行时会自动连接并加载插件和适配器。

<!-- [图片: 启动成功的控制台输出] -->

启动成功后,你将看到类似输出:

```

🚀 LinkZone Node.js 统一运行时启动

📡 连接地址: data/runtime/linkzone.sock

📂 扫描插件目录: ecosystems/nodejs/plugins

📦 发现 1 个插件文件

✓ 已加载插件: 青龙面板管理 (v2.0.0)

📂 扫描适配器目录: ecosystems/nodejs/adapters

📦 发现 1 个适配器文件

✓ 已加载适配器: wx (v3.2.0)

🔥 插件热重载已启用

🔥 适配器热重载已启用

✅ 成功启动 1 个插件, 1 个适配器

✅ 运行时准备就绪

```

---

配置说明

系统配置位于 data/config.yaml,采用键值对格式:

```yaml

# 核心配置

- key: system.core.bot_name

  value: "LinkZone"

  type: string

  comment: 机器人名称

- key: system.core.log_level

  value: info

  type: string

  comment: '日志级别 (可选: debug, info, warn, error)'

# HTTP 服务

- key: system.server.http_port

  value: :8080

  type: string

  comment: HTTP 服务器监听的地址和端口

# 管理 Token (请修改为你自己的安全密钥)

- key: system.server.admin_token

  value: "your_secure_token_here"

  type: string

  comment: Web 后台管理 API 的 Bearer Token

# 许可证配置

- key: system.license.key

  value: "YOUR-LICENSE-KEY"

  type: string

  comment: 许可证密钥

- key: system.license.server_url

  value: "https://your-license-server.com"

  type: string

  comment: 授权服务器地址

```

---

插件开发

插件结构

插件存放在 ecosystems/nodejs/plugins/ 目录下,支持两种结构:

```

plugins/

├── 作者名 /

│ ├── plugin-name.js # 单文件插件

│ └── complex-plugin/ # 多文件插件

│ └── index.js

```

元数据注释

每个插件必须在文件头部声明元数据:

```javascript

/**

* @name 示例插件

* @version 1.0.0

* @author YourName

* @description 这是一个示例插件

* @command 测试 // 命令触发器 (完全匹配)

* @keyword 关键词 // 关键词触发器 (包含匹配)

* @rule ^ 正则表达式 $ // 正则触发器

* @admin false // 是否需要管理员权限

* @priority 10 // 优先级 (数字越大越先执行)

* @cron 0 0 8 * * * // 定时任务 (可选)

*/

```

编写第一个插件

创建文件 plugins/demo/hello.js

```javascript

/**

* @name 你好世界

* @version 1.0.0

* @author Demo

* @description 一个简单的示例插件

* @command 你好

* @command hello

*/

module.exports = async function (sender) {

const name = await sender.getSenderName();

await sender.reply你好,${name}!欢迎使用 LinkZone!);

};

```

保存后,框架会自动热重载插件(无需重启)。

使用类形式

对于复杂插件,推荐使用类形式:

/**

 * @name 高级插件

 * @version 1.0.0

 * @author Demo

 * @description 类形式的插件示例

 * @rule ^calc\\s+(.+)$

 */

class CalcPlugin extends Plugin {

    async onStart() {

        console.log('计算器插件已启动');

    }

    async handleMessage(sender) {

        const expr = await sender.param(1);

        

        try {

            // 注意:实际使用请用安全的计算库

            const result = eval(expr);

            await sender.reply计算结果: ${result});

        } catch (e) {

            await sender.reply('表达式错误');

        }

    }

    async onStop() {

        console.log('计算器插件已停止');

    }

}

module.exports = CalcPlugin;

多轮对话

使用 listen() 方法实现多轮对话:

/**

 * @name 问卷调查

 * @version 1.0.0

 * @author Demo

 * @description 多轮对话示例

 * @command 问卷

 */

module.exports = async function (sender) {

    await sender.reply('请问你的名字是?');

    

    const r1 = await sender.listen({ timeout: 30000 });

    if (r1.timeout) return sender.reply('超时了,下次再来吧~');

    

    const name = await r1.sender.getMessage();

    

    await sender.reply${name},请问你的年龄是?);

    

    const r2 = await sender.listen({ timeout: 30000 });

    if (r2.timeout) return sender.reply('超时了~');

    

    const age = await r2.sender.getMessage();

    

    await sender.reply收到!\n姓名: ${name}\n年龄: ${age});

};

### 数据持久化

使用 getData / setData 存储插件数据:

```javascript

/**

* @name 签到插件

* @version 1.0.0

* @author Demo

* @description 每日签到

* @command 签到

*/

module.exports = {

async handleMessage(sender) {

const userId = await sender.getSenderId();

const today = new Date().toDateString();

const key = sign_${userId};

const lastSign = await this.getData(key);

if (lastSign === today) {

return sender.reply('今天已经签到过啦 ~');

}

await this.setData(key, today);

await sender.reply('签到成功!');

}

};

```

### 使用 LZDB

对于更灵活的数据库操作,使用 LZDB

```javascript

const db = new LZDB('my-plugin'); // 创建命名空间

// 基本操作

await db.set('key', { count: 1});

const data = await db.get('key', { count: 0});

await db.delete('key');

const exists = await db.exists('key');

const keys = await db.keys();

await db.clear();

```

---

适配器开发

适配器负责对接不同的消息平台(微信、QQ、Telegram 等)。

适配器结构

适配器存放在 ecosystems/nodejs/adapters/ 目录:

```

adapters/

├── wx.js # 微信适配器

├── qq.js # QQ 适配器

└── telegram.js # Telegram 适配器

```

元数据注释

/**

 * @author YourName

 * @name 适配器名称

 * @version 1.0.0

 * @description 适配器描述

 * @platform platform_id

 * @icon 💬

 * @tags 标签1,标签2

 * 

 * @config-schema {

 *   "apiUrl": {

 *     "type": "string",

 *     "label": "API 地址",

 *     "required": true

 *   },

 *   "token": {

 *     "type": "string",

 *     "label": "访问令牌",

 *     "required": true

 *   }

 * }

 */

适配器示例

/**

 * @name 示例适配器

 * @version 1.0.0

 * @description 适配器开发模板

 * @platform demo

 */

const axios = require('axios');

module.exports = {

    async onStart() {

        // 获取配置

        const config = await this.getConfig();

        

        // 注册 Webhook 路由

        await this.registerRoute('/api/bot/demo', this.handleWebhook.bind(this), 'POST');

        

        console.log('示例适配器已启动');

    },

    async handleWebhook(req) {

        const { user_id, message, group_id } = req.body;

        

        // 推送事件到框架

        await this.pushEvent({

            type: 'message',

            platform: 'demo',

            botId: 'bot001',

            senderId: user_id,

            message: message,

            groupId: group_id || '',

            timestamp: Date.now()

        });

        

        return { status: 200, body: { ok: true } };

    },

    async send(message) {

        const { receiver_id, segments, bot_id } = message;

        

        // 转换消息格式并发送

        const text = segments

            .filter(s => s.type === 'text')

            .map(s => s.data.text)

            .join('');

        

        const config = await this.getConfig();

        await axios.post(config.apiUrl, {

            to: receiver_id,

            content: text

        });

        

        return demo_${Date.now()};

    },

    async onStop() {

        console.log('示例适配器已停止');

    }

};

SDK API 参考

Sender 对象

Sender 是消息上下文,提供了丰富的 API:

#### 消息获取

| 方法 | 返回值 | 说明 |

|------|--------|------|

| getMessage() | string | 获取消息文本 |

| getSenderId() | string | 获取发送者 ID |

| getSenderName() | string | 获取发送者昵称 |

| getPlatform() | string | 获取平台标识 |

| getBotId() | string | 获取机器人 ID |

| getGroupId() | string | 获取群组 ID |

| getMessageId() | string | 获取消息 ID |

| getEvent() | object | 获取完整事件对象 |

状态判断

| 方法 | 返回值 | 说明 |

|------|--------|------|

| isAdmin() | boolean | 是否管理员 |

| isGroup() | boolean | 是否群聊 |

| isPrivate() | boolean | 是否私聊 |

常见问题

### Q: 插件修改后不生效?

A: 框架支持热重载,保存文件后会自动重新加载。如果没有生效,请检查控制台是否有错误输出。

### Q: 如何调试插件?

A: 在代码中使用 console.log() 输出调试信息,日志会显示在控制台中。

### Q: 数据存储在哪里?

A: 数据存储在 data/badger/ 目录的 BadgerDB 数据库中。

### Q: 如何添加新的平台适配?

A: 在 adapters/ 目录创建新的适配器文件,实现 send() 方法和事件推送即可。

### Q: 多个插件的执行顺序?

A: 按 @priority 优先级从高到低执行。相同优先级按加载顺序执行。

---

## 附录

### Cron 表达式

```

┌──────────── 秒 (0-59)

│ ┌────────── 分 (0-59)

│ │ ┌──────── 时 (0-23)

│ │ │ ┌────── 日 (1-31)

│ │ │ │ ┌──── 月 (1-12)

│ │ │ │ │ ┌── 周 (0-6, 0= 周日)

│ │ │ │ │ │

* * * * * *

```

示例:

- 0 0 8 * * * - 每天 8:00

- 0 30 * * * * - 每小时的 30 分

- 0 0 0 1 * * - 每月 1 号 0:00

### 许可证

LinkZone 需要有效的许可证才能运行。请联系开发者获取许可证密钥。

---

> 📝 文档版本: 1.0.0

> 📅 更新时间: 2025-12-17

> 💬 如有问题,欢迎反馈