Skip to main content
Sender binds to the current runtime context. For message triggers, it represents the current IM, account, chat, and user. For route triggers, it represents the current HTTP request. Cron / fake contexts may not point to a real IM chat.
from middleware import Sender, getSenderID

sender = Sender(getSenderID())

Read message context

These methods take no arguments and return fields from the current runtime context. Missing fields usually return an empty string, empty array, or False.
MethodPurposeParametersReturns
getImtype()Get the current IM type. Cron runs may return fake.Nonestr
getUserID()Get the current user ID.Nonestr
getUserName()Get the current user display name.Nonestr
getUserAvatarUrl()Get the current user avatar URL.Nonestr
getChatID()Get the current chat ID; group chats use group ID, private chats are often empty.Nonestr
getChatName()Get the current chat name.Nonestr
getGroupName()Get the group name. Same as getChatName().Nonestr
isAdmin()Check whether the current user is an administrator.Nonebool
isAI()Check whether the message came from an AI trigger context.Nonebool
getAIParam()Get the AI parameter.Nonestr
getMessage()Get the current message text.Nonestr
getMessageID()Get the current message ID.Nonestr
getHistoryMessageIDs(number)Get recent message IDs.number: required count.list[str]
param(index)Read a rule regex capture.index starts at 1; out-of-range returns an empty string.str
user = sender.getUserName()
message = sender.getMessage()
first_match = sender.param(1)
sender.reply(f"{user} sent: {message}\nParam: {first_match}")

Reply with text and media

reply* methods reply to the current runtime context. For message triggers, they reply to the current chat. For route triggers, reply(...) / replyMarkdown(...) can write the route response. A cron fake context does not send a real IM reply.
MethodPurposeParametersReturns
reply(text)Reply with plain text.text: required.SendReceipt
replyMarkdown(markdown)Reply with Markdown text. Rendering depends on the adapter.markdown: required.SendReceipt
replyImage(source, options=None)Reply with an image.Image URL, path, base64, or data URI; options optional.SendReceipt
replyVoice(source, options=None)Reply with voice/audio.Voice URL or path; options optional.SendReceipt
replyVideo(source, options=None)Reply with a video.Video URL or path; options optional.SendReceipt
replyFile(source, options=None)Reply with a file.File URL or path; options optional.SendReceipt
replyMixed(items, options=None)Reply with structured mixed messages.items: required mixed items.SendReceipt
returnValue(text)Set the runtime return value without sending an IM message.text: required.Runtime result
sender.reply("Plain text")
sender.replyMarkdown("## Result\n\n- Done")
sender.replyImage("https://example.com/a.png")
sender.replyVoice("./voice.wav")
sender.replyVideo("./demo.mp4")
sender.replyFile("./report.csv", {"filename": "report.csv", "mimeType": "text/csv"})
sender.replyMixed([
    {"type": "text", "text": "Result: "},
    {"type": "image", "source": "./result.png", "name": "result.png"},
])
replyImage(...) and other current-chat reply methods do not need imType, group ID, or user ID. Use push(...) or push* when you need to choose the target.

MediaOptions

Media reply methods accept an optional dictionary as the second parameter.
options.filename
string
Display filename. Also accepted as fileName or file_name.
options.mimeType
string
MIME type. Also accepted as mime_type.
options.timeout
number
Media request timeout. Millisecond values are converted to request timeout.

Control flow

MethodPurposeParametersReturns
setContinue()Continue matching subsequent plugins.Nonebool
recallMessage(messageid)Recall a message.messageid: message ID.SendReceipt
breakIn(content)Re-enter the message pipeline with new text.content: required.Runtime result
if sender.isAdmin():
    sender.setContinue()
else:
    sender.reply("Only administrators can continue.")

Next steps

Last modified on June 3, 2026