消息事件示例
本文档提供了云湖机器人接收到的不同类型消息事件的 JSON 结构示例,按照 event.message.contentType 进行分类。
消息类型
当机器人在群组或私聊中收到普通消息时,会触发此事件。根据消息内容的不同,event.message.contentType 字段会有不同的取值:
text: 文本消息image: 图片消息markdown: Markdown 格式消息file: 文件消息form: 表单消息(指令消息)tip: 提示消息
文本消息
最基础的文本消息。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
header.eventType | string | 事件类型 | message.receive.normal |
event.sender.senderId | string | 发送者 ID | "7756242" |
event.chat.chatId | string | 会话 ID (群组或用户) | "307149245" |
event.message.msgId | string | 消息的唯一 ID | "930a7bad5d8144c5b25bc161031bb82b" |
event.message.contentType | string | 消息内容类型 | "text" |
event.message.content.text | string | 消息的文本内容 | "这是一条普通消息" |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "d1ae39a31063408099b5961ed637f10c",
"eventType": "message.receive.normal",
"eventTime": 1761214759404
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "307149245",
"chatType": "group"
},
"message": {
"msgId": "930a7bad5d8144c5b25bc161031bb82b",
"parentId": "",
"sendTime": 1761214759381,
"chatId": "307149245",
"chatType": "group",
"contentType": "text",
"content": {
"text": "这是一条普通消息",
"menu": {
"": "北京"
}
},
"instructionId": 0,
"instructionName": "",
"commandId": 0,
"commandName": ""
}
}
}图片消息
包含图片的消息。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
event.message.contentType | string | 消息内容类型 | "image" |
event.message.content.imageUrl | string | 图片的 URL | "https://..." |
event.message.content.imageName | string | 图片文件名 | "e4f...png" |
event.message.content.imageWidth | number | 图片宽度 (像素) | 512 |
event.message.content.imageHeight | number | 图片高度 (像素) | 465 |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "1fe12e6f9ab942e39468c4de0de66bb0",
"eventType": "message.receive.normal",
"eventTime": 1761214895781
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "307149245",
"chatType": "group"
},
"message": {
"msgId": "467066ccf64641ab84fb7a9f6d354959",
"parentId": "",
"sendTime": 1761214895677,
"chatId": "307149245",
"chatType": "group",
"contentType": "image",
"content": {
"imageUrl": "https://chat-storage1.jwznb.com/e4f77d3729a7fc3e5040be276b3c569b.png?sign=9dcdb53f9eb836ad30bf6b966dc936b8&t=68fa0fbf",
"imageName": "e4f77d3729a7fc3e5040be276b3c569b.png",
"etag": "Fs4Kfnw0zx08tcXkZ7Blv56oqPXe",
"imageWidth": 512,
"imageHeight": 465,
"menu": {
"": "北京"
}
},
"instructionId": 0,
"instructionName": "",
"commandId": 0,
"commandName": ""
}
}
}文件消息
包含文件的消息。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
header.eventType | string | 事件类型 | message.receive.normal |
event.sender.senderId | string | 发送者 ID | "7756242" |
event.chat.chatId | string | 会话 ID (群组或用户) | "307149245" |
event.message.msgId | string | 消息的唯一 ID | "e70bb54c40424deabad0f1e4e40a0c7c" |
event.message.contentType | string | 消息内容类型 | "file" |
event.message.content.fileName | string | 文件名称 | "1601237804-1-16.mp4" |
event.message.content.fileUrl | string | 文件 URL | "03127b650c0c4fc2a535ee47e2178d54" |
event.message.content.etag | string | 文件唯一标识 | "FuZVWM-3ZYi5NYnaKM3PPWMGBcRa" |
event.message.content.fileSize | number | 文件大小(字节) | 1504310 |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "2f65029fd6c542adaaa76467856d5201",
"eventType": "message.receive.normal",
"eventTime": 1763215557323
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "307149245",
"chatType": "group"
},
"message": {
"msgId": "e70bb54c40424deabad0f1e4e40a0c7c",
"parentId": "",
"sendTime": 1763215557280,
"chatId": "307149245",
"chatType": "group",
"contentType": "file",
"content": {
"fileName": "1601237804-1-16.mp4",
"fileUrl": "03127b650c0c4fc2a535ee47e2178d54",
"etag": "FuZVWM-3ZYi5NYnaKM3PPWMGBcRa",
"fileSize": 1504310,
"menu": {}
},
"instructionId": 0,
"instructionName": "",
"commandId": 0,
"commandName": ""
}
}
}markdown消息
包含 Markdown 格式文本的消息。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
header.eventType | string | 事件类型 | message.receive.normal |
event.sender.senderId | string | 发送者 ID | "7756242" |
event.chat.chatId | string | 会话 ID (群组或用户) | "307149245" |
event.message.msgId | string | 消息的唯一 ID | "c573840bfe444f998aa53fe923df0b77" |
event.message.contentType | string | 消息内容类型 | "markdown" |
event.message.content.text | string | Markdown 格式的文本内容 | "# 你好\n## 这是二级标题" |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "5edb68b4208f4c4d83147bd8b827f9b8",
"eventType": "message.receive.normal",
"eventTime": 1763215594710
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "307149245",
"chatType": "group"
},
"message": {
"msgId": "c573840bfe444f998aa53fe923df0b77",
"parentId": "",
"sendTime": 1763215594645,
"chatId": "307149245",
"chatType": "group",
"contentType": "markdown",
"content": {
"text": "# 你好\n## 这是二级标题",
"menu": {}
},
"instructionId": 0,
"instructionName": "",
"commandId": 0,
"commandName": ""
}
}
}提示消息
系统提示消息,通常用于通知群组成员变更等系统事件。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
header.eventType | string | 事件类型 | message.receive.normal |
event.sender.senderId | string | 发送者 ID | "7756242" |
event.chat.chatId | string | 会话 ID (群组或用户) | "307149245" |
event.message.msgId | string | 消息的唯一 ID | "c22c24fc-8e3f-4480-a05b-3b491f07e1da" |
event.message.contentType | string | 消息内容类型 | "tip" |
event.message.content.text | string | 提示消息的文本内容 | "已将\"小小学?\"添加为群管理员" |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "a346f840280045a1baa268ce87af3cf8",
"eventType": "message.receive.normal",
"eventTime": 1763212071049
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": ""
},
"chat": {
"chatId": "307149245",
"chatType": "group"
},
"message": {
"msgId": "c22c24fc-8e3f-4480-a05b-3b491f07e1da",
"parentId": "",
"sendTime": 1763212071009,
"chatId": "307149245",
"chatType": "group",
"contentType": "tip",
"content": {
"text": "已将\"小小学?\"添加为群管理员"
},
"instructionId": 0,
"instructionName": "",
"commandId": 0,
"commandName": ""
}
}
}指令消息
当用户通过指令菜单、或直接发送以 / 开头的文本与机器人交互时,会触发此事件。
指令消息的事件类型为 message.receive.instruction,根据交互方式的不同,event.message.contentType 字段会有不同的取值:
text: 直接指令(用户直接发送以/开头的文本)form: 自定义指令(用户通过指令菜单中的自定义输入表单触发)
前往网页控制台以配置你的机器人指令。
下面我们将使用几个demo级别的指令来做演示:
| 指令名称 | 描述 | ID |
|---|---|---|
| 这是直接发的指令 | 直接发的指令 | 2103 |
| 这是普通指令 | 这是普通指令 | 2104 |
| 这是自定义输入指令 | 这是自定义输入指令的描述 | 2105 |
| help | help | 2107 |
指令消息 - 文本类型
用户直接发送以 / 开头的文本触发的指令。
文本类型指令又分为 直接指令 和 普通指令 。
关键字段说明
| 字段路径 | 类型 | 描述 | 示例值 |
|---|---|---|---|
header.eventType | string | 事件类型 | message.receive.instruction |
event.sender.senderId | string | 发送者 ID | "7756242" |
event.chat.chatId | string | 会话 ID | "37090343" |
event.message.msgId | string | 消息的唯一 ID | "5d6c47a6fc124653a67fa67c595ea08f" |
event.message.contentType | string | 消息内容类型 | "text" |
event.message.content.text | string | 消息的文本内容 | "/这是直接发的指令" |
event.message.instructionId | number | 指令的唯一 ID | 2103 |
event.message.instructionName | string | 指令的名称 | "这是直接发的指令" |
完整 JSON 示例 —— 直接指令
{
"version": "1.0",
"header": {
"eventId": "b2dc5986402545ce80a7bf5b862010c8",
"eventType": "message.receive.instruction",
"eventTime": 1761208476688
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "37090343",
"chatType": "bot"
},
"message": {
"msgId": "5d6c47a6fc124653a67fa67c595ea08f",
"parentId": "",
"sendTime": 1761208476676,
"chatId": "37090343",
"chatType": "bot",
"contentType": "text",
"content": {
"text": "/这是直接发的指令",
"menu": {
"MW941CUD": "0",
"S5VCMYU4": "北京"
}
},
"instructionId": 2103,
"instructionName": "这是直接发的指令",
"commandId": 2103,
"commandName": "这是直接发的指令"
}
}
}完整 JSON 示例 —— 普通指令
{
"version": "1.0",
"header": {
"eventId": "86895467a4644819b4ba744ac1f44053",
"eventType": "message.receive.instruction",
"eventTime": 1761208548716
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "37090343",
"chatType": "bot"
},
"message": {
"msgId": "4bfd90b450eb4c1daf63e9491d8d04c2",
"parentId": "",
"sendTime": 1761208548672,
"chatId": "37090343",
"chatType": "bot",
"contentType": "text",
"content": {
"text": "这是普通指令的默认文字 饿啊",
"menu": {
"MW941CUD": "0",
"S5VCMYU4": "北京"
}
},
"instructionId": 2104,
"instructionName": "这是普通指令",
"commandId": 2104,
"commandName": "这是普通指令"
}
}
}指令消息 - 表单类型
用户通过指令菜单中的自定义输入表单触发的指令。
关键字段说明
| 字段路径 | 类型 | 描述 |
|---|---|---|
event.message.contentType | string | 消息内容类型,固定为 "form" |
event.message.content.formJson | object | 用户提交的表单数据 |
event.message.instructionId | number | 指令的唯一 ID |
event.message.instructionName | string | 指令的名称 |
完整 JSON 示例
{
"version": "1.0",
"header": {
"eventId": "f27ea6f554b347058852f55502b2d2b7",
"eventType": "message.receive.instruction",
"eventTime": 1761208636918
},
"event": {
"sender": {
"senderId": "7756242",
"senderType": "user",
"senderUserLevel": "owner",
"senderNickname": "小学不在这里哦"
},
"chat": {
"chatId": "37090343",
"chatType": "bot"
},
"message": {
"msgId": "e37a993ce328455caf6d5d9ae1d9d6ee",
"parentId": "",
"sendTime": 1761208636906,
"chatId": "37090343",
"chatType": "bot",
"contentType": "form",
"content": {
"formJson": {
"loktny": {
"id": "loktny",
"type": "input",
"label": "这是自定义输入指令的标签",
"value": "这是自定义输入指令的标签的默认内容"
}
},
"menu": {
"MW941CUD": "0",
"S5VCMYU4": "北京"
}
},
"instructionId": 2105,
"instructionName": "这是自定义输入指令",
"commandId": 2105,
"commandName": "这是自定义输入指令"
}
}
}Koishi 指令开发
上文中展示的各类消息和指令事件,都可以通过 Koishi 的中间件和指令系统进行响应和处理。
本节将通过几个示例,演示如何为不同类型的指令创建处理器。
首先要注意,云湖平台设置的指令,都带有/前缀,
你需要在koishi的全局设置里配置此指令前缀,才能正确响应对应的指令。
响应直接指令
以下代码演示了如何创建一个响应 这是直接发的指令 的指令处理器。
当用户发送 /这是直接发的指令 时,该处理器会被触发,并返回 Hello from 直接指令!。
session 对象中包含了完整的事件信息,日志中展示了其详细结构。
ctx
.command('这是直接发的指令')
.action(async ({ session }, jsoninput) => {
ctx.logger.info(session)
return 'Hello from 直接指令!'
})2025-10-24 10:26:11 [I] testplugin Session { id: 3495, sn: 3495, event: { type: 'message-created', platform: 'yunhu', selfId: '37090343', timestamp: 1761272772508, user: { id: '7756242', type: 'user', name: '小学不在这里哦', role: 'owner' }, message: { id: '163bc710f8b8400a88ccb88692e75986', content: '/这是直接发的指令', elements: [ Element { type: 'text', attrs: { content: '/这是直接发的指令' }, children: [] } ], quote: undefined }, channel: { type: 0, id: 'group:307149245' }, guild: { id: '307149245' }, member: { user: { id: '7756242', type: 'user', name: '小学不在这里哦', role: 'owner' }, name: '小学不在这里哦' } }, locales: [], _stripped: { hasAt: false, content: '/这是直接发的指令', appel: false, atSelf: false, prefix: '/' }, guild: { permissions: [], locales: [], platform: 'yunhu', id: '307149245' }, channel: { permissions: [], locales: [], platform: 'yunhu', id: 'group:307149245' }, user: { id: 837, flag: 0, authority: 1, permissions: [], locales: [] }, scope: 'commands.这是直接发的指令.messages', [Symbol(cordis.tracker)]: { associate: 'session', property: 'ctx' } }响应普通指令
“普通指令”指用户通过点击指令菜单中的普通按钮来触发的指令。
这类指令通常会附带一些预设的文本或用户输入的参数。
下面的示例创建了一个名为 这是普通指令 的指令,并使用 [...args] 来接收所有后续参数。
当指令被触发时,args 数组将包含指令名称后的所有参数内容。
ctx
.command('这是普通指令 [...args]')
.action(async ({ session }, ...args) => {
ctx.logger.info('用户输入的参数为:', args)
return 'Hello from 普通指令!'
})2025-10-24 10:28:43 [I] testplugin 用户输入的参数为: [ '这是普通指令的默认文字', '然后这里是额外输入内容' ]响应自定义输入指令
云湖平台的一大特色是支持开发者创建自定义的指令输入表单。
当用户提交表单后,适配器会将表单数据作为一个 JSON 字符串,完整地传递给对应的指令。
下面的示例演示了如何处理这种自定义输入。
指令定义中的 [jsoninput] 参数将接收到用户提交的全部表单数据。
ctx
.command('这是自定义输入指令 [jsoninput]')
.action(async ({ session }, jsoninput) => {
ctx.logger.info('用户输入的json表单内容为:', jsoninput)
return 'Hello from 测试!'
})2025-10-24 10:32:48 [I] testplugin 用户输入的json表单内容为: {"loktny":{"id":"loktny","type":"input","label":"这是自定义输入指令的标签","value":"这是自定义输入指令的标签的默认内容"}}监听交互事件
除了响应指令消息,您还可以通过监听特定事件来处理用户的交互,例如点击按钮。
以下代码演示了如何监听 interaction/button 事件。当用户点击任何一个由机器人发送的按钮时,这个监听器就会被触发,并打印出 session 对象,其中包含了关于该次交互的详细信息。
ctx.on('interaction/button', async (session) => {
ctx.logger.info(session)
})2025-10-24 10:34:59 [I] testplugin Session { id: 3535, sn: 3535, event: { selfId: '37090343', platform: 'yunhu', timestamp: 1761273299284, _type: 'yunhu', _data: { version: '1.0', header: { eventId: 'e9d1baeeb3f041b6bad5730195023911', eventType: 'bot.shortcut.menu', eventTime: 1761273300022 }, event: { botId: '37090343', menuId: 'MNM1L2YC', menuType: 1, menuAction: 1, chatId: '307149245', chatType: 'group', senderType: 'user', senderId: '7756242', sendTime: 1761273300 }, [Symbol(unparsedBody)]: '{"version":"1.0","header":{"eventId":"e9d1baeeb3f041b6bad5730195023911","eventType":"bot.shortcut.menu","eventTime":1761273300022},"event":{"botId":"37090343","menuId":"MNM1L2YC","menuType":1,"menuAction":1,"chatId":"307149245","chatType":"group","senderType":"user","senderId":"7756242","sendTime":1761273300}}' }, type: 'interaction/button', user: { id: '7756242' }, channel: { id: 'group:307149245' }, guild: { id: '307149245' }, button: { id: 'MNM1L2YC' } }, locales: [], [Symbol(cordis.tracker)]: { associate: 'session', property: 'ctx' } }