Skip to content

Message hooks

A plugin can intercept messages before sending and before showing. A hook is declared in contributes, and it needs the matching permission.

Permission: messages.transform_outgoing. Manifest:

"contributes": {
"outgoing": { "block": false, "media": false, "filter": { "chatTypes": ["user", "group"] } }
}
  • block — the hook may cancel sending.
  • media — also sees file sends (the text is the caption).
  • filter — limits by chats (chats) or chat types: user, bot, self, group, supergroup, forum, channel.

The event is message.outgoing. Inside the handler these are available (only in the synchronous freshgram.messages):

@freshgram.on("message.outgoing")
def outgoing(event):
if "secret" in event["text"]:
freshgram.messages.drop_outgoing("Not sending secrets")
return
freshgram.messages.set_outgoing(event["text"].upper(), silent=True)

set_outgoing accepts text, markdown, silent, schedule, reply_to, topic, entities. An unusable value is ignored. drop_outgoing(reason) does not send the message; a non-empty reason is shown as a toast.

Permission: messages.transform_incoming. In the manifest, contributes.incoming with onFailure (pass or block), mode (swap or hold), service and filter. See the full manifest reference.

The event is message.incoming:

@freshgram.on("message.incoming")
def incoming(event):
freshgram.messages.set_incoming(text="…", markdown=True)
# or
freshgram.messages.hide_incoming("spam")

Only the display changes: forwarding, editing and other plugins’ events see the real text.

markdown=True parses **bold**, __italic__, ~~strike~~, ||spoiler||, `code`, code blocks, [text](url) and quotes. markdown="html" parses <b>, <i>, <u>, <s>, <code>, <pre>, <a href>, <tg-spoiler>, <blockquote expandable>, <emoji id=N>, <br> (needs the format.html feature). Bad markup raises Invalid.