使用媒体发送 API,你可以把图片、语音、视频、文件或图文混合内容回复到当前会话,也可以主动推送到指定 IM 目标。
新插件优先使用 Sender 的 replyImage、replyVoice、replyVideo、replyFile 和 replyMixed。旧版回复脚本中的全局 sendImage、sendVoice、sendVideo、sendFile、sendMixed 仍可用于维护存量插件,但新文档示例不再主推全局函数。
选择发送方式
回复当前会话
在消息触发的插件里使用 sender.replyImage(...) 等方法,目标自动来自当前消息。
主动推送
使用 pushImage(...)、pushVoice(...)、pushVideo(...)、pushFile(...) 或 pushMixed(...) 指定 imType、群和用户。
发送组合内容
使用 replyMixed(...) 一次发送文本、图片、语音、视频或文件组成的消息。
先保存文件
使用 fileDownload(...) 保存远程地址、base64 或 data URI,再把本地路径传给媒体发送方法。
快速示例
//[author: your-name]
//[runtime: [email protected]]
//[rule: 发图]
const { Sender, getSenderID } = require('./middleware.js')
const sender = new Sender(getSenderID())
const receipt = await sender.replyImage('https://example.com/demo.png')
if (receipt.ok === false) {
await sender.reply(`图片发送失败:${receipt.error || '未知错误'}`)
}
媒体来源
媒体方法的 source 参数支持以下形式:
| 来源 | 示例 | 适合场景 |
|---|
| 远程 URL | https://example.com/a.png | 文件已经托管在公网或适配器可访问的位置。 |
| 本地绝对路径 | /opt/autclaw/plugin/tmp/a.png | 插件已经生成文件。 |
| 本地相对路径 | ./tmp/a.png | 文件在插件运行目录附近。 |
| base64 | base64://... | 直接发送生成的二进制内容。 |
| data URI | data:image/png;base64,... | 带 MIME 类型的 base64 内容。 |
本地路径最适合插件自己生成的文件,例如截图、报表、TTS 语音或下载后的临时文件。远程 URL 更适合已经公开可访问的素材。
回复媒体
先创建 Sender,再调用对应的回复方法。返回值通常是 SendReceipt。
const { Sender, getSenderID } = require('./middleware.js')
const sender = new Sender(getSenderID())
await sender.replyImage('https://example.com/a.png')
await sender.replyVoice('./voice.wav')
await sender.replyVideo('./demo.mp4')
await sender.replyFile('./report.csv', { filename: 'report.csv' })
方法作用
| 方法 | 作用 | 常用来源 |
|---|
replyImage(source, options?) | 发送图片。 | png、jpg、gif、图片 URL、base64。 |
replyVoice(source, options?) | 发送语音。 | wav、mp3、ogg、opus、语音 URL。 |
replyVideo(source, options?) | 发送视频。 | mp4、mov、视频 URL。 |
replyFile(source, options?) | 发送文件。 | csv、txt、pdf、zip 或其他文件。 |
replyMixed(items, options?) | 发送混合消息。 | 文本 + 图片/语音/视频/文件。 |
options
媒体回复方法的第二个参数是可选对象。当前普通插件发送帮助函数实际使用这些字段:
| 字段 | 类型 | 说明 |
|---|
filename / fileName / file_name | string | 指定发送时展示或保存的文件名。 |
mimeType / mime_type | string | 指定 MIME 类型,例如 image/png、video/mp4。 |
需要指定目标时,请使用 pushImage(...)、pushVoice(...)、pushVideo(...)、pushFile(...) 或 pushMixed(...)。普通回复默认发送到当前会话。
发送混合消息
replyMixed(items, options?) 可以把文本和媒体组成一个消息序列。媒体项可使用 source,也可使用 file、url 或 path 表示来源。
await sender.replyMixed([
{ type: 'text', text: '处理完成:' },
{ type: 'image', source: './result.png', name: 'result.png' },
{ type: 'file', source: './report.csv', name: 'report.csv', mime_type: 'text/csv' },
])
支持的 items:
| item | 必填字段 | 说明 |
|---|
{ type: 'text', text: '...' } | text | 发送普通文本片段。 |
{ type: 'markdown', text: '...' } | text | 发送 Markdown 文本片段,取决于适配器支持。 |
{ type: 'image', source: '...' } | source | 发送图片。 |
{ type: 'voice', source: '...' } | source | 发送语音。 |
{ type: 'video', source: '...' } | source | 发送视频。 |
{ type: 'file', source: '...' } | source | 发送文件。 |
媒体项可额外传 name、file_name、filename、mime_type 或 mimeType。
主动推送媒体
主动推送不依赖当前消息。你需要指定目标:
imType:IM 类型,例如 qq、wx,以实际启用的适配器为准。
groupCode:群号/群 ID。私聊时通常传空字符串。
userID:用户 ID。群推送时通常传空字符串。
title:推送标题或备注,部分适配器会忽略。
const { pushImage, pushVideo, pushMixed } = require('./middleware.js')
await pushImage('qq', '123456', '', '日报', './daily.png', { account_id: 'bot_qq_ops' })
await pushVideo('qq', '123456', '', '演示视频', './demo.mp4', { account_id: 'bot_qq_ops' })
await pushMixed('qq', '123456', '', '处理结果', [
{ type: 'text', text: '结果如下:' },
{ type: 'image', source: './result.png' },
], { account_id: 'bot_qq_ops' })
| 方法 | 参数 | 返回 |
|---|
pushImage | (imType, groupCode, userID, title, imageUrl, options?, timeout?) | 发送数量,通常是 0 或 1 |
pushVoice | (imType, groupCode, userID, title, voiceUrl, options?, timeout?) | 发送数量 |
pushVideo | (imType, groupCode, userID, title, videoUrl, options?, timeout?) | 发送数量 |
pushFile | (imType, groupCode, userID, title, fileUrl, options?, timeout?) | 发送数量 |
pushMixed | (imType, groupCode, userID, title, items, options?, timeout?) | 发送数量 |
更多主动推送账号选择规则见 JavaScript 主动推送 或 Python 主动推送。
保存并发送文件
fileDownload(url, path?) 会把 http(s)、base64://... 或 data:*;base64,... 保存为本地文件。返回的 path / file_path 可以继续传给媒体发送方法。
const { Sender, getSenderID, fileDownload } = require('./middleware.js')
const sender = new Sender(getSenderID())
const file = await fileDownload('data:image/png;base64,...', 'images')
await sender.replyImage(file.path, { filename: file.file_name, mimeType: file.mime_type })
fileDownload 参数
| 参数 | 类型 | 必填 | 说明 |
|---|
url | string | 是 | 支持 http(s)、base64://... 和 data:*;base64,...。 |
path | string | 否 | 保存目录。不传时保存到运行目录下的 file;相对路径保存到 file/<path>;绝对路径按原路径保存。 |
FileDownloadResult
{
"path": "/opt/autclaw/file/images/demo.png",
"file_path": "/opt/autclaw/file/images/demo.png",
"file_name": "demo.png",
"mime_type": "image/png",
"file_size": 12345
}
fileDownload(...) 单个文件默认限制约 20 MB。下载失败、来源不可访问或文件过大时会抛出异常。
处理用户上传的文件
如果用户在消息里上传文件,先读取媒体项,再调用 downloadAdapterFile(...) 保存到本地。
const { Sender, getSenderID, downloadAdapterFile } = require('./middleware.js')
const sender = new Sender(getSenderID())
const items = await sender.getMediaItems()
const fileItem = items.find((item) => item.type === 'file')
if (!fileItem) {
await sender.reply('请发送一个文件')
} else {
const saved = await downloadAdapterFile(fileItem, { path: 'imports' })
await sender.reply(`已保存:${saved.file_name}`)
}
downloadAdapterFile(...) 返回字段与 fileDownload(...) 相同,并可能额外包含:
{
"ok": true,
"url": "https://adapter.example/file?id=...",
"action": "resolveFileURL"
}
SendReceipt
文本、媒体和撤回类方法通常返回发送回执。适配器可能添加额外字段。
{
"ok": true,
"message_id": "123456",
"messageid": "123456",
"message_ids": ["123456"],
"raw": {},
"action": "sendImage"
}
检查发送结果时,建议把 ok === false / ok is False 当作失败;不要只依赖某一个消息 ID 字段。
const receipt = await sender.replyVideo('./demo.mp4')
if (receipt.ok === false) {
await sender.reply(`视频发送失败:${receipt.error || '未知错误'}`)
} else {
console.log('message id:', receipt.message_id || receipt.messageid)
}
实用技巧
- 发送本地生成文件前,先确认文件已经写入完成,再调用
replyImage / replyVideo 等方法。
- 给文件和 mixed 媒体项设置
filename / name,方便用户识别下载内容。
- 大文件优先使用可访问的 URL;需要落盘处理时再用
fileDownload(...)。
- 用户上传文件不要手动解析平台原始字段;使用
sender.getMediaItems() + downloadAdapterFile(...)。
- 媒体发送失败时读取回执里的
error,并给用户一个可执行的下一步提示。
旧版回复脚本入口
维护 plugin/replies/*.js 这类旧版脚本时,可以继续使用全局函数:
sendImage('https://example.com/a.png')
sendVoice('./voice.wav')
sendVideo('./demo.mp4')
sendFile('./report.csv')
sendMixed([
{ type: 'text', text: '结果:' },
{ type: 'image', source: './result.png' },
])
新建 plugin/scripts/*.js 或 plugin/scripts/*.py 时,请优先使用 Sender 写法,便于阅读和类型提示。