bloop_server_framework/health_monitor/telegram.rs
1use crate::health_monitor::{HealthReport, HealthReportSender};
2use teloxide::types::{ChatId, MessageId};
3use teloxide::{Bot, RequestError, prelude::*};
4use tracing::error;
5
6/// A [`HealthReportSender`] implementation that sends health reports via Telegram.
7///
8/// This sender uses the [`teloxide`] library to send a message containing the
9/// health report to a specific chat. It also attempts to delete the previously sent
10/// message to avoid cluttering the chat.
11///
12/// Note: This implementation assumes only one message is being managed at a time.
13/// Deleting the previous message is done by subtracting 1 from the current message
14/// ID, which is a simple but not fully robust approach.
15///
16/// # Examples
17///
18/// ```
19/// use teloxide::types::ChatId;
20/// use bloop_server_framework::health_monitor::{
21/// telegram::TelegramReportHealthSender
22/// };
23///
24/// let sender = TelegramReportHealthSender::new(
25/// "your-bot-token",
26/// ChatId(123456)
27/// );
28/// ```
29#[derive(Debug)]
30pub struct TelegramReportHealthSender {
31 bot: Bot,
32 chat_id: ChatId,
33}
34
35impl TelegramReportHealthSender {
36 /// Creates a new [`TelegramReportHealthSender`].
37 pub fn new(token: impl Into<String>, chat_id: ChatId) -> Self {
38 Self {
39 bot: Bot::new(token),
40 chat_id,
41 }
42 }
43}
44
45impl HealthReportSender for TelegramReportHealthSender {
46 type Error = RequestError;
47
48 async fn send(&mut self, report: &HealthReport, silent: bool) -> Result<(), Self::Error> {
49 let mut send_message = self.bot.send_message(self.chat_id, report.as_text_report());
50
51 if silent {
52 send_message = send_message.disable_notification(true);
53 }
54
55 let message = send_message.send().await?;
56
57 if let Err(err) = self
58 .bot
59 .delete_message(self.chat_id, MessageId(message.id.0 - 1))
60 .await
61 {
62 error!("Error deleting previous telegram message: {:?}", err);
63 };
64
65 Ok(())
66 }
67}