chat_member_updates/
chat_member_updates.rs

1use teloxide::{prelude::*, types::ParseMode, utils::html};
2use teloxide_core::adaptors::DefaultParseMode;
3
4/// We use a type alias to be able to write just `bot: Bot` in handlers, instead
5/// of a lengthy `DefaultParseMode<Bot>`.
6///
7/// `DefaultParseMode` here is a [requester adaptor], that allows us to specify
8/// a default parse mode. The other option would be to use `.parse_mode(...)`
9/// after each API call manually (e.g.
10/// `bot.send_message(...).parse_mode(...).await?`).
11///
12/// [requester adaptor]: teloxide::requests::Requester#adaptors
13type Bot = DefaultParseMode<teloxide::Bot>;
14
15#[tokio::main]
16async fn main() -> ResponseResult<()> {
17    pretty_env_logger::init();
18
19    // We specify default parse mode to be `Html`, so that later we can use
20    // `html::user_mention`
21    let bot = teloxide::Bot::from_env().parse_mode(ParseMode::Html);
22
23    // Create a handler for our bot, that will process updates from Telegram
24    let handler = dptree::entry()
25        .inspect(|u: Update| {
26            eprintln!("{u:#?}"); // Print the update to the console with inspect
27        })
28        .branch(
29            Update::filter_chat_member()
30                .branch(
31                    dptree::filter(|m: ChatMemberUpdated| {
32                        m.old_chat_member.is_left() && m.new_chat_member.is_present()
33                    })
34                    .endpoint(new_chat_member),
35                )
36                .branch(
37                    dptree::filter(|m: ChatMemberUpdated| {
38                        m.old_chat_member.is_present() && m.new_chat_member.is_left()
39                    })
40                    .endpoint(left_chat_member),
41                ),
42        );
43
44    // Create a dispatcher for our bot
45    Dispatcher::builder(bot, handler).enable_ctrlc_handler().build().dispatch().await;
46
47    Ok(())
48}
49
50/// Welcome Endpoint
51async fn new_chat_member(bot: Bot, chat_member: ChatMemberUpdated) -> ResponseResult<()> {
52    let user = chat_member.old_chat_member.user.clone();
53
54    let telegram_group_name = chat_member.chat.title().unwrap_or("");
55
56    // We get a "@username" mention via `mention()` method if the user has a
57    // username, otherwise we create a textual mention with "Full Name" as the
58    // text linking to the user
59    let username =
60        user.mention().unwrap_or_else(|| html::user_mention(user.id, user.full_name().as_str()));
61
62    bot.send_message(chat_member.chat.id, format!("Welcome to {telegram_group_name} {username}!"))
63        .await?;
64
65    Ok(())
66}
67
68async fn left_chat_member(bot: Bot, chat_member: ChatMemberUpdated) -> ResponseResult<()> {
69    let user = chat_member.old_chat_member.user;
70
71    let username =
72        user.mention().unwrap_or_else(|| html::user_mention(user.id, user.full_name().as_str()));
73
74    bot.send_message(chat_member.chat.id, format!("Goodbye {username}!")).await?;
75
76    Ok(())
77}