功能限制与实现细节
音频发送策略
云湖的机器人接口不允许机器人直接发送音频文件(用户可以发送语音,但机器人不能)。早期适配器会把音频通过 ctx.ffmpeg 转成带纯色背景的视频再发送,但视频消息在聊天中会占据较大的上下高度,容易造成刷屏。
当前适配器会根据音频来源采用两种策略:
| 音频来源 | 发送方式 |
|---|---|
| 公网可访问的 HTTP(S) 链接 | 使用 A2UI 协议发送 AudioPlayer 播放器组件 |
| 内网、本机或云湖无法公网访问的链接 | 下载并上传音频,再通过适配器配置的媒体代理地址交给 AudioPlayer 播放 |
公网音频链接
当 <audio> 元素的 src 是公网可访问的 HTTP(S) 链接时,适配器会生成 A2UI 消息(contentType: 'a2ui'),云湖客户端可以直接渲染播放器,无需转换成视频。
await session.send(h('audio', {
src: 'https://example.com/audio.mp3',
title: '示例音频',
}));适配器会排除 localhost、127.0.0.1 以及内网 IPv4 地址;如果你的域名实际无法被云湖访问,请先将其替换为公网可访问的链接。
内网音频链接
如果音频链接是内网地址、本机地址,或无法被云湖客户端直接访问,适配器会下载原始音频并上传,再通过媒体代理地址提供给客户端。最终仍然是 A2UI 消息,不会转换为视频消息。
为什么不直接使用文件上传接口得到的原始地址?
云湖 A2UI 播放器请求音频时可能受到富媒体资源请求头限制。适配器因此对非公网来源的音频使用媒体代理地址,避免播放器无法加载资源。
文件大小限制
云湖对不同类型的文件有严格的上传大小限制:
- 图片:最大 10MB
- 视频:最大 20MB
- 其他文件:最大 20MB
为了尽可能确保文件能成功发送,适配器会进行如下处理:
- 超限视频:如果视频大小超过 20MB,适配器会尝试使用
ctx.ffmpeg对其进行一次压缩。如果压缩后的大小符合限制,则会发送;否则,操作将失败。 - 超限图片和文件:适配器无法处理超限的图片或其他文件,将直接抛出错误。
图片资源访问
直接访问云湖的图片 URL 会因为缺少 Referer 请求头而导致 403 Forbidden 错误。
您必须在请求中添加 Referer: https://www.yhchat.com/ 头才能成功获取图片。
以下是一个使用 curl 访问图片的示例:
curl --location 'https://chat-img.jwznb.com/a0068c6770fe2df08d1923287bb9cdbf.jpg' \
--header 'Referer: https://www.yhchat.com/'额外接口的来源
本适配器提供的一些非官方额外接口,其实现逻辑来源于对以下几个 Web 页面的网络请求分析:
https://www.yhchat.com/user/homepage/7756242https://yhfx.jwznb.com/share?key=0FRmLHlPL47M&ts=1761497803https://yhfx.jwznb.com/share?key=m7Z4l2bLBWt2&ts=1761497822
Webhook GET 请求处理
在设置 Webhook 监听地址时,为了方便用户确认该路径可被公网访问,适配器对 GET 请求进行了额外处理。
当您通过浏览器访问 Webhook 路径时,会看到一个说明页面,用于验证连通性。
发送富文本消息
本适配器支持通过 Koishi 的 h() 函数 发送 Markdown 和 HTML 格式的消息。
Markdown 消息
使用 <yunhu:markdown> 元素来发送 Markdown 格式的内容。
ctx
.command('md测试')
.action(async ({ session }) => {
const markdownContent = '# 你好\n## 这是 Markdown!';
await session.send(h('yunhu:markdown', markdownContent));
await session.send(h('markdown', markdownContent));
});HTML 消息
使用 <html> 元素来发送 HTML 格式的内容。
ctx
.command('html测试')
.action(async ({ session }) => {
const htmlContent = '<h1>你好</h1><h2>这是 HTML!</h2>';
await session.send(h('yunhu:html', htmlContent));
await session.send(h('html', htmlContent));
});WARNING
注意!
常见问题:我复制了以上demo指令 html测试,为什么发出来的内容里有一个是图片呢?
这是因为你的koishi用插件实现了 component:html 服务。此服务一般由 puppeteer 插件提供。
此时你有两个解决方法:
- 不使用
h("html"),改为使用h("yunhu:html") - 不使用puppeteer的
component:html服务。如果你不希望使用此服务。可以使用@shangxueink/puppeteer-without-canvas插件。
指令前缀兼容性
云湖平台的所有机器人指令都带有一个固定且不可修改的前缀 /。
为了确保在 Koishi 中定义的指令能够被正确触发,您必须将 / 添加到 Koishi 的指令前缀配置中。
可以在 Koishi 控制台的“全局设置”下的
prefix配置项中完成。
集成侧边栏
为了方便您在 Koishi 控制台中快速管理机器人,本适配器在侧边栏注册了一个云湖图标。
点击该图标,即可直接跳转到云湖的官方控制台,无需离开koishi控制台。