diff --git a/config/default.toml b/config/default.toml index 3b913ff..9438f70 100644 --- a/config/default.toml +++ b/config/default.toml @@ -62,7 +62,9 @@ whitelist = ["username"] [tg_bot] base_url = "https://api.telegram.org" -chat_id = '-1' +chat_id = "-1" +# This is optional, if you don't need message thread just remove it +message_thread_id = "1" token = "token" [raid_leaderboard] diff --git a/config/example.toml b/config/example.toml index a5136f7..2c8f04e 100644 --- a/config/example.toml +++ b/config/example.toml @@ -73,6 +73,8 @@ whitelist = ["example-username"] [tg_bot] base_url = "https://api.telegram.org" chat_id = '-1' +# This is optional, if you don't need message thread just remove it +message_thread_id = '1' token = "token" [raid_leaderboard] diff --git a/config/test.toml b/config/test.toml index 0158711..ac1fb8d 100644 --- a/config/test.toml +++ b/config/test.toml @@ -63,6 +63,8 @@ whitelist = ["test-username"] [tg_bot] base_url = "https://api.telegram.org" chat_id = '-1' +# This is optional, if you don't need message thread just remove it +message_thread_id = '1' token = "token" [raid_leaderboard] diff --git a/src/config.rs b/src/config.rs index 035a9a9..57e0b03 100644 --- a/src/config.rs +++ b/src/config.rs @@ -82,6 +82,7 @@ pub struct TelegramBotConfig { pub base_url: String, pub token: String, pub chat_id: String, + pub message_thread_id: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -214,6 +215,7 @@ impl Default for Config { tg_bot: TelegramBotConfig { base_url: "https://api.telegram.org".to_string(), chat_id: "-0".to_string(), + message_thread_id: Some("-0".to_string()), token: "token".to_string(), }, raid_leaderboard: RaidLeaderboardConfig { diff --git a/src/main.rs b/src/main.rs index 52a3f87..2a7266c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -270,11 +270,7 @@ async fn main() -> AppResult<()> { config.x_oauth.clone(), Some(config.tweet_sync.api_key.clone()), )?); - let telegram_service = Arc::new(TelegramService::new( - &config.tg_bot.base_url, - &config.tg_bot.token, - &config.tg_bot.chat_id, - )); + let telegram_service = Arc::new(TelegramService::new(config.tg_bot.clone())); let server_db = db.clone(); let graphql_client = Arc::new(graphql_client.clone()); let server_addr_clone = server_address.clone(); diff --git a/src/services/telegram_service.rs b/src/services/telegram_service.rs index 628e6df..d494869 100644 --- a/src/services/telegram_service.rs +++ b/src/services/telegram_service.rs @@ -1,18 +1,21 @@ use reqwest::{Client, StatusCode}; use serde::Serialize; -use crate::{AppError, AppResult}; +use crate::{config::TelegramBotConfig, AppError, AppResult}; #[derive(Clone)] pub struct TelegramService { client: Client, base_url: String, default_chat_id: String, + default_message_thread_id: Option, } #[derive(Serialize)] struct MessagePayload<'a> { chat_id: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + message_thread_id: Option<&'a str>, text: &'a str, parse_mode: &'a str, disable_web_page_preview: bool, @@ -40,23 +43,26 @@ impl TelegramService { .replace("!", "\\!") } - pub fn new(base_url: &str, token: &str, default_chat_id: &str) -> Self { + pub fn new(config: TelegramBotConfig) -> Self { Self { client: Client::new(), - base_url: format!("{base_url}/bot{token}"), - default_chat_id: default_chat_id.to_string(), + base_url: format!("{}/bot{}", config.base_url, config.token), + default_chat_id: config.chat_id, + default_message_thread_id: config.message_thread_id, } } pub async fn send_message(&self, text: &str) -> AppResult<()> { - self.send(&self.default_chat_id, text).await + self.send(&self.default_chat_id, self.default_message_thread_id.as_deref(), text) + .await } - async fn send(&self, chat_id: &str, text: &str) -> AppResult<()> { + async fn send(&self, chat_id: &str, message_thread_id: Option<&str>, text: &str) -> AppResult<()> { let url = format!("{}/sendMessage", self.base_url); let payload = MessagePayload { chat_id, + message_thread_id, text, parse_mode: "MarkdownV2", // or "HTML" disable_web_page_preview: true, diff --git a/src/services/tweet_synchronizer_service.rs b/src/services/tweet_synchronizer_service.rs index e8f6e7f..0edbf95 100644 --- a/src/services/tweet_synchronizer_service.rs +++ b/src/services/tweet_synchronizer_service.rs @@ -112,14 +112,10 @@ impl TweetSynchronizerService { let link = build_x_status_url(author_name, &tweet.id); let tg_message = format!( - "Raid Target Found!\n\n*Link*: {}\n*Author*: {}\n*Text*: {}\n*Impressions*: {}\n*Posted At*: {}", - TelegramService::escape_markdown_v2(&link), - TelegramService::escape_markdown_v2(author_name), - TelegramService::escape_markdown_v2(&tweet.text), - tweet.impression_count, - tweet.created_at + "**Raid Target Found!**\n\n**Link**: {}\n**Author**: {}\n**Text**: {}\n**Impressions**: {}\n**Posted At**: {}", + &link, author_name, &tweet.text, tweet.impression_count, tweet.created_at ); - messages.push(tg_message); + messages.push(TelegramService::escape_markdown_v2(&tg_message)); } tokio::spawn(async move { @@ -222,7 +218,7 @@ impl TweetSynchronizerService { #[cfg(test)] mod tests { use super::*; - use crate::config::Config; + use crate::config::{Config, TelegramBotConfig}; use crate::models::raid_quest::CreateRaidQuest; use crate::utils::test_db::reset_database; use mockall::predicate::*; @@ -253,11 +249,13 @@ mod tests { // B. Setup Telegram Mock Server let mock_server = MockServer::start().await; - let telegram_service = Arc::new(TelegramService::new( - &mock_server.uri(), - "123456", - &config.tg_bot.chat_id, - )); + let telegram_config = TelegramBotConfig { + base_url: mock_server.uri(), + token: "123456".to_string(), + chat_id: config.tg_bot.chat_id.clone(), + message_thread_id: config.tg_bot.message_thread_id.clone(), + }; + let telegram_service = Arc::new(TelegramService::new(telegram_config)); // C. Config let app_config = Arc::new(config);