1use reqwest::{Client, Error as ReqwestError};
2use serde::{Deserialize, Serialize};
3use std::time::Duration;
4
5const BASE_URL: &str = "https://api.telegram.org/bot";
6
7#[derive(Debug)]
8pub enum TelegramError {
9 RequestError(ReqwestError),
10 ApiError(String),
11}
12
13impl From<ReqwestError> for TelegramError {
14 fn from(error: ReqwestError) -> Self {
15 TelegramError::RequestError(error)
16 }
17}
18
19#[derive(Debug, Deserialize)]
20pub struct Update {
21 pub update_id: i64,
22 pub message: Option<Message>,
23}
24
25#[derive(Debug, Deserialize)]
26pub struct Message {
27 pub message_id: i64,
28 pub from: Option<User>,
29 pub chat: Chat,
30 pub text: Option<String>,
31}
32
33#[derive(Debug, Deserialize)]
34pub struct User {
35 pub id: i64,
36 pub first_name: String,
37 pub last_name: Option<String>,
38 pub username: Option<String>,
39}
40
41#[derive(Debug, Deserialize)]
42pub struct Chat {
43 pub id: i64,
44 pub chat_type: String,
45 pub title: Option<String>,
46 pub username: Option<String>,
47}
48
49#[derive(Debug, Serialize)]
50pub struct SendMessageRequest {
51 pub chat_id: i64,
52 pub text: String,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub reply_to_message_id: Option<i64>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub parse_mode: Option<String>,
57}
58
59pub struct Bot {
60 token: String,
61 client: Client,
62}
63
64impl Bot {
65 pub fn new(token: String) -> Result<Self, TelegramError> {
66 let client = Client::builder().timeout(Duration::from_secs(30)).build()?;
67
68 Ok(Bot { token, client })
69 }
70
71 fn api_url(&self, method: &str) -> String {
72 format!("{}{}/{}", BASE_URL, self.token, method)
73 }
74
75 pub async fn get_updates(&self, offset: Option<i64>) -> Result<Vec<Update>, TelegramError> {
76 let mut url = self.api_url("getUpdates");
77 if let Some(offset) = offset {
78 url = format!("{}?offset={}", url, offset);
79 }
80
81 let response = self
82 .client
83 .get(&url)
84 .send()
85 .await?
86 .json::<serde_json::Value>()
87 .await?;
88
89 if let Some(ok) = response.get("ok").and_then(|v| v.as_bool()) {
90 if !ok {
91 return Err(TelegramError::ApiError(
92 response
93 .get("description")
94 .and_then(|v| v.as_str())
95 .unwrap_or("Unknown API error")
96 .to_string(),
97 ));
98 }
99 }
100
101 let updates = response
102 .get("result")
103 .and_then(|v| serde_json::from_value::<Vec<Update>>(v.clone()).ok())
104 .unwrap_or_default();
105
106 Ok(updates)
107 }
108
109 pub async fn send_message(
110 &self,
111 request: SendMessageRequest,
112 ) -> Result<Message, TelegramError> {
113 let url = self.api_url("sendMessage");
114
115 let response = self
116 .client
117 .post(&url)
118 .json(&request)
119 .send()
120 .await?
121 .json::<serde_json::Value>()
122 .await?;
123
124 if let Some(ok) = response.get("ok").and_then(|v| v.as_bool()) {
125 if !ok {
126 return Err(TelegramError::ApiError(
127 response
128 .get("description")
129 .and_then(|v| v.as_str())
130 .unwrap_or("Unknown API error")
131 .to_string(),
132 ));
133 }
134 }
135
136 let message = response
137 .get("result")
138 .and_then(|v| serde_json::from_value::<Message>(v.clone()).ok())
139 .ok_or_else(|| {
140 TelegramError::ApiError("Failed to parse message response".to_string())
141 })?;
142
143 Ok(message)
144 }
145}