Relays: users talking through the bot
A relay connects two users: what one sends the bot in their private chat is copied to the other, so neither sees the other's account. Anonymous chats, support desks, a buyer and a seller, a match in a dating bot.
await app.relay.start(ctx, ctx.from!.id, sellerId); // both are connected now
await app.relay.peer(ctx, ctx.from!.id); // { peer, since, data } or undefined
await app.relay.end(ctx, ctx.from!.id); // ends it for both; returns the link- Messages are copied with
copyMessage: text, photos, voice notes, files, locations… arrive from the bot. - A reply to a relayed message is a reply to its counterpart on the other side, and editing a message edits its copy (text and captions). Message pairs are kept for 7 days in the session storage.
- Service messages (Mini App data, payments, pins) aren't relayed: they go on to their handlers. Telegram doesn't tell bots when someone is typing, so "typing…" can't be passed on.
- /commands, menu buttons, active dialogues and buttons keep working as usual and aren't relayed, so a
/endcommand (and anything else) stays available. - Private chats only. The other user must have started the bot, like for any message the bot sends.
startends the users' earlier relays (arelayEndevent each). Options:ttlMsends the relay by itself (silently: schedule a task to announce it),datais anything JSON you want back frompeer.- The first argument is
ctxor the bot (bot, afterbot.init()). - Relays live in the session storage, so they survive restarts and work across processes with a shared storage.
Checking messages
new EasyTG({
relay: {
// false drops the message; a string drops it and tells the sender why.
filter: ({ ctx }) => (/https?:\/\//.test(ctx.message?.text ?? '') ? 'Links are not allowed here.' : true),
},
});Events
app.on('relayMessage', ({ from, to }) => stats.count(from, to));
app.on('relayEnd', async ({ users, reason, ctx }) => {
// reason 'unreachable': the other user blocked the bot. `ctx` is the sender's update: tell them.
if (reason === 'unreachable') await ctx?.reply('They left the chat.');
});relayEnd fires for app.relay.end and for relays that start replaced (reason: 'app'), and when a message can't be delivered because the other user blocked the bot (reason: 'unreachable', with the sender's ctx).
Try it
Switch between the two users at the top of the chat to play both sides.
examples/support.ts is a support desk: customers open tickets, an agent takes one and they talk through a relay, with a link filter and a rating at the end. examples/match.ts uses a relay for matches who want to chat, and hides both users' reply keyboards while they do (app.hideMenu, and app.withUser for the other side).