diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index f55ec94..17c400b 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -8,12 +8,67 @@ export default defineConfig({ themeConfig: { siteTitle: '主页', nav: [ - { text: '快速开始', link: '/start' }, - { text: '开发文档', link: '/develop/index' }, - { text: 'elements', link: '/develop/elements' }, + { + text: '快速开始', + items: [ + { text: '目录', link: '/start/index' }, + { text: '框架', link: '/start/start' }, + { text: '渲染器', link: '/start/Renderer' }, + { text: '适配器', link: '/start/adapter' } + ] + }, + { + text: '事件', + items: [ + { text: '目录', link: '/event/index' }, + { text: '消息事件', link: '/event/message' }, + { text: '通知事件', link: '/event/notice' }, + { text: '请求事件', link: '/event/request' } + ] + }, + { + text: '开发指南', + items: [ + { text: '目录', link: '/develop/index' }, + { text: '插件规范', link: '/develop/standard' }, + { text: '开发插件', link: '/develop/plugin' }, + { text: '开发插件包', link: '/develop/plugins' } + ] + }, + { + text: '开发工具', + items: [ + { text: '目录', link: '/utils/index' }, + { text: 'karin', link: '/utils/karin' }, + { text: 'segment', link: '/utils/segment' }, + { text: 'redis', link: '/utils/redis' }, + { text: 'update', link: '/utils/update' }, + { text: 'YamlEditor', link: '/utils/YamlEditor' }, + { text: 'Renderer', link: '/utils/Renderer' } + ] + }, + { + text: 'Api', + items: [ + { text: '目录', link: '/api/index' }, + { text: 'kritor', link: '/api/kritor' }, + { text: 'OneBot11', link: '/api/OneBot11' } + ] + }, { text: '插件索引', link: '/plugins/index' }, ], sidebar: { + '/start/': [ + { + text: '快速开始', + items: [ + { text: '目录', link: '/start/index' }, + { text: '框架', link: '/start/start' }, + { text: '渲染器', link: '/start/Renderer' }, + { text: '适配器', link: '/start/adapter' } + ], + } + ], '/event/': [ { text: '事件', @@ -27,13 +82,38 @@ export default defineConfig({ { text: '插件开发', items: [ - { text: 'elements', link: '/develop/elements' }, - { text: '#karin', link: '/develop/karin' }, - { text: 'YamlEditor', link: '/develop/YamlEditor' }, - { text: '插件编写', link: '/develop/plugin' }, + { text: '目录', link: '/develop/index' }, + { text: '插件规范', link: '/develop/standard' }, + { text: '开发插件', link: '/develop/plugin' }, + { text: '开发插件包', link: '/develop/plugins' } + ] + } + ], + '/utils/': [ + { + text: '开发工具', + items: [ + { text: 'karin', link: '/utils/karin' }, + { text: 'segment', link: '/utils/segment' }, + { text: 'logger', link: '/utils/logger' }, + { text: 'common', link: '/utils/common' }, + { text: 'redis', link: '/utils/redis' }, + { text: 'update', link: '/utils/update' }, + { text: 'YamlEditor', link: '/utils/YamlEditor' }, + { text: 'Renderer', link: '/utils/Renderer' } ] } - ] + ], + '/api/': [ + { + text: 'Api', + items: [ + { text: '目录', link: '/api/index' }, + { text: 'kritor', link: '/api/kritor' }, + { text: 'OneBot11', link: '/api/OneBot11' } + ], + } + ], }, socialLinks: [ { icon: 'github', link: 'https://github.com/KarinJS/Karin' } diff --git a/docs/develop.md b/docs/Renderer/Renderer.md similarity index 100% rename from docs/develop.md rename to docs/Renderer/Renderer.md diff --git a/docs/api/OneBot11.md b/docs/api/OneBot11.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/api/index.md b/docs/api/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/api/kritor.md b/docs/api/kritor.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/develop/index.md b/docs/develop/index.md index bb7ba40..43b39d5 100644 --- a/docs/develop/index.md +++ b/docs/develop/index.md @@ -1,7 +1,7 @@ # 编写插件 - ## 目录 + [普通插件编写](./plugin.md) [插件包编写](./plugins.md) @@ -19,20 +19,21 @@ > 推荐安装 `ESLint` 扩展插件进行语法格式检查`(需安装开发依赖,pnpm install)` ## 命名规范 -- 单个js插件:请尽量使用英文进行命名,方便开发者跟踪日志。 + +- 单个js插件:请使用英文进行命名,方便开发者跟踪日志。 - 插件包:要求以 `kritor-plugin-` 开头,后面跟上插件名,如 `kritor-plugin-hello-world`。 - 可在仓库标签添加 `karin` 、 `karin-plugin` 等标签,方便用户搜索。 - `plugins`目录只识别以 `kritor-plugin-` 开头的文件夹 - ### 温馨提示 + - 只有附带 `index.js` 文件在插件包根目录,才会被视为插件包 - 如不存在 `apps` 目录,则只会加载 `index.js` 文件 - 如存在 `apps` 目录,则会加载 `apps` 目录下所有的 `js` 文件、根目录的`index.js`。 ## 插件包目录参考结构 -``` +```md kritor-plugin-hello-world ├── apps │ ├── app1.js @@ -44,17 +45,21 @@ kritor-plugin-hello-world └── package.json ``` + ## #karin 在模板仓库下,有这么一段代码 + ```js import { plugin, segment } from '#Karin' ``` `#Karin` 是一个别名,指向 `./lib/index.js` 文件。 此文件为入口文件,开发者无需像以下这样引入模块: + ```js import segment from './lib/bot/segment.js' import plugin from './lib/plugins/plugin.js' ``` -详情请查看 [开发工具](./karin.md) 文档 \ No newline at end of file + +详情请查看 [开发工具](../utils/index.md) 文档 diff --git a/docs/develop/karin.md b/docs/develop/karin.md deleted file mode 100644 index 45c0c4e..0000000 --- a/docs/develop/karin.md +++ /dev/null @@ -1,160 +0,0 @@ -## 概述 -`#Karin`是`./lib/index.js`文件的别名,这是一个集中导出多个模块的入口文件。 -通过使用别名,开发者可以更简洁地引入所需的模块,无需指定完整的路径。 - -```js -import segment from './lib/bot/segment.js' -import plugin from './lib/plugins/plugin.js' - -// 以上的导入麻烦且冗长,在使用别名后可以简化为 -import { segment, plugin } from '#Karin' -``` - -## 使用 - -::: tip -可能会更新不及时,有一定阅读能力的可以查看 [lib/index.js](https://github.com/KarinJS/Karin/blob/main/lib/index.js) -::: - -- ## `segment` - 请点击 [elements](./elements.md) 查看详情 - -- ## `YamlEditor` - 请点击 [YamlEditor](./YamlEditor.md) 查看详情 - -- ## `kritor` - 内部方法,若无特殊需求,不建议使用 - -- ## `APP` - ```js - import { App } from '#Karin' - // ... - ``` -- ## `Bot` - ```js - import { Bot } from '#Karin' - // ... - ``` -- ## `Cfg` - ```js - import { Cfg } from '#Karin' - // ... - ``` -- ## `common` - ```js - import { common } from '#Karin' - - /** 休眠函数 延迟5秒 */ - await common.sleep(5 * 1000) - - /** 下载文件 参数1为下载地址,参数2为保存到本地的路径 */ - await common.downFile('https://example.com/1.jpg', './temp/test/1.jpg') - - /** 递归创建文件夹 */ - common.mkdir('./temp/test') - - /** 快速构建淡紫色的bot前缀日志 */ - common.logger('qq', '这是一条来自QQ的消息') - // 输出:[Bot:qq] 这是一条来自QQ的消息 - - /** 获取绝对路径,支持file://前缀 */ - common.absPath('file://./temp/test') - // 输出:/home/karin/temp/test - - /** 将文件转换为不带前缀的base64字符串 */ - await common.base64('./temp/test/1.jpg') - // 输出:'/9j/4AAQSkZJRgABAQEAYABgAADg...' - - /** 将数据流对象转换为Buffer对象 */ - const Buffer = await common.stream(fs.createReadStream('./temp/test/1.jpg')) - // 输出:Buffer - - /** 将文件转换为Buffer对象 支持file:// base64:// 可读流等... */ - const buffer = await common.buffer(buffer) - // 输出 buffer - - ``` -- ## `logger` - ```js - import { logger } from '#Karin' - - /** 打印trace日志 */ - logger.trace('这是一条trace日志') - /** 打印debug日志 */ - logger.debug('这是一条debug日志') - /** 打印info日志 */ - logger.info('这是一条info日志') - /** 打印warn日志 */ - logger.warn('这是一条warn日志') - /** 打印mark日志 */ - logger.mark('这是一条mark日志') - /** 打印error日志 */ - logger.error('这是一条error日志') - /** 打印fatal日志 */ - logger.fatal('这是一条fatal日志') - - // 其中 logger还提供了打印不同颜色日志的方法 - - /** 打印红色日志 */ - logger.info(logger.red('这是一条红色的info日志')) - /** 打印绿色日志 */ - logger.info(logger.green('这是一条绿色的info日志')) - /** 打印黄色日志 */ - logger.info(logger.yellow('这是一条黄色的info日志')) - /** 打印蓝色日志 */ - logger.info(logger.blue('这是一条蓝色的info日志')) - /** 打印品红色日志 */ - logger.info(logger.magenta('这是一条品红色的info日志')) - /** 打印青色日志 */ - logger.info(logger.cyan('这是一条青色的info日志')) - /** 打印白色日志 */ - logger.info(logger.white('这是一条白色的info日志')) - /** 打印灰色日志 */ - logger.info(logger.chalk.gray('这是一条灰色的info日志')) - /** 打印淡紫色日志 */ - logger.info(logger.violet('这是一条淡紫色的info日志')) - - // 当以上方法无法满足你的需求时,你可以使用 chalk 库来自定义颜色 - logger.info(logger.chalk.hex('#FF0000')('这是一条自定义颜色的info日志')) - - ``` -- ## `plugin` - ```js - import { plugin } from '#Karin' - // ... - ``` -- ## `redis` - ```js - import { redis } from '#Karin' - - /** 存储一个键值对 */ - await redis.set('key', 'value') - - /** 存储一个键值对 60秒后过期 */ - await redis.set('key', 'value', { EX: 60 }) - - /** 获取指定键的值 */ - const value = await redis.get('key') - console.log(value) - - /** 删除指定键 */ - await redis.del('key') - - /** 获取所有键 慎用... 返回数组 */ - const all = await redis.keys('*') - console.log(all) - - /** 模糊获取以k开头的所有键列表 返回数组 */ - const keys = await redis.keys('k*') - /** 打印所有键的值 */ - for (const key of keys) { - const value = await redis.get(key) - console.log(value) - } - ``` - -- ## `Renderer` - ```js - import { Renderer } from '#Karin' - // ... - ``` diff --git a/docs/develop/plugins.md b/docs/develop/plugins.md index 918cb1c..c26c731 100644 --- a/docs/develop/plugins.md +++ b/docs/develop/plugins.md @@ -5,15 +5,17 @@ 打开[模板仓库](https://github.com/KarinJS/karin-plugin-template) ## 克隆模板仓库 + 点击`Use this template`或`使用此模板`按钮,创建自己的仓库。 -![](https://cdn.jsdelivr.net/gh/Zyy955/imgs/img/202404121412587.png) +![202404121412587](https://cdn.jsdelivr.net/gh/Zyy955/imgs/img/202404121412587.png) 填写仓库名称,描述,选择是否公开。 -![](https://cdn.jsdelivr.net/gh/Zyy955/imgs/img/202404121414580.png) +![202404121414580](https://cdn.jsdelivr.net/gh/Zyy955/imgs/img/202404121414580.png) ## 克隆仓库到本地 以下命令,在karin根目录执行 + ```bash git clone https://github.com/karinjs/karin-plugin-template.git ./plugins/karin-plugin-template. ``` @@ -29,4 +31,3 @@ pnpm install --filter=karin-plugin-template ```bash node . --dev ``` - diff --git a/docs/develop/standard.md b/docs/develop/standard.md new file mode 100644 index 0000000..7c4558b --- /dev/null +++ b/docs/develop/standard.md @@ -0,0 +1,116 @@ +# 插件开发规范 + +[[toc]] + +## 命名规范 + +### karin-plugin-example + +> `karin-plugin-example`为存放非插件包的目录,即单个js文件插件的存放目录。 + +- 使用英文进行命名,无固定前缀要求 +- 名称尽量简短,避免过长 +- 名称避免使用特殊符号,使用`-`连接单词 + +例如:`hello-world.js`、`my-plugin.js`、`my-awesome-plugin.js` + +### 插件包 + +- 插件包名称必须以`karin-plugin-`开头,后面跟插件名称 +- 必须使用英文命名,尽量简短,避免使用特殊符号 +- 统一为小写,使用`-`连接单词 + +例如:`kritor-plugin-hello`、`karin-plugin-my-plugin`、`karin-plugin-my-awesome-plugin` + +## 结构规范 + +> 插件包的目录结构,请参照以下规范进行组织,如果特殊需求,可由开发者自行在基础结构上进行调整 + +### 文件结构 + +:::tip +以下是一个基础的结构规范,具体项目可根据实际情况进行调整 +::: + +```md +kritor-plugin-hello +├── apps +│ ├── app1.js +│ └── app2.js +├── config +│ ├── config +│ │ ├── config.yaml +│ │ └── user.yaml +│ └── defSet +│ ├── config.yaml +│ └── user.yaml +├── resources +│ ├── template +│ ├── font +│ ├── icon +│ ├── image +│ └── css +├── lib +├── model +├── index.js +├── .gitignore +├── README.md +├── CHANGELOG.md +├── LICENSE +└──package.json +``` + +### 数据文件 + +- 对于`数据文件`,karin要求开发者将数据文件`统一`存放到`karin/data/`下 +- 请每个插件在`karin/data/`下创建以插件包名命名的文件夹,并将数据文件存放在该文件夹下 +- 如无特殊需求,请不要在`data`文件夹下创建其他文件夹 + +### 配置文件 + +- karin要求插件包的配置文件均存在热更新机制 +- 统一使用`yaml`、`json`等格式,并将`用户可编辑的配置`文件存放在`karin/config/`下 +- 对于默认配置文件,统一存放在`config/defSet/`下,由开发者进行维护修改,此处禁止用户编辑修改 +- 如无特殊需求,请不要在`config`文件夹下创建其他文件夹 +- 如对此处有疑问,请查看[插件包模板仓库](https://github.com/KarinJS/karin-plugin-template)进行参考 + +### resources + +:::tip +任选其一即可,以下是两种常见的规范 +::: + +规范1: + +- 插件包的资源文件 +- 字体文件存放在`resources/font/`下 +- 图片文件存放在`resources/image/`下 +- 图标文件存放在`resources/icon/`下 +- 通用样式文件存放在`resources/css/`下 +- 渲染模板存放在`resources/template/`下,每一种模板新建一个文件夹 + +规范2: + +- 每一种渲染模板都在`resources`下新建一个文件夹,文件夹名称为模板名称,将模板的资源文件存放在该文件夹下 + +### 临时文件 + +- karin会在启动的时候,在`karin/temp`下为每一个插件包创建对应名称的文件夹 +- 开发者可在该文件夹下存放临时文件,如缓存文件、日志文件等 +- 请勿对他人的文件夹进行删除、修改 +- 如无特殊需求,请不要在该文件夹下创建其他文件夹。 + +## 仓库规范 + +- 要求插件仓库名称必须以`karin-plugin-`开头,必须与插件包名称一致 +- 插件仓库必须提供开源协议 +- 在仓库标签页,添加`karin`、`karin-plugin` +- 对于未开源的插件仓库,请遵守[插件收录规范][插件收录] +- 对于商业性质的插件仓库,也请遵守[插件收录规范][插件收录] +- 对于二改的`karin`仓库,必须进行开源,并使用`GPLv3+`协议,并使用`karin`标签进行标记 + +## 插件收录 + +请查看[插件收录规范][插件收录] + +[插件收录]: ../plugins/index.md#🎉插件收录规范 diff --git a/docs/event/index.md b/docs/event/index.md index a9e3c1e..a4ea152 100644 --- a/docs/event/index.md +++ b/docs/event/index.md @@ -2,4 +2,21 @@ --- -[消息事件](./message.md) \ No newline at end of file +## 事件概述 + +> 事件是一段上报,上报也可以由插件主动触发 +> 例如插件向适配器发送请求,适配器返回结果时触发上报 +> 在大多数协议端中,事件上报基本上是通过 `HTTP`、`WebSocket`通信实现的 +> 而在karin,使用了`kritor`标准,新增了一种`gRPC`协议进行通信 + +## 消息事件 + +- [消息事件](./message.md) + +## 通知事件 + +- [通知事件](./notice.md) + +## 请求事件 + +- [请求事件](./request.md) diff --git a/docs/event/message.md b/docs/event/message.md index 307c6e5..9f14096 100644 --- a/docs/event/message.md +++ b/docs/event/message.md @@ -8,16 +8,20 @@ 开发者只需要关注karin本身的标准即可。 ::: -### 标准属性对象 +[[toc]] + +## 标准属性对象 + +> 以下,是一个标准的适配器应该遵循的属性对象 ```js -const message = { +const e = { self_id: 'string', // 机器人的ID,默认为uin user_id: 'string', // 用户ID,默认为uin group_id: 'string', // 群组ID,仅在群聊中有效,默认为uin time: 0, // 消息时间戳 message_id: 'string', // 消息ID - message_seq: 'string', // 消息序列号 + message_seq: 'string', // 消息序列号 推荐使用message_id,某些场景可能无法提供 raw_message: 'string', // 原始消息文本 // 从什么地方收到的信息 contact: { @@ -32,60 +36,109 @@ const message = { sender: { uid: 'string', // 用户uin,由于为新属性,可能不存在 uin: 'string', // 用户uin,建议目前使用uin作为唯一标识 - nick: 'string' // 用户昵称,可能不存在 + nick: 'string', // 用户昵称,可能不存在 + role: 'string', // 用户角色,可能不存在 目前暂未实现 }, - elements: [], // 消息元素数组,详情见下方 - msg: 'string', // 框架属性,由karin处理后的消息纯文本 - game: 'string', // 框架属性,通过前缀判断是否为游戏指令 - image: [], // 框架属性,图片数组 - at: [], // 框架属性,存放被@的用户uin、uid,如uid不存在则会键入uin - atBot: false | true, // 框架属性,是否@机器人 - atAll: false | true, // 框架属性,是否@全体成员 - file: {}, // 框架属性,文件对象 - reply_id: 'string' // 框架属性,引用回复消息ID + elements: [], // 消息元素数组 见#elements + replyCallback(elements, retry_count) // 回复函数,这个方法不应该由开发者调用 } ``` -### elements +## karin拓展字段 -> 对于媒体消息,karin标准为统一使用file属性,不再使用url +karin在标准字段之外,会对消息事件进行拓展,以便开发者更方便的使用。 ```js -const elements = [ - { type: 'text', text: 'Hello' }, // 文本 - { type: 'face', id: 1 }, // 表情 - { type: 'at', uid: '1234567890', uin: '1234567890' }, // @某人 开发者通常只需要关注uid即可 - { type: 'reply', message_id: 'abc1234567890' }, // 引用回复 - { type: 'image', file: 'https://example.com/image.png' }, // 图片 - { type: 'video', file: 'https://example.com/video.mp4' }, // 视频 - { type: 'record', file: 'https://example.com/record.mp3' }, // 语音 - - // ...其他类型消息 -] +const e = { +// ... + bot(), // 适配器对象 + msg: 'string', // 由karin处理后的消息纯文本 + game: 'string', // 通过前缀判断是否为游戏指令 + image: [], // 图片数组 + at: [], // 存放被@的用户uin、uid,如uid不存在则会键入uin + atBot: false | true, // 是否@机器人 + atAll: false | true, // 是否@全体成员 + file: {}, // 文件对象 + reply_id: 'string', // 引用回复消息ID + isAdmin: false | true, // 是否为机器人管理员 + isMaster : false | true, // 是否为机器人主人 + isPrivate: false | true, // 是否为私聊消息 + isGroup: false | true, // 是否为群聊消息 + logText: 'string', // 日志用户字符串 + logFnc: 'string', // 日志函数字符串 + store: new Map(), // 开发者可以存放自定义数据 + reply(elements, options) // 快速回复接口 +} +``` + +## elements + +见 [element](../utils/segment.md) + +## replyCallback + +> 此方法需要由适配器实现,开发者不应该调用此方法。 + +```js +/** + * @callback replyCallback + * @param {Array} elements - 发送的消息元素 只能是数组 + * @param {number} retry_count - 重试次数 + * @returns {{ message_id?: string }} + */ +e.replyCallback = (elements, retry_count) => { + // 适配器实现 +} ``` -### 快速回复 +## 快速回复 > 此外,每个消息事件,karin都会提供一个快速回复接口,开发者可以直接调用接口快速回复消息。 ```js -e.reply('Hello') // 回复消息内容 -e.reply('Hello', { at: true }) // @消息发送者 -e.reply('Hello', { reply: true }) // 引用回复消息本身 -e.reply('Hello', { recallMsg: 10 }) // 发送成功后,撤回消息时间,单位秒 -e.reply('Hello', { button: false }) // 暂未实现 -e.reply('Hello', { retry_count: 1 }) // 重试次数 -e.reply('Hello', { at: true, reply: true, recallMsg: 10, button: false, retry_count: 1 }) +/** + * @callback quickReplyCallback + * @param {string|KarinElement|Array} elements - 发送的消息 + * @param {object} [options] - 回复数据 + * @param {boolean} [options.at] - 是否at用户 + * @param {boolean} [options.reply] - 是否引用回复 + * @param {number} [options.recallMsg] - 群聊是否撤回消息,0-120秒,0不撤回 + * @param {boolean} [options.button] - 是否使用按钮 + * @param {number} [options.retry_count] - 重试次数 + * @returns {{ message_id?: string }} + */ +e.reply = (elements, options) => { + // 这部分由karin实现,开发者只需要调用即可 +} + ``` | 参数 | 类型 | 说明 | | ------------------- | ------- | -------------------------------- | -| message | string | 回复消息内容 | +| elements | string | 回复消息内容 | | options | object | 回复选项,以下均为可选参数 | | options.at | boolean | 是否@消息发送者 | | options.reply | boolean | 是否引用回复消息本身 | | options.recallMsg | number | 发送成功后,撤回消息时间,单位秒 | | options.button | boolean | 暂未实现 | | options.retry_count | number | 发送失败后,重试次数 | + +## bot + +> `e.bot`为上报事件bot的的适配器对象,开发者可以通过此对象调用Api接口 + +```js +// 获取头像 +const avatar = await e.bot.getAvatarUrl('uid', 100) +console.log(avatar) // https://q1.qlogo.cn/g?b=qq&s=100&nk=uid +``` + +更多api接口请查看 [Api](../api/index.md) + +## 流程 + +> 大概流程,待补充更详细的... + +![流程](./message.svg) diff --git a/docs/event/message.svg b/docs/event/message.svg new file mode 100644 index 0000000..5ae6b26 --- /dev/null +++ b/docs/event/message.svg @@ -0,0 +1 @@ +
协议端上报消息
适配器转换消息 通过`KarinMessage(lib/bot/KarinMessage.js)`转换
适配器实现`replyCallback`方法
适配器通过`Bot.emit('message', e)`进行上报
`karin`在`lib/event/message.js`实现`reply`、`bot`方法,加入标准字段
插件触发 开始处理事件
\ No newline at end of file diff --git a/docs/event/notice.md b/docs/event/notice.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/event/request.md b/docs/event/request.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md index 142f6fd..f51e4e4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ hero: link: https://docs.onebots.org/ - theme: alt text: 快速上手 - link: /start + link: /start/start - theme: brand text: 插件索引 link: /plugins/index diff --git a/docs/start/adapter.md b/docs/start/adapter.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/start/index.md b/docs/start/index.md new file mode 100644 index 0000000..2ea281a --- /dev/null +++ b/docs/start/index.md @@ -0,0 +1,23 @@ +# 快速开始目录 + +## 安装karin环境、配置、启动 + +- [安装karin](./start.md) 环境、配置、启动 + +## 安装适配器 + +- [安装适配器](./adapter.md) 适配器是karin的大脑,它负责实现与用户的通信 + +## 安装渲染器 + +- [安装渲染器](../Renderer/Renderer.md) 推荐安装,大部分插件均在使用 + +## 安装插件 + +- [安装插件](../plugins/index.md) 插件是让karin变得更加强大的重要途径,可以实现各种功能 + +## 完善此文档 + +欢迎大家贡献自己的力量,完善此文档,让更多人能够快速上手karin + +[点击此处跳转到文档贡献页面](https://github.com/KarinJS/Karin/tree/docs) diff --git a/docs/start.md b/docs/start/start.md similarity index 69% rename from docs/start.md rename to docs/start/start.md index 0c0e871..8c41a1e 100644 --- a/docs/start.md +++ b/docs/start/start.md @@ -5,13 +5,14 @@ ## 环境 > 支持 Windows、Linux、MacOS、Docker 等环境 -> 推荐安装的没有强制性需求,可根据个人需求进行安装 +> 推荐安装的没有强制性需求,可根据个人需求进行安装 +> karin开发的场景,默认您拥有以下全部环境,若有特殊需求,请自行安装 | - | 安装 | 说明 | | ---------------- | -------- | ------------------------------------------------------------------------------ | -| [NodeJs][NodeJs] | √ | 推荐版本18以上 | +| [NodeJs][NodeJs] | √ | 推荐版本18+ | | [git][git] | 推荐安装 | 分布式版本控制软件,国内用户推荐使用 [腾讯软件管家][腾讯软件管家] 进行加速下载 | -| [redis][redis] | 推荐安装 | 用于存储数据,大多数插件都用到,推荐安装 | +| [redis][redis] | 推荐安装 | 一个高性能的内存数据库,windows用户推荐使用[redis-windows][redis-windows] | ## 安装 @@ -99,19 +100,22 @@ node . --dev ::: -## 渲染器 +## 安装适配器 -::: tip -`Karin`开放了`Renderer`接口,开发者可自行注册渲染器,实现自定义渲染器 -::: +> 适配器的作用就是在不同的聊天平台之间建立桥梁,使karin可以与不同平台的用户进行交互 + +- [安装适配器](./adapter.md) + +## 安装渲染器 -如果你不需要进行渲染`html`页面等操作,可跳过此步骤。 +> 渲染器在karin的定义可能它更是一个单纯的截图工具 +> 默认提供了`puppeteer`,`puppeteer`打开html -> 渲染 -> 截图 -> 返回图片base64编码 +> 当然,你也可以自行注册渲染器,实现自定义截图逻辑 -默认提供[karin-puppeteer][karin-puppeteer]作为渲染器,可根据需求自行安装。 -通过`WebSocketServer`进行通信,详情请查看[karin-puppeteer][karin-puppeteer] +- [安装渲染器](../Renderer/Renderer.md) -[karin-puppeteer]: https://github.com/KarinJS/karin-puppeteer [NodeJs]: https://nodejs.org/en [git]: https://git-scm.com/ [腾讯软件管家]: https://sw.pcmgr.qq.com/1e05804bd17b358a8c88284df8331fcd/65fcde89/spcmgr/download/Git-2.44.0-64-bit.exe [redis]: https://github.com/redis-windows/redis-windows/releases +[redis-windows]: https://github.com/redis-windows/redis-windows \ No newline at end of file diff --git a/docs/utils/Renderer.md b/docs/utils/Renderer.md new file mode 100644 index 0000000..b73cc2d --- /dev/null +++ b/docs/utils/Renderer.md @@ -0,0 +1,6 @@ +# Renderer + + ```js + import { Renderer } from '#Karin' + // ... + ``` diff --git a/docs/develop/YamlEditor.md b/docs/utils/YamlEditor.md similarity index 84% rename from docs/develop/YamlEditor.md rename to docs/utils/YamlEditor.md index 4ee3ec4..cda9437 100644 --- a/docs/develop/YamlEditor.md +++ b/docs/utils/YamlEditor.md @@ -1,32 +1,19 @@ # YamlEditor 使用说明 ## 概述 + `YamlEditor` 是一个用于编辑 YAML 文件的类。它提供了读取、修改、添加、删除和保存 YAML 文件的功能。这个类在应用中适用于对 YAML 配置文件进行操作的场景。 ::: tip 最最最重要的是,可以保留注释信息,并且不会影响 YAML 文件的结构。 ::: -- [YamlEditor 使用说明](#yamleditor-使用说明) - - [概述](#概述) - - [使用](#使用) - - [导入和实例化](#导入和实例化) - - [加载文件](#加载文件) - - [获取 YAML 中的值](#获取-yaml-中的值) - - [设置 YAML 中的值](#设置-yaml-中的值) - - [向 YAML 中添加新值](#向-yaml-中添加新值) - - [删除 YAML 中的值](#删除-yaml-中的值) - - [向 YAML 中的数组添加新元素](#向-yaml-中的数组添加新元素) - - [检查指定路径的键是否存在](#检查指定路径的键是否存在) - - [查询指定路径中是否包含指定的值](#查询指定路径中是否包含指定的值) - - [保存文件](#保存文件) - - [注意事项](#注意事项) - - [示例](#示例) - +[[toc]] ## 使用 ### 导入和实例化 + ```js import { YamlEditor } from '#Karin' @@ -34,12 +21,12 @@ import { YamlEditor } from '#Karin' const yamlEditor = new YamlEditor('./path/to/your/file.yaml') ``` - ### 加载文件 -创建实例时,`YamlEditor` 会自动加载指定路径的 YAML 文件。如果文件不存在或读取出错,将会记录错误。 +创建实例时,`YamlEditor` 会自动加载指定路径的 YAML 文件。如果文件不存在或读取出错,将会记录错误。 ### 获取 YAML 中的值 + ```js // 获取指定路径的值,路径用点号分隔 const value = yamlEditor.get('root.child.key') @@ -50,26 +37,29 @@ if (value === false) { console.log('获取的值:', value) } ``` -通过 `get(path)` 方法获取 YAML 中指定路径的值。如果路径不存在,将返回 `false`。 +通过 `get(path)` 方法获取 YAML 中指定路径的值。如果路径不存在,将返回 `false`。 ### 设置 YAML 中的值 + ```js // 设置指定路径的值 yamlEditor.set('root.child.key', 'newValue') ``` -通过 `set(path, value)` 方法设置 YAML 中指定路径的值。如果路径不存在,将会创建相应的结构。 +通过 `set(path, value)` 方法设置 YAML 中指定路径的值。如果路径不存在,将会创建相应的结构。 ### 向 YAML 中添加新值 + ```js // 向指定路径添加新值 yamlEditor.add('root.newPath', 'newValue') ``` -使用 `add(path, value)` 方法,可以在 YAML 中的指定路径添加新值。如果路径不存在,将会创建相应的结构。 +使用 `add(path, value)` 方法,可以在 YAML 中的指定路径添加新值。如果路径不存在,将会创建相应的结构。 ### 删除 YAML 中的值 + ```js // 删除指定路径的值 const success = yamlEditor.del('root.child.key') @@ -80,53 +70,58 @@ if (success) { console.log('删除失败') } ``` -`del(path)` 方法用于删除 YAML 中指定路径的值。如果成功删除,将返回 `true`;否则返回 `false`。 +`del(path)` 方法用于删除 YAML 中指定路径的值。如果成功删除,将返回 `true`;否则返回 `false`。 ### 向 YAML 中的数组添加新元素 + ```js // 向指定路径的数组添加新元素 yamlEditor.append('root.array', 'newElement', true) // 在数组开头添加 yamlEditor.append('root.array', 'newElement') // 在数组末尾添加 ``` -使用 `append(path, value, prepend)` 方法,可以向 YAML 中指定路径的数组添加新元素。`prepend` 参数决定是否在数组的开头添加元素,默认是在末尾添加。 +使用 `append(path, value, prepend)` 方法,可以向 YAML 中指定路径的数组添加新元素。`prepend` 参数决定是否在数组的开头添加元素,默认是在末尾添加。 ### 检查指定路径的键是否存在 + ```js // 向指定路径的数组添加新元素 yamlEditor.has('a.b.c') // true yamlEditor.has('x.y.z') // false ``` -使用 `has(path)` 方法,可以检查 YAML 中指定路径的键是否存在。如果存在,返回 `true`;否则返回 `false`。 +使用 `has(path)` 方法,可以检查 YAML 中指定路径的键是否存在。如果存在,返回 `true`;否则返回 `false`。 ### 查询指定路径中是否包含指定的值 + ```js // 查询指定路径中是否包含指定的值 yamlEditor.hasVal('a.b.c', 'val') // true yamlEditor.hasVal('x.y.z', 'val') // false ``` -使用 `hasVal(path, value)` 方法,可以查询 YAML 中指定路径的值是否包含指定的值。如果包含,返回 `true`;否则返回 `false`。 +使用 `hasVal(path, value)` 方法,可以查询 YAML 中指定路径的值是否包含指定的值。如果包含,返回 `true`;否则返回 `false`。 ### 保存文件 + ```js // 保存修改后的 YAML 文件 yamlEditor.save() ``` -通过 `save()` 方法保存 YAML 文件。这个方法将会覆盖原文件,确保之前的修改被保存。如果保存过程中出错,将记录错误。 +通过 `save()` 方法保存 YAML 文件。这个方法将会覆盖原文件,确保之前的修改被保存。如果保存过程中出错,将记录错误。 ## 注意事项 + - **日志记录**:`YamlEditor` 使用了日志记录功能,确保在操作过程中能够及时发现问题。 - **错误处理**:所有方法都进行了错误处理,当发生异常时将记录错误。 - **路径格式**:指定路径时使用点号分隔,例如 `'root.child.key'`。 - **保存文件**:使用 `save()` 方法确保所做的修改被写入文件。 - ## 示例 + ```js // 创建 YamlEditor 实例 const yamlEditor = new YamlEditor('./example.yaml') @@ -157,4 +152,5 @@ yamlEditor.hasVal('x.y.z', 'val') // false // 保存更改 yamlEditor.save() ``` -通过这些操作,您可以方便地读取和修改 YAML 文件。 \ No newline at end of file + +通过这些操作,您可以方便地读取和修改 YAML 文件。 diff --git a/docs/utils/common.md b/docs/utils/common.md new file mode 100644 index 0000000..8880806 --- /dev/null +++ b/docs/utils/common.md @@ -0,0 +1,35 @@ +# common + +```js +import { common } from '#Karin' + +/** 休眠函数 延迟5秒 */ +await common.sleep(5 * 1000) + +/** 下载文件 参数1为下载地址,参数2为保存到本地的路径 */ +await common.downFile('https://example.com/1.jpg', './temp/test/1.jpg') + +/** 递归创建文件夹 */ +common.mkdir('./temp/test') + +/** 快速构建淡紫色的bot前缀日志 */ +common.logger('qq', '这是一条来自QQ的消息') +// 输出:[Bot:qq] 这是一条来自QQ的消息 + +/** 获取绝对路径,支持file://前缀 */ +common.absPath('file://./temp/test') +// 输出:/home/karin/temp/test + +/** 将文件转换为不带前缀的base64字符串 */ +await common.base64('./temp/test/1.jpg') +// 输出:'/9j/4AAQSkZJRgABAQEAYABgAADg...' + +/** 将数据流对象转换为Buffer对象 */ +const Buffer = await common.stream(fs.createReadStream('./temp/test/1.jpg')) +// 输出:Buffer + +/** 将文件转换为Buffer对象 支持file:// base64:// 可读流等... */ +const buffer = await common.buffer(buffer) +// 输出 buffer + +``` diff --git a/docs/utils/index.md b/docs/utils/index.md new file mode 100644 index 0000000..84a3afc --- /dev/null +++ b/docs/utils/index.md @@ -0,0 +1,41 @@ +# 开发工具 + +## karin + +> 这里正确的名称是`#karin`,但是为了方便搜索,我们使用`karin`来代替 +`#karin`是整个框架的核心入口,所有的开发工具都是基于`#karin`进行使用 + +详情查看[karin](./karin.md) + +## logger + +`logger`是一个日志工具,用于打印不同级别的日志 + +## common + +`common`是一个工具集合,包含了一些常用的工具函数,例如`sleep`、`downFile`等 + +## redis + +`redis`是一个开源的高性能键值对数据库,常用于缓存、消息队列等场景 +详情查看[redis](./redis.md) + +## segment + +`segment`是一个用于构造消`element`的工具 +详情查看[segment](./segment.md) + +## Renderer + +`Renderer`是一个渲染器入口,用于存储开发者的渲染器实例 +详情查看[Renderer](./Renderer.md) + +## YamlEditor + +`YamlEditor`是一个用于编辑`yaml`文件的工具 +详情查看[YamlEditor](./YamlEditor.md) + +## update + +`update`是一个用于更新插件工具,还可获取插件更新日志 +详情查看[update](./update.md) diff --git a/docs/utils/karin.md b/docs/utils/karin.md new file mode 100644 index 0000000..4b2241b --- /dev/null +++ b/docs/utils/karin.md @@ -0,0 +1,50 @@ +# 概述 + +`#Karin`是`./lib/index.js`文件的别名,这是一个集中导出多个模块的入口文件。 +通过使用别名,开发者可以更简洁地引入所需的模块,无需指定完整的路径。 + +```js +import segment from './lib/bot/segment.js' +import plugin from './lib/plugins/plugin.js' + +// 以上的导入麻烦且冗长,在使用别名后可以简化为 +import { segment, plugin } from '#Karin' +``` + +## 使用 + +::: tip +可能会更新不及时,有一定阅读能力的可以查看 [lib/index.js](https://github.com/KarinJS/Karin/blob/main/lib/index.js) +::: + +- ## `kritor` + + 内部方法,若无特殊需求,不建议使用 + +- ## `APP` + + ```js + import { App } from '#Karin' + // ... + ``` + +- ## `Bot` + + ```js + import { Bot } from '#Karin' + // ... + ``` + +- ## `Cfg` + + ```js + import { Cfg } from '#Karin' + // ... + ``` + +- ## `plugin` + + ```js + import { plugin } from '#Karin' + // ... + ``` diff --git a/docs/utils/logger.md b/docs/utils/logger.md new file mode 100644 index 0000000..f748483 --- /dev/null +++ b/docs/utils/logger.md @@ -0,0 +1,45 @@ +# logger + +```js +import { logger } from '#Karin' + +/** 打印trace日志 */ +logger.trace('这是一条trace日志') +/** 打印debug日志 */ +logger.debug('这是一条debug日志') +/** 打印info日志 */ +logger.info('这是一条info日志') +/** 打印warn日志 */ +logger.warn('这是一条warn日志') +/** 打印mark日志 */ +logger.mark('这是一条mark日志') +/** 打印error日志 */ +logger.error('这是一条error日志') +/** 打印fatal日志 */ +logger.fatal('这是一条fatal日志') + +// 其中 logger还提供了打印不同颜色日志的方法 + +/** 打印红色日志 */ +logger.info(logger.red('这是一条红色的info日志')) +/** 打印绿色日志 */ +logger.info(logger.green('这是一条绿色的info日志')) +/** 打印黄色日志 */ +logger.info(logger.yellow('这是一条黄色的info日志')) +/** 打印蓝色日志 */ +logger.info(logger.blue('这是一条蓝色的info日志')) +/** 打印品红色日志 */ +logger.info(logger.magenta('这是一条品红色的info日志')) +/** 打印青色日志 */ +logger.info(logger.cyan('这是一条青色的info日志')) +/** 打印白色日志 */ +logger.info(logger.white('这是一条白色的info日志')) +/** 打印灰色日志 */ +logger.info(logger.chalk.gray('这是一条灰色的info日志')) +/** 打印淡紫色日志 */ +logger.info(logger.violet('这是一条淡紫色的info日志')) + +// 当以上方法无法满足你的需求时,你可以使用 chalk 库来自定义颜色 +logger.info(logger.chalk.hex('#FF0000')('这是一条自定义颜色的info日志')) + +``` diff --git a/docs/utils/redis.md b/docs/utils/redis.md new file mode 100644 index 0000000..a5fde1c --- /dev/null +++ b/docs/utils/redis.md @@ -0,0 +1,30 @@ +# redis + +```js +import { redis } from '#Karin' + +/** 存储一个键值对 */ +await redis.set('key', 'value') + +/** 存储一个键值对 60秒后过期 */ +await redis.set('key', 'value', { EX: 60 }) + +/** 获取指定键的值 */ +const value = await redis.get('key') +console.log(value) + +/** 删除指定键 */ +await redis.del('key') + +/** 获取所有键 慎用... 返回数组 */ +const all = await redis.keys('*') +console.log(all) + +/** 模糊获取以k开头的所有键列表 返回数组 */ +const keys = await redis.keys('k*') +/** 打印所有键的值 */ +for (const key of keys) { + const value = await redis.get(key) + console.log(value) +} +``` diff --git a/docs/utils/segment.md b/docs/utils/segment.md new file mode 100644 index 0000000..4445ffa --- /dev/null +++ b/docs/utils/segment.md @@ -0,0 +1,626 @@ +# elements + +本文档介绍了 Krita 的消息元素结构和 `segment` 模块的使用方法。 + +::: tip tips +目前尚在开发阶段,可能有部分内容未完善或错误,敬请谅解。 +::: + +## 导入 + +::: tip 温馨提示 +以下所有的示例都假设你已经导入了 `segment` 模块。 +::: + +```js +import { segment } from '#karin' +``` + +## 多媒体资源标准 + +karin对于多媒体资源的标准化处理,遵循以下规则: + +- 对于网络资源,要求传入的url必须为 `https://` 或 `http://` 开头 +- 对于base64格式,传入必须是 `base64://` 格式开头的字符串 +- 对于`file://`格式,传入的字符串必须是`绝对路径`,且资源必须存在 +- 对于未知字段,请确认适配器可以正确处理 + +::: tip 注意 +对于`file://`格式,请开发者注意以下几点: + +- 请确保用户的协议端和karin运行环境一致,否则可能导致文件读取失败 +- 对于Linux系统,由于绝对路径前方有`/`,格式为`file:///root/...`,请注意区分`///`和`//` +::: + +## 文本 text + +```js +const text = segment.text('Hello, world!') +console.log(text) +``` + +输出: + +```js +{ + type: 'text', + text: 'Hello, world!' +} +``` + +## 表情 face + +::: tip 温馨提示 +键入的ID必须为数字 +::: + +```js +const face = segment.face(1) +console.log(face) +``` + +输出: + +```js +{ + type: 'face', + id: 1 +} +``` + +## 图片 image + +::: tip 温馨提示 +遵循 [多媒体资源标准](#多媒体资源标准) +::: + +```js +const image = segment.image('https://example.com/image.png') // 网络图片 +const image = segment.image('base64://iVBORw0KGgoAAAANSUhEUgA...') // base64格式 +const image = segment.image('file://C:/Users/admin/Pictures/image.png') // Windows绝对路径 +const image = segment.image('file:///root/karin/image.png') // Linux绝对路径 +console.log(image) +``` + +输出: + +```js +{ // 对于网络图片,要求传入的url必须为https://或http://开头 + type: 'image', + file: 'https://example.com/image.png' +} +{ // 对于base64格式,传入的字符串必须是base64格式的图片 + type: 'image', + file: 'base64://iVBORw0KGgoAAAANSUhEUgA...' +} +{ // file://格式,传入的字符串必须是绝对路径,且图片必须存在 + type: 'image', + file: 'file://C:/Users/admin/Pictures/image.png' +} +{ // file:///格式,传入的字符串必须是绝对路径,且图片必须存在 + type: 'image', + file: 'file:///root/karin/image.png' +} +``` + +## 语音 record + +::: tip 温馨提示 +遵循 [多媒体资源标准](#多媒体资源标准) +::: + +```js +const record = segment.record('https://example.com/record.mp3') +console.log(record) +``` + +输出: + +```js +{ + type:'record', + file: 'https://example.com/record.mp3' +} +``` + +## 视频 video + +::: tip 温馨提示 +遵循 [多媒体资源标准](#多媒体资源标准) +::: + +```js +const video = segment.video('https://example.com/video.mp4') +console.log(video) +``` + +输出: + +```js +{ + type: 'video', + file: 'https://example.com/video.mp4' +} +``` + +## @用户 at + +::: tip 温馨提示 +开发者只需要关注uid字段即可 +::: + +```js +const at = segment.at('abc1234567890', '1234567890') +console.log(at) +``` + +输出: + +```js +{ + type: 'at', + uid: 'abc1234567890', + uin: '1234567890' // 二选一 推荐使用uid +} +``` + +## 戳一戳 poke + +关于这部分,见[mirai](https://github.com/mamoe/mirai/blob/f5eefae7ecee84d18a66afce3f89b89fe1584b78/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/HummerMessage.kt#L49) + +```js +const poke = segment.poke(1, -1, 1) +console.log(poke) +``` + +输出: + +```js +{ + type: 'poke', + poke: 1, // 类型 + id: -1, // id + strength: 1 // 强度 已知只有shamrock可以发送 +} +``` + +## 链接分享 share + +```js +const share = segment.share('https://example.com/share', '分享标题', '分享描述', '图片 URL') +console.log(share) +``` + +输出: + +```js +{ + type:'share', + url: 'https://example.com/share', + title: '分享标题', + content: '分享描述', + image: '图片 URL' +} +``` + +## 推荐好友或群 contact + +```js +const contact = segment.contact('qq', '12345') +console.log(contact) +``` + +输出: + +```js +{ + type: 'contact', + platform: 'qq', // 'qq' 表示推荐好友,'group' 表示推荐群 + id: '12345' // 被推荐人的 QQ 号或被推荐群的群号 +} +``` + +## 位置 location + +```js +const location = segment.location('121.527328', '31.21515', '上海市浦东新区', '内容描述') +console.log(location) +``` + +输出: + +```js +{ + type: 'location', + lat: '121.527328', // 纬度 + lon: '31.21515', // 经度 + title: '上海市浦东新区', // 标题 (可选) + content: '内容描述' // 内容描述 (可选) +} +``` + +## 音乐分享 music + +```js +const music = segment.music('qq', '12345') +console.log(music) +``` + +输出: + +```js +{ + type:'music', + platform: 'qq', // 音乐类型,'qq', '163', 'xm' + id: '12345' // 歌曲 ID +} +``` + +## 自定义音乐分享 customMusic + +```js +const customMusic = segment.customMusic('https://example.com/music.mp3', 'https://example.com/music.mp3', '标题', '内容描述', 'https://example.com/image.jpg') +console.log(customMusic) +``` + +输出: + +```js +{ + type: 'customMusic', + url: 'https://example.com/music.mp3', // 点击后跳转目标 URL + audio: 'https://example.com/music.mp3', // 音乐 URL + title: '标题', // 标题 + content: '内容描述', // 内容描述 + image: 'https://example.com/image.jpg', // 图片 URL +} +``` + +## 回复 reply + +```js +const reply = segment.reply('1234567890') +console.log(reply) +``` + +输出: + +```js +{ + type:'reply', + message_id: '1234567890' +} +``` + +## 发送res_id合并转发 forward + +```js +const forward = segment.forward('abs1234567890') +console.log(forward) +``` + +输出: + +```js +{ + type: 'forward', + id: 'abs1234567890' +} +``` + +## 合并转发自定义节点 node + +```js +const node = segment.node('1234567890', 'karin', [segment.text('Hello, world!')]) +console.log(node) +``` + +输出: + +```js +{ + type: 'node', + user_id: '1234567890', + nickname: 'karin', + content: [ + { + type: 'text', + text: 'Hello, world!' + } + ] +} +``` + +## xml + +```js +const xml = segment.xml('...', 'id') +console.log(xml) +``` + +输出: + +```js +{ + type: 'xml', + data: '...', + id: 'id' +} +``` + +## JSON + +```js +const json = segment.json('JSON 内容') +console.log(json) +``` + +输出: + +```js +{ + type: 'json', + data: 'JSON 内容' +} +``` + +## markdown消息 + +```js +// 原生markdown内容 +const markdown = segment.markdown('## 标题\n- 列表1\n- 列表2') + +// 模板markdown参数 此为QQBot官方字段,其他平台不可用 +const markdown = segment.markdown({ + custom_template_id: '模板ID', + params: [ + { key: 'title', values: ['标题'] }, + { key: 'list', values: ['列表1'] } + ] +}) +console.log(markdown) +``` + +输出: + +```js +// 原生markdown内容 +{ + type:'markdown', + content: '## 标题\n- 列表1\n- 列表2' +} + +// 模板markdown参数 此为QQBot官方字段,其他平台不可用 +{ + type:'markdown', + custom_template_id: '模板ID', + params: [ + { key: 'title', values: ['标题'] }, + { key: 'list', values: ['列表1', '列表2'] } + ] +} +``` + +## rows按钮 QQBot官方格式 + +::: tip 温馨提示 +rows和button的键入值一致,且比较复杂,请查看最下方的构建方法,这里只展示输出 +::: + +::: details 点我查看输出示例 + +```js:line-numbers {1} + { + type: 'rows', + rows: [ + { + buttons: [ + { + id: '1', + render_data: { + label: '⬅️上一页', + visited_label: '⬅️上一页' + }, + action: { + type: 1, + permission: { + type: 1, + specify_role_ids: [ + '1', + '2', + '3' + ] + }, + click_limit: 10, + unsupport_tips: '兼容文本', + data: 'data', + at_bot_show_channel_list: true + } + }, + { + id: '2', + render_data: { + label: '➡️下一页', + visited_label: '➡️下一页' + }, + action: { + type: 1, + permission: { + type: 1, + specify_role_ids: [ + '1', + '2', + '3' + ] + }, + click_limit: 10, + unsupport_tips: '兼容文本', + data: 'data', + at_bot_show_channel_list: true + } + } + ] + }, + { + buttons: [ + { + id: '3', + render_data: { + label: '📅 打卡(5)', + visited_label: '📅 打卡(5)' + }, + action: { + type: 1, + permission: { + type: 1, + specify_role_ids: [ + '1', + '2', + '3' + ] + }, + click_limit: 10, + unsupport_tips: '兼容文本', + data: 'data', + at_bot_show_channel_list: true + } + } + ] + } + ] +} + +``` + +::: + +## button按钮 + +::: tip 温馨提示 +rows和button的键入值一致,且比较复杂,请查看最下方的构建方法,这里只展示输出 +::: + +::: details 点我查看输出示例 + +```js:line-numbers {1} +{ + type: 'button', + buttons: [ + { + id: '1', + render_data: { + label: '⬅️上一页', + visited_label: '⬅️上一页' + }, + action: { + type: 1, + permission: { + type: 1, + specify_role_ids: [ + '1', + '2', + '3' + ] + }, + click_limit: 10, + unsupport_tips: '兼容文本', + data: 'data', + at_bot_show_channel_list: true + } + }, + { + id: '2', + render_data: { + label: '➡️下一页', + visited_label: '➡️下一页' + }, + action: { + type: 1, + permission: { + type: 1, + specify_role_ids: [ + '1', + '2', + '3' + ] + }, + click_limit: 10, + unsupport_tips: '兼容文本', + data: 'data', + at_bot_show_channel_list: true + } + } + ] +} +``` + +::: + +## rows按钮、button按钮构建方法 + +::: tip 温馨提示 +以下所有代码,`segment.rows`和`segment.button`均可使用 +所有未出现在快速构建方法中的参数,均为可选参数,可以根据需要选择是否传入 +::: + +### 跳转按钮 + +```js:line-numbers {1} +// 快速构建 +segment.rows({ link: 'https://example.com' }) + +// 完整构建 +segment.rows({ + text: '链接跳转', // 按钮默认显示的文本 + show: '链接跳转', // 按钮点击后显示的文本 + link: 'https://example.com', + style: 0, // 按钮样式 0 灰色线框,1 蓝色线框 默认 0 + admin: false, // 设置为true时,只有群管理员可以点击 + list: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 + role: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 (仅频道可用) + tips: '指令提示' // 客户端不支持本 action 的时候,弹出的 toast 文案 +}) + +``` + +### 回调按钮 + +```js:line-numbers {1} +// 快速构建 +segment.rows({ type: 1, text: '回调按钮'}) + +// 完整构建 +segment.rows({ + type: 1, // 按钮类型 1 回调按钮 + text: '回调按钮', // 按钮默认显示的文本 + show: '回调按钮', // 按钮点击后显示的文本 + data: '操作相关数据', // 回调数据 + style: 0, // 按钮样式 0 灰色线框,1 蓝色线框 默认 0 + admin: false, // 设置为true时,只有群管理员可以点击 + list: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 + role: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 (仅频道可用) + tips: '指令提示' // 客户端不支持本 action 的时候,弹出的 toast 文案 +}) + +``` + +### 指令按钮 + +```js:line-numbers {1} +// 快速构建 +segment.rows({ text: '指令按钮' }) + +// 完整构建 +segment.rows({ + type: 2, // 按钮类型 2 指令按钮 + text: '指令按钮', // 按钮默认显示的文本 + show: '指令按钮', // 按钮点击后显示的文本 + data: '操作相关数据', // 指令数据 + style: 0, // 按钮样式 0 灰色线框,1 蓝色线框 默认 0 + enter: true, // 设置为true时,点击按钮后直接自动发送 data,默认 false + reply: true, // 设置为true时,点击按钮后回复当前消息,默认 false + admin: false, // 设置为true时,只有群管理员可以点击 + list: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 + role: ['用户ID1', '用户ID2'], // 设置后,只有这些用户可以点击,与admin互斥 (仅频道可用) + tips: '指令提示' // 客户端不支持本 action 的时候,弹出的 toast 文案 +}) diff --git a/docs/utils/update.md b/docs/utils/update.md new file mode 100644 index 0000000..e69de29