Handling Updates
You can handle updates by assigning update handlers to the client. A handler is
a function that takes two arguments: ctx
and next
.
ctx
is the received update with context-aware methods and shortcuts. See all
types of updates here.
next
is a function that passes the update to the next handlers.
Once an update reaches a handler, it won’t reach others unless it calls
next
. When next
is called, the same thing goes on again: the update won’t
reach the next handler until next
is called, and so on.
There are four methods responsible for assigning handlers:
use
This is the main method to assign a handler, and all others depend on it. It assigns an unconditional handler, meaning that it will always get called unless it is blocked by a handler preceding it.
|
use———————handler
|
|
|
next
/
/
/
/
/
/
/
/
/
/
|
The following are some usage examples.
/** Logging */
client.use(async (ctx, next) => {
console.log("I always get logged before an update is handled.");
console.log("Update", ctx.toJSON(), "received at", Date.now());
await next(); // move to the next handlers
});
/** Error handling */
client.use(async (_ctx, next) => {
try {
await next(); // call the next handlers
} catch (err) {
console.error("Failed to handle an update:");
console.trace(err);
}
});
/** Ignoring updates */
client.use(async (ctx, next) => {
const message = ctx.effectiveMessage;
const date = message?.date;
const isTooOld = date !== undefined && Date.now() - date.getTime() > 5 * 60 * 1_000;
if (message !== undefined && isTooOld) {
// message is older than 5 minutes, not interesting
console.log(
"Ignoring messsage", message.id,
"in", message.chat.id,
"because it is too old.",
);
} else {
await next(); // handle it if newer than 5 minutes
}
});
/** Performance monitoring */
client.use(async (_ctx, next) => {
const then = performance.now();
await next(); // call the next handlers
const elapsed = performance.now() - then;
console.log("Update handled in", ${Math.round(elapsed)}ms`);
});
branch
branch
takes 3 functions:
- One that checks for a specific condition.
- A handler function that gets called when the specific condition is met, the true handler.
- Another one that gets called when it is not met, the false handler.
|
branch————————
|
condition
|
————————————
| |
true false
| |
handler handler
| |
next next
/ /
/ /
/ /
/ /
/ /
/ /
/ /
| /
| /
| /
| /
| /
| /
| /
| /
| /
| /
| /
| /
|/
|
Here’s an example.
client.branch(
/** condition: update is from a special user */
(ctx) => ctx.effectiveUser?.username?.toLowerCase() == "onetimeusername",
/** true handler */
() => {
console.log("Using more compute power: Update from someone special.");
},
/** false handler */
() => {
console.log("Handling postponed: Update from regular user.");
},
);
filter
filter
is almost the same as branch
except that it does not have a false
handler. It automatically moves to the next handlers if the condition is not
met.
|
filter————————
|
condition
|
————————————
| |
true false
| /
handler /
| /
next /
/ /
/ /
/ /
/ /
/ /
/ /
/ /
| /
| /
| /
| /
| /
| /
| /
| /
|/
|
Here’s an example.
client.filter(
/** condition: update is from a forum chat */
(ctx) => {
return ctx.effectiveChat?.type == "supergroup" && ctx.effectiveChat.isForum;
},
(ctx) => {
console.log("Received an update from a forum.");
},
);
on
on
works like filter
but instead of providing a function that checks for a
condition, you provide it a filter query. If the update matched the provided
filter, the handler gets called.
|
on————————————
|
check
|
————————————
| |
passes does not
| /
handler /
| /
next /
/ /
/ /
/ /
/ /
/ /
/ /
/ /
| /
| /
| /
| /
| /
| /
| /
| /
|/
|
Here are some examples.
/** When the client's connection state changes */
client.on("connectionState", ({ connectionState }) => {
console.log("New connection state:", connectionState);
});
/** Handles text messages */
client.on("message:text", ({ message }) => {
// do something with message.text
});
/** Handles callback queries */
client.on("callbackQuery", ({ callbackQuery }) => {
// do something with callbackQuery
});