1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


use teloxide::{
    payloads::{self, EditMessageReplyMarkupSetters, SendMessageSetters},
    requests::{JsonRequest, Requester},
    types::{ChatId, InlineKeyboardMarkup, MessageId, Recipient, ReplyMarkup},
    Bot,
};

pub struct UpdateableMessage {
    pub chat_id: ChatId,
    pub message_id: MessageId,
    pub text: String,
    pub reply_markup: Option<InlineKeyboardMarkup>,
}

impl UpdateableMessage {
    pub async fn new(req: JsonRequest<payloads::SendMessage>) -> anyhow::Result<Self> {
        let Recipient::Id(chat_id) = req.chat_id else {
            return Err(anyhow::anyhow!("chat_id is not a ChatId"));
        };

        let reply_markup = match &req.reply_markup {
            None => None,
            Some(ReplyMarkup::InlineKeyboard(reply_markup)) => Some(reply_markup),
            _ => {
                return Err(anyhow::anyhow!(
                    "reply_markup is not an InlineKeyboardMarkup"
                ))
            }
        };

        Ok(Self {
            chat_id,
            text: req.text.to_owned(),
            reply_markup: reply_markup.cloned(),
            message_id: req.await?.id,
        })
    }

    pub async fn resend(&mut self, bot: &Bot) -> anyhow::Result<()> {
        let _ = bot.delete_message(self.chat_id, self.message_id);

        let mut crt = bot.send_message(self.chat_id, &self.text);

        if let Some(reply_markup) = self.reply_markup.to_owned() {
            crt = crt.reply_markup(reply_markup);
        }

        self.message_id = crt.await?.id;

        Ok(())
    }

    pub async fn update_text(&mut self, bot: &Bot, text: &str) -> anyhow::Result<()> {
        if self.text != text {
            self.text = text.to_owned();

            let res = bot
                .edit_message_text(self.chat_id, self.message_id, text)
                .await;

            if let Err(_) = res {
                self.resend(bot).await?;
            }
        }

        Ok(())
    }

    pub async fn update_markup(
        &mut self,
        bot: &Bot,
        reply_markup: Option<InlineKeyboardMarkup>,
    ) -> anyhow::Result<()> {
        if self.reply_markup != reply_markup {
            let mut req = bot.edit_message_reply_markup(self.chat_id, self.message_id);

            if let Some(reply_markup) = &reply_markup {
                req = req.reply_markup(reply_markup.clone());
            }

            let res = req.await;

            if let Err(_) = res {
                self.resend(bot).await?;
            }

            self.reply_markup = reply_markup;
        }

        Ok(())
    }

    pub async fn delete(self, bot: &Bot) -> anyhow::Result<()> {
        bot.delete_message(self.chat_id, self.message_id).await?;

        Ok(())
    }
}