| use anyhow::Result; |
| use serde::de::DeserializeOwned; |
| use serde_json::Value; |
| use teloxide::types::{ChatAction, ChatId, ChatMember, Message, Update}; |
| use reqwest::Client; |
|
|
| #[derive(Clone)] |
| pub struct WorkerBot { |
| client: Client, |
| worker_url: String, |
| token: String, |
| } |
|
|
| impl WorkerBot { |
| pub fn new(worker_url: &str, token: &str) -> Self { |
| let client = Client::builder() |
| .timeout(std::time::Duration::from_secs(30)) |
| .build() |
| .expect("build client"); |
| Self { client, worker_url: worker_url.trim_end_matches('/').to_string(), token: token.to_string() } |
| } |
|
|
| fn api_url(&self, method: &str) -> String { |
| format!("{}/bot{}/{}", self.worker_url, self.token, method) |
| } |
|
|
| async fn post_json<T: DeserializeOwned>(&self, method: &str, body: &Value) -> Result<T> { |
| let resp = self.client.post(&self.api_url(method)).json(body).send().await?; |
| let result: Value = resp.json().await?; |
| if let Some(ok) = result.get("ok").and_then(|v| v.as_bool()) { |
| if ok { |
| return Ok(serde_json::from_value(result.get("result").cloned().unwrap_or_default())?); |
| } |
| } |
| Err(anyhow::anyhow!("Telegram API error: {:?}", result)) |
| } |
|
|
| pub async fn set_my_commands(&self, commands: Vec<teloxide::types::BotCommand>) -> Result<()> { |
| self.post_json::<Value>("setMyCommands", &serde_json::json!({"commands": commands})).await?; |
| Ok(()) |
| } |
|
|
| pub async fn send_message(&self, chat_id: ChatId, text: String) -> Result<Message> { |
| self.post_json("sendMessage", &serde_json::json!({"chat_id": chat_id.0, "text": text})).await |
| } |
|
|
| pub async fn send_message_with_reply(&self, chat_id: ChatId, text: String, reply: serde_json::Value) -> Result<Message> { |
| let mut body = serde_json::json!({"chat_id": chat_id.0, "text": text, "reply_markup": reply}); |
| self.post_json("sendMessage", &body).await |
| } |
|
|
| pub async fn edit_message_text(&self, chat_id: ChatId, msg_id: i32, text: String) -> Result<Message> { |
| self.post_json("editMessageText", &serde_json::json!({"chat_id": chat_id.0, "message_id": msg_id, "text": text})).await |
| } |
|
|
| pub async fn edit_message_with_reply(&self, chat_id: ChatId, msg_id: i32, text: String, reply: serde_json::Value) -> Result<Message> { |
| self.post_json("editMessageText", &serde_json::json!({"chat_id": chat_id.0, "message_id": msg_id, "text": text, "reply_markup": reply})).await |
| } |
|
|
| pub async fn send_chat_action(&self, chat_id: ChatId, action: ChatAction) -> Result<()> { |
| let action_str = format!("{:?}", action).to_lowercase(); |
| self.post_json::<Value>("sendChatAction", &serde_json::json!({"chat_id": chat_id.0, "action": action_str})).await?; |
| Ok(()) |
| } |
|
|
| pub async fn answer_callback_query(&self, query_id: String, text: &str) -> Result<()> { |
| self.post_json::<Value>("answerCallbackQuery", &serde_json::json!({"callback_query_id": query_id, "text": text})).await?; |
| Ok(()) |
| } |
|
|
| pub async fn get_chat_member(&self, chat_id: &str, user_id: u64) -> Result<ChatMember> { |
| self.post_json("getChatMember", &serde_json::json!({"chat_id": chat_id, "user_id": user_id})).await |
| } |
|
|
| pub async fn get_updates(&self, offset: i64, timeout: u32) -> Result<Vec<Update>> { |
| let url = format!("{}?offset={}&timeout={}", self.api_url("getUpdates"), offset, timeout); |
| let resp = self.client.get(&url).send().await?; |
| let result: Value = resp.json().await?; |
| if let Some(ok) = result.get("ok").and_then(|v| v.as_bool()) { |
| if ok { |
| return Ok(serde_json::from_value(result.get("result").cloned().unwrap_or_default())?); |
| } |
| } |
| Err(anyhow::anyhow!("getUpdates error: {:?}", result)) |
| } |
| } |
|
|