Koishi 插件开发入门教程(一)

本作品采用BY-NC-SA(知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议)进行许可。转载请标明转载源。

本文已同样方式发布于本人的微信公众号(沐辰的小窝)

一、前提

阅读这个系列的文章,你需要有以下几个基础:

  • 已经正确安装NodeJS环境、Koishi
  • 学会如何使用Boilerplate命令行正确启动koishi
  • 学会如何使用一些基本插件(如如何使用适配器对接你的机器人到聊天平台)
  • 有基本的Javascript或TypeScript编程基础(只需要非常基础的就可以了)

如果没有满足上述两个条件,建议移步对应文档先行学习

传送门:创建模板项目 | Koishi

二、创建一个插件

koishi根目录(也就是有koishi.yml的目录),输入以下指令来创建一个插件:

$ yarn new  # 如果你是使用npm的用户,输入npm run new
yarn run v1.22.19
> koishi-scripts new
√ plugin name: ... #这里输入你的插件ID,回车继续,如"novelai"或者"inspect"
√ description: ... #这里输入你的插件描述,回车继续

在下面的示例中,我将以example为插件ID,给您介绍,如果您没有想好插件ID,可以先使用"example",下面是创建example插件的例子:

$ yarn new
yarn run v1.22.19
> koishi-scripts new
√ plugin name: ... example
√ description: ... A example plugin for koishi

接下来,你应该会在该目录下的plugin子目录里看到以你输入的插件ID为名称的文件夹。在这个文件夹中,你会发现有一个叫做src的文件夹,其中包含了一个交index.ts的文件,这个文件是插件的入口文件,一切插件都是从这里开始执行。

现在,这个文件中包含了一些样板代码,你可以在这里开始编写你的插件代码。这是example生成出的代码的内容:

import { Context, Schema } from 'koishi'

export const name = 'example'

export interface Config {}

export const Config: Schema<Config> = Schema.object({})

export function apply(ctx: Context) {
  // write your plugin here
}

第一行,import { Context, Schema } from 'koishi'是从koishi的核心中导入了插件上下文和配置结构的定义,关于这两者的用途和使用方法我将会在后续的文章中进行介绍。

后面的三行,也就是从export const name = 'example'export const Config: Schema<Config> = Schema.object({}),定义了插件的名称和支持的配置项。

而插件开发的重点,则是我们最后的这个apply函数,我们将在下一章详细讲解这个函数的使用。

三、编写一个Hello World插件

从现在开始,你已经搭建好了开发一个项目的脚手架,那么,事不迟疑,我们马上进入插件开发。

首先,我们先要理解什么是apply函数。apply函数是你插件的主体代码,在你的插件被启用后就会执行apply函数内的内容。而apply函数的ctx参数则是一个与koishi或者其他插件交互的接口(然而这个理解不完全准确,我们会在后续进行补充),通过这个接口,你可以访问到你的机器人、注册机器人命令、访问数据库等等

所以你可以在apply函数中写入一个console.info("Hello World"),完成后的代码大概长这样:

//....此处省略插件定义......
export function apply(ctx: Context) {
  console.info("Hello world");
}

然后你需要在koishi.yml中启用这个插件(如果您习惯使用Koishi的Web页面管理可以在下一步以相同的方式启用),对于example插件,我们可以这样写:

plugins:
	#.....其他内容.......
	example: {}

然后,输入yarn dev或者npm run dev(请注意!这里不是你平常使用的yarn start或者npm start!!!),启动koishi并启用开发模式

你就能在控制台看到如下输出(这一部分是截取):

2022-12-09 11:02:56 [I] app apply plugin example
Hello world

如果完成了这一步,恭喜你,你的插件已经正确运行了,你已经迈出了插件制作的第一步。

四、中间件的初步使用

刚刚,我们已经在控制台成功实现了让koishi在控制台中输出Hello World,那么接下来,我们转战聊天平台,让你的机器人会说话。

我们将刚刚的代码修改,变成下面这种样子:

export function apply(ctx: Context) {
  ctx.middleware((session, next) => {
    if (session.content === '天王盖地虎') {
      return '宝塔镇河妖'
    } else {
      return next()
    }
  })
}

此时,你不需要再重启机器人,因为koishi自带的热重载功能会检测到你的插件已经发生了修改,会自动重新加载你的插件(请注意,这个功能只会在开发者模式下启用,所以必须使用yarn dev启动机器人),所以命令行上会输出

