Use media sending APIs to reply to the current conversation with images, voice, video, files, or mixed content. You can also push media proactively to a specific IM target.
New plugins should prefer Sender methods: replyImage, replyVoice, replyVideo, replyFile, and replyMixed. Legacy global functions such as sendImage, sendVoice, sendVideo, sendFile, and sendMixed still work for maintaining old reply scripts, but new examples use Sender.
Choose a sending method
Reply to the current chat Use sender.replyImage(...) and related methods in a message-triggered plugin. The target comes from the current message.
Push proactively Use pushImage(...), pushVoice(...), pushVideo(...), pushFile(...), or pushMixed(...) with imType, group, and user IDs.
Send combined content Use replyMixed(...) to send text, images, voice, video, or files in one message sequence.
Save files first Use fileDownload(...) to save a remote URL, base64 payload, or data URI, then pass the local path to a media method.
Quick example
//[author: your-name]
//[runtime: [email protected] ]
//[rule: image]
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 ( `Image send failed: ${ receipt . error || 'unknown error' } ` )
}
The source parameter of media methods supports these forms:
Source Example Best for Remote URL https://example.com/a.pngFiles already hosted publicly or reachable by the adapter. Local absolute path /opt/autclaw/plugin/tmp/a.pngFiles generated by the plugin. Local relative path ./tmp/a.pngFiles near the plugin runtime directory. base64 base64://...Sending generated binary content directly. data URI data:image/png;base64,...Base64 content with a MIME type.
Local paths are best for files generated by plugins, such as screenshots, reports, TTS audio, or downloaded temporary files. Remote URLs work well when the asset is already publicly reachable.
Create Sender first, then call the reply method. The return value is usually 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' })
Method purpose
Method Purpose Common sources replyImage(source, options?)Send an image. png, jpg, gif, image URL, base64.replyVoice(source, options?)Send voice/audio. wav, mp3, ogg, opus, audio URL.replyVideo(source, options?)Send video. mp4, mov, video URL.replyFile(source, options?)Send a file. csv, txt, pdf, zip, or other files.replyMixed(items, options?)Send a mixed message. Text + image/voice/video/file.
options
The second parameter of media reply methods is an optional object. Current regular plugin helpers use these fields:
Field Type Description filename / fileName / file_namestringDisplayed or saved filename. mimeType / mime_typestringMIME type, such as image/png or video/mp4.
To specify a target, use pushImage(...), pushVoice(...), pushVideo(...), pushFile(...), or pushMixed(...). Regular replies send to the current conversation by default.
Send mixed messages
replyMixed(items, options?) combines text and media into one message sequence. Media items can use source, file, url, or path for the source.
await sender . replyMixed ([
{ type: 'text' , text: 'Done: ' },
{ type: 'image' , source: './result.png' , name: 'result.png' },
{ type: 'file' , source: './report.csv' , name: 'report.csv' , mime_type: 'text/csv' },
])
Supported items:
item Required field Description { type: 'text', text: '...' }textSend a plain text segment. { type: 'markdown', text: '...' }textSend a Markdown segment, depending on adapter support. { type: 'image', source: '...' }sourceSend an image. { type: 'voice', source: '...' }sourceSend voice/audio. { type: 'video', source: '...' }sourceSend video. { type: 'file', source: '...' }sourceSend a file.
Media items can also include name, file_name, filename, mime_type, or mimeType.
Proactive push does not depend on the current message. Specify the target:
imType: IM type, such as qq or wx. Use the adapters enabled in your deployment.
groupCode: Group number or group ID. Usually an empty string for private chats.
userID: User ID. Usually an empty string for group pushes.
title: Push title or note. Some adapters ignore it.
const { pushImage , pushVideo , pushMixed } = require ( './middleware.js' )
await pushImage ( 'qq' , '123456' , '' , 'Daily report' , './daily.png' , { account_id: 'bot_qq_ops' })
await pushVideo ( 'qq' , '123456' , '' , 'Demo video' , './demo.mp4' , { account_id: 'bot_qq_ops' })
await pushMixed ( 'qq' , '123456' , '' , 'Result' , [
{ type: 'text' , text: 'Result:' },
{ type: 'image' , source: './result.png' },
], { account_id: 'bot_qq_ops' })
Method Parameters Returns pushImage(imType, groupCode, userID, title, imageUrl, options?, timeout?)Send count, usually 0 or 1 pushVoice(imType, groupCode, userID, title, voiceUrl, options?, timeout?)Send count pushVideo(imType, groupCode, userID, title, videoUrl, options?, timeout?)Send count pushFile(imType, groupCode, userID, title, fileUrl, options?, timeout?)Send count pushMixed(imType, groupCode, userID, title, items, options?, timeout?)Send count
For proactive push account selection rules, see JavaScript proactive push or Python proactive push .
Save and send files
fileDownload(url, path?) saves http(s), base64://..., or data:*;base64,... sources as local files. Pass the returned path / file_path to media sending methods.
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 parameters
Parameter Type Required Description urlstringYes Supports http(s), base64://..., and data:*;base64,.... pathstringNo Save directory. If omitted, saves under runtime file; relative paths save under file/<path>; absolute paths are used as-is.
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
}
A single fileDownload(...) file is limited to about 20 MB by default. Download failures, unreachable sources, or oversized files throw exceptions.
Handle user-uploaded files
If a user uploads a file in a message, read media items first, then call downloadAdapterFile(...) to save it locally.
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 ( 'Please send a file' )
} else {
const saved = await downloadAdapterFile ( fileItem , { path: 'imports' })
await sender . reply ( `Saved: ${ saved . file_name } ` )
}
downloadAdapterFile(...) returns the same fields as fileDownload(...) and may include extra fields:
{
"ok" : true ,
"url" : "https://adapter.example/file?id=..." ,
"action" : "resolveFileURL"
}
SendReceipt
Text, media, and recall methods usually return a send receipt. Adapters may add extra fields.
{
"ok" : true ,
"message_id" : "123456" ,
"messageid" : "123456" ,
"message_ids" : [ "123456" ],
"raw" : {},
"action" : "sendImage"
}
When checking results, treat ok === false / ok is False as failure. Do not rely on only one message ID field.
const receipt = await sender . replyVideo ( './demo.mp4' )
if ( receipt . ok === false ) {
await sender . reply ( `Video send failed: ${ receipt . error || 'unknown error' } ` )
} else {
console . log ( 'message id:' , receipt . message_id || receipt . messageid )
}
Practical tips
Before sending a locally generated file, make sure it has been fully written.
Set filename / name for files and mixed media items so users can recognize downloads.
Prefer reachable URLs for large files. Save to disk with fileDownload(...) only when you need local processing.
Do not manually parse user-uploaded platform raw fields. Use sender.getMediaItems() + downloadAdapterFile(...).
When media sending fails, read error from the receipt and give users a concrete next step.
Legacy reply script entry points
When maintaining legacy plugin/replies/*.js scripts, you can still use global functions:
sendImage ( 'https://example.com/a.png' )
sendVoice ( './voice.wav' )
sendVideo ( './demo.mp4' )
sendFile ( './report.csv' )
sendMixed ([
{ type: 'text' , text: 'Result: ' },
{ type: 'image' , source: './result.png' },
])
For new plugin/scripts/*.js or plugin/scripts/*.py files, prefer the Sender style for readability and type hints.