跳转到主要内容
使用媒体发送 API,你可以把图片、语音、视频、文件或图文混合内容回复到当前会话,也可以主动推送到指定 IM 目标。
新插件优先使用 SenderreplyImagereplyVoicereplyVideoreplyFilereplyMixed。旧版回复脚本中的全局 sendImagesendVoicesendVideosendFilesendMixed 仍可用于维护存量插件,但新文档示例不再主推全局函数。

选择发送方式

回复当前会话

在消息触发的插件里使用 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 参数支持以下形式:
来源示例适合场景
远程 URLhttps://example.com/a.png文件已经托管在公网或适配器可访问的位置。
本地绝对路径/opt/autclaw/plugin/tmp/a.png插件已经生成文件。
本地相对路径./tmp/a.png文件在插件运行目录附近。
base64base64://...直接发送生成的二进制内容。
data URIdata: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?)发送图片。pngjpggif、图片 URL、base64。
replyVoice(source, options?)发送语音。wavmp3oggopus、语音 URL。
replyVideo(source, options?)发送视频。mp4mov、视频 URL。
replyFile(source, options?)发送文件。csvtxtpdfzip 或其他文件。
replyMixed(items, options?)发送混合消息。文本 + 图片/语音/视频/文件。

options

媒体回复方法的第二个参数是可选对象。当前普通插件发送帮助函数实际使用这些字段:
字段类型说明
filename / fileName / file_namestring指定发送时展示或保存的文件名。
mimeType / mime_typestring指定 MIME 类型,例如 image/pngvideo/mp4
需要指定目标时,请使用 pushImage(...)pushVoice(...)pushVideo(...)pushFile(...)pushMixed(...)。普通回复默认发送到当前会话。

发送混合消息

replyMixed(items, options?) 可以把文本和媒体组成一个消息序列。媒体项可使用 source,也可使用 fileurlpath 表示来源。
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发送文件。
媒体项可额外传 namefile_namefilenamemime_typemimeType

主动推送媒体

主动推送不依赖当前消息。你需要指定目标:
  • imType:IM 类型,例如 qqwx,以实际启用的适配器为准。
  • 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?)发送数量,通常是 01
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 参数

参数类型必填说明
urlstring支持 http(s)base64://...data:*;base64,...
pathstring保存目录。不传时保存到运行目录下的 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/*.jsplugin/scripts/*.py 时,请优先使用 Sender 写法,便于阅读和类型提示。
Last modified on June 3, 2026