2022-12-09 11:15:57 [I] watch reload plugin at plugins\example\src\index.ts

这句日志表示检测到了插件被修改,自动重新加载了插件

此时,你需要打开你的聊天软件,找到你机器人绑定的聊天账号,并向机器人发送一句“天王盖地虎”(你也可以在机器人所在的群内发送),然后你就会收到来自机器人的消息,就像这样

沐辰-TimeBather : 天王盖地虎
你的可爱的机器人  : 宝塔镇河妖

自此,你的机器人已经可以和你做简单的交互了。

本篇完。

10 个赞

非常棒的教程!支持!

2 个赞

很棒的教程!终于可以一步步学习如何写插件了!

2 个赞

为什么我一步一步跟着做出现了这种错误 :sneezing_face:

2023-05-18 10:00:38 [I] sqlite auto creating table stats_longterm
√ plugin name: ... motdping
√ description: ... motd的信息获取

added 1 package in 1s

D:\koishi-app>npm start

> koishi-app@0.0.0 start
> koishi startts new

2023-05-18 10:03:39 [I] app Koishi/4.12.9
2023-05-18 10:03:39 [I] app apply plugin group:entry
2023-05-18 10:03:39 [I] app apply plugin group:basic
.....
2023-05-18 10:03:40 [I] app apply plugin gocqhttp
2023-05-18 10:03:40 [I] assets missing config "selfUrl", fallback to "file:" scheme
2023-05-18 10:03:40 [I] app server listening at http://127.0.0.1:5140
2023-05-18 10:03:41 [W] config failed to resolve koishi-plugin-motdping
2023-05-18 10:03:41 [W] config Error: Cannot find module 'D:\koishi-app\node_modules\koishi-plugin-motdping\lib\index.js'. Please verify that the package.json has a valid "main" entry
                            at tryPackage (node:internal/modules/cjs/loader:436:19)
                            at Module._findPath (node:internal/modules/cjs/loader:678:18)
                            at Module._resolveFilename (node:internal/modules/cjs/loader:1061:27)
                            at Function.resolve (node:internal/modules/cjs/helpers:116:19)
                            at PackageProvider2.loadPackage (D:\koishi-app\node_modules\@koishijs\plugin-config\lib\node\index.js:151:29)
                            at PackageProvider2.loadDirectory (D:\koishi-app\node_modules\@koishijs\plugin-config\lib\node\index.js:137:14)
                            at async Promise.all (index 0)
                            at async PackageProvider2.prepare (D:\koishi-app\node_modules\@koishijs\plugin-config\lib\node\index.js:116:5)
                            at async PackageProvider2.get (D:\koishi-app\node_modules\@koishijs\plugin-config\lib\node\index.js:121:5)
                            at async PackageProvider2.refresh (D:\koishi-app\node_modules\@koishijs\plugin-console\lib\shared\index.js:66:14)
3 个赞

您好,请使用yarn dev/npm run dev

5 个赞

使用 yarn dev 启动开发模式。官方文档内对工作区开发作了详细介绍。

3 个赞

帮大忙的教程!很伟大的教程! :innocent:

3 个赞

催更!

3 个赞

我的插件开发就是从这里开始的(

5 个赞

不同的配置(字符串、选项、路径……)怎样在yml文件里设置, 并且在插件里调用呢?

2 个赞

koishi的一般插件开发 并不需要开发者来操作读取和写入koishi.yml文件,
你只需要根据需求,编写插件对应的配置项即可


至于调用,那就得依赖koishi了~

1 个赞

试过了,如果只在插件脚本里修改配置项的参数是没有效果的,而在koishi.yml`里修改就会生效。而且,配置项在插件里设置参数,必须要写入koishi.yml对应的插件参数下才可以。有些类型的参数,比如字符串,虽然能生效,但不会在后台的插件管理里显示。但是在插件里经过处理的字符串,比如路径,却可以在后台看到。这是为什么呢?

2 个赞

我找到原因了。原来是插件的函数主体如果使用默认的export function apply(ctx: Context, config: Config) ,就能在控制台看到。如果使用自定义的,export default function PluginName(ctx: Context, config: Config) , 就不能在插件管理的后台看到,虽然自定义的函数,插件参数也能生效。

2 个赞