Working with Messages

Message Updates

There are three updates that are directly related to messages:

Here are some examples on adding listeners for each of them:

client.on("message", (ctx) => {
  // called when a message is received or sent
});

client.on("editedMessage", (ctx) => {
  // called when a message is edited
});

client.on("deletedMessages", (ctx) => {
  // called when one or more messages are deleted
});

To see how the context object would look like for each update, you can refer to their specific documentation pages linked above.

Filtering Message Types

There is a significant number of different types of messages, which makes processing all of them in a single handler a little harder.

Fortunately, you can easily filter out messages by their types when assigning your handler. Here are some examples:

client.on("message:text", (ctx) => {
  // This handler is called only when text messages are received.
  // So ctx.msg.text is always set.
});

client.on("editedMessage:photo", (ctx) => {
  // This handler is called only when photo messages are edited.
  // So ctx.msg.photo is always set.
});

Accessing the Message in Handlers

You can access the received message in through ctx.msg or ctx.message.

client.on("message", (ctx) => {
  // Both ctx.msg and ctx.message are referring to the received message.
});

Edited messages are accessed through ctx.msg and ctx.editedMessage.

client.on("editedMessage", (ctx) => {
  // Both ctx.msg and ctx.editedMessage are referring to the edited message.
});

ctx.msg is just a shortcut that resolves to ctx.message ?? ctx.editedMessage. See Message.

Updates for deleted messages don’t include full message objects, only references to them (see MessageReference).

client.on("deletedMessages", (ctx) => {
  // ctx.deletedMessages is an array of MessageReference.
});

Notes

  • UpdateDeletedMessages is not always sent to bots, so it is recommended that you don’t depend on it for bots.
  • Updates for outgoing messages are not sent for bots by default, but you can disable the ignoreOutgoing option to receive them:
const client = new Client({
  ignoreOutgoing: false,
  /* ... */
});

Sending Messages

There are multiple methods that can be used to send messages. Each of them is used for sending a specific type of message.

Here are some example calls:

const chat = /* ... */; // ID
const file = /* ... */; // FileSource

await client.sendMessage(
  chat,
  "Hey!",
  { disableNotification: true, /* other optional options */ }
);

await client.sendPhoto(chat, file, { caption: "Optional Caption", /* other optional options */ });

await client.sendDocument(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendVideo(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendAnimation(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendAnimation(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendAudio(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendVoice(chat, file, { caption: "Optional Caption", /* ooo */ });

await client.sendDice(chat); // defaults to 🎲
await client.sendDice(chat, { emoji: "🏀" }); // but you can send any valid dice

To use the above example calls, chat must be replaced with a valid ID, and file must be replaced a valid FileSource.

As previously said, the last parameters are optional and can always be omitted, so for example you can do just await client.sendMessage(chat, "Hey!"); if you don’t specify any optional parameter. Optional parameters are those parameters marked with ? in the method documentations.

Inside handlers, you can call the respective reply* shortcuts to easily reply the context message:

client.on("message", async (ctx) => {
  await ctx.reply(text); // same as client.sendMessage(ctx.chat.id, text, { replyToMessageId: ctx.msg.id });
  await ctx.replyPhoto(file); // same as client.sendPhoto(ctx.chat.id, file, { replyToMessageId: ctx.msg.id });
});

Deleting Messages

You can delete messages by calling either deleteMessage or deleteMessages.

await ctx.deleteMessage(chat, messageId);
await ctx.deleteMessages(chat, [...messageIds]);

You can delete the context message with delete:

client.on("message", async (ctx) => {
  await ctx.delete(); // This deletes the received message.
});

Forwarding Messages

You can forward messages by calling either forwardMessage or forwardMessages.

await ctx.forwardMessage(fromChat, toChat);
await ctx.forwardMessages(fromChat, toChat);

You can forward the context message with forward:

client.on("message", async (ctx) => {
  await ctx.forward(toChat); // This forwards the received message.
});