接着上一章继续写基础。想了想好像JS基础知识没什么要介绍的了,直接写插件教程了,如果有补充(比如说完全没有讲的TS)会穿插在插件教程里。
Koishi 插件写作
之前提到过怎么创建插件,这里不赘述了,不记得的可以翻#4,接下来逐个介绍Koishi的各个机能。
ctx
ctx的类型是Context(上下文),绝大部分Koishi功能都通过ctx提供,比如指令command,监听on,服务器server等等。接下来会先介绍最重要的指令开发。
指令开发
import { Context, Schema } from 'koishi'
export const name = 'echo'
export interface Config {}
export const Config: Schema<Config> = Schema.object({})
export function apply(ctx: Context) {
ctx.command('echo <msg>')
.action((_, message) => message);
}
如上,这是一个插件index.ts文件,用Typescript语言编写。
与JS不同的是,TS是一门强类型语言。我们注意到:ctx: Context 以及 Config: Schema ,冒号之前表示变量,冒号之后表示类型。比如说我们在ts中声明一个number变量我们可以这样写:
<em>let a: number = 1</em>
不过我们也不需要每时每刻都手动写出类型,ts具有强大的类型推断功能,我们一般情况下只需要和js一样写作,省略类型即可。
然后注意到文件中的import export,表示引入的类型或者功能对象,以及导出的函数(比如说apply函数,作为插件的入口)。
指令开发的格式如下:
ctx.command('指令名 <参数1> <参数2> [参数3]')
.action((_, arg1, arg2, arg3) => { /* 功能 */ })
看到第一行,我们传一个定义指令的字符串到函数参数内:用尖括号括起来的是必选参数,用中括号括起来的是可选参数。意思是,如果一个用户发送该指令没有包含所有的必选参数,Koishi是不会响应的。另外,所有的可选参数肯定只能放在必选参数后面(识别顺序问题)。
看到第二行,跟一个.action表示定义该指令的行为,我们会传一个函数来定义指令的行为。我们也称这个函数叫做回调函数,意思是当你触发了这条指令,就会回调相应的功能。这里我们采用箭头函数的简便写法,首先第一个是保留参数 _ ,里面包含了许多消息中包含的信息,这里我们暂时还用不到,后面arg1~3表示的是我们定义指令时传进来的三个参数。
ctx.command('echo <msg>')
.action((_, message) => message);
意思是: 我们定义的指令名称叫echo,有一个必选参数msg,如果不包含参数将不会触发指令。指令的行为是:返回这个msg。所以说,当我们发送:echo 123时,bot就会回复123。
例子:我们定义一个指令add,有三个可选参数,分别表示可能的加数。例如 add 1 2 将会返回 3,add 1 2 3 将会返回 6,add 将会返回 0。我们可以这样写我们的指令:
ctx.command('add [arg1] [arg2] [arg3]')
.action((_, arg1, arg2, arg3) => {
let sum = 0;
if(arg1) sum += arg1;
if(arg2) sum += arg2;
if(arg3) sum += arg3;
return sum;
});
它的意思是:定义一个变量记录最终的答案,如果arg1存在,则答案加上arg1,以此类推,最后返回sum。
更多和指令开发有关的知识可以学习官方文档:指令开发
监听
它的格式是:
ctx.on(事件名称, 回调函数)
监听的效果是:当事件发生时,会执行什么样的步骤。事件名称比如说有:message,当监听收到一条消息;friend-request,当有好友请求时;等等。所有事件的参考可以看这里。
例子一:当收到天王盖地虎,会回复宝塔镇河妖。(引用自Koishi官网)
ctx.on('message', (session) => {
if (session.content === '天王盖地虎') { // session.content取出收到消息的内容
session.send('宝塔镇河妖') // session.send在当前对话环境下发送消息
}
})
例子二:bot唤醒信息(引用自Koishi官网)
// bot-status-updated 不是会话事件
// 所以回调函数接受的参数不是 session 而是 bot
ctx.on('bot-status-updated', (bot) => {
if (bot.status === Status.ONLINE) { // bot.status 取出机器人实例的在线状态 Status.ONLINE表示机器人在线
// 这里的 userId 换成你的账号
bot.sendPrivateMessage(userId, '我上线了~')
}
})
更复杂的消息 - 消息元素
有时我们发送的不只是照片,还有可能是一张照片,一个视频或者一个文件;消息中还可能包含引用消息或者艾特用户。我们将用h元素来构造更加复杂的消息。
首先我们在源文件最顶端引入h元素:
import { h } from 'koishi';
然后我们可以在任何发送消息的场景使用h元素,包括command中的return,监听message时的session.send等等。我们使用示例如下, 应该包含了大部分的情况:
import { h } from 'koishi'
// 最简单:纯文本消息(等价于发送 "你好")
h('message', '你好') // 用于构造一条普通文本消息
// 发送一张图片
h('img', { src: 'https://koishi.chat/logo.png' }) // src 是图片链接
// @某个用户
h('at', { id: 123456 }) // id 是要提及的用户ID
// 引用一条消息
h('quote', { id: 'abcd1234' }) // 引用消息ID,用于回复或上下文引用
// 组合多元素消息
h('message', [
'你好,', // 普通文本
h('at', { id: 123456 }), // 提及用户
',欢迎回来!' // 普通文本
]) // children 可为数组,表示组合发送多个元素
// 图片与文本混合
h('message', [
'给你看张图:',
h('img', { src: 'https://example.com/pic.png' }),
'好看吧?'
])
// 嵌套结构
h('message', [
h('quote', { id: 'm123' }, [
'上一条消息内容'
]),
'这是我的回复'
])
例子:当一个用户进群之后,发送一条欢迎消息,包含:欢迎 xxx 进群!+ 该用户的头像
export function apply(ctx: Context) {
// 监听用户入群事件
ctx.on('guild-member-added', async (session) => {
// 使用session.userId获取QQ号
const userId = session.userId;
// 构造欢迎消息
const message = h('message', [
"欢迎 ",
h('at', { id: userId }),
"进群!",
h('img', { src: `http://q2.qlogo.cn/headimg_dl?dst_uin=${userId}&spec=100` }) // 头像API
])
// 发送消息到当前群
await session.send(message)
})
}
效果如下:

最后
下一节会解答群友的疑惑,以及实现群友需求的部分插件。

Comments NOTHING