1mod method;
2
3use std::collections::HashMap;
4
5use anyhow::{anyhow, Context, Result};
6use http_req::{request::Request, uri::Uri};
7use serde::{de::DeserializeOwned, Serialize};
8use serde_json::Value;
9
10use crate::{
11 Chat, ChatId, ChatInviteLink, ChatMember, ChatPermissions, File, InputFile, Me, Message,
12 MessageId, ParseMode, True, UserId, UserProfilePhotos,
13};
14
15pub use self::method::Method;
16
17const BASE_URL: &str = "https://api.telegram.org/bot";
18
19pub struct Telegram {
20 base_url: &'static str,
21 token: String,
22}
23
24impl Telegram {
25 pub fn new(token: String) -> Self {
26 Self {
27 base_url: BASE_URL,
28 token,
29 }
30 }
31
32 pub fn new_with_base_url(token: String, base_url: &'static str) -> Self {
33 Self { base_url, token }
34 }
35}
36
37impl Telegram {
38 pub fn request<T>(&self, method: Method, body: &[u8]) -> Result<T>
39 where
40 T: DeserializeOwned,
41 {
42 let url = format!("{}{}/{}", self.base_url, self.token, method.to_string());
43 let uri = Uri::try_from(url.as_str())?;
44
45 let mut writer = Vec::new();
46 Request::new(&uri)
47 .header("Content-Type", "application/json")
48 .header("Content-Length", &body.len())
49 .body(body)
50 .send(&mut writer)?;
51
52 let value = serde_json::from_str::<Value>(&String::from_utf8(writer)?)?;
53
54 let result = value
55 .get("result")
56 .ok_or(anyhow!("tg api returned without result"))?;
57 let t: T = serde_json::from_value(result.clone())?;
58
59 Ok(t)
60 }
61
62 pub fn request_with_attach<T, S>(
63 &self,
64 method: Method,
65 query: HashMap<S, S>,
66 body: &[u8],
67 ) -> Result<T>
68 where
69 T: DeserializeOwned,
70 S: Serialize,
71 {
72 let mut url = format!("{}{}/{}", self.base_url, self.token, method.to_string());
73 if !query.is_empty() {
74 let mut iter = query.iter();
75 let (k, v) = iter.next().unwrap();
76 let k = serde_json::to_string(k).context("query key serialize error")?;
77 let v = serde_json::to_string(v).context("query value serialize error")?;
78
79 url += &format!("?{k}={v}");
80
81 for (k, v) in iter {
82 let k = serde_json::to_string(k).context("query key serialize error")?;
83 let v = serde_json::to_string(v).context("query value serialize error")?;
84 url += &format!("&{k}={v}");
85 }
86 }
87
88 let uri = Uri::try_from(url.as_str())?;
89
90 let mut writer = Vec::new();
91 Request::new(&uri)
92 .header("Content-Type", "multipart/form-data")
93 .header("Content-Length", &body.len())
94 .body(body)
95 .send(&mut writer)?;
96
97 let value = serde_json::from_str::<Value>(&String::from_utf8(writer)?)?;
98
99 let result = value
100 .get("result")
101 .ok_or(anyhow!("tg api returned without result"))?;
102 let t: T = serde_json::from_value(result.clone())?;
103
104 Ok(t)
105 }
106}
107
108impl Telegram {
110 pub fn get_me(&self) -> Result<Me> {
111 self.request(Method::GetMe, &[])
112 }
113
114 pub fn log_out(&self) -> Result<True> {
115 self.request(Method::LogOut, &[])
116 }
117
118 pub fn close(&self) -> Result<True> {
119 self.request(Method::Close, &[])
120 }
121
122 pub fn send_message<T>(&self, chat_id: ChatId, text: T) -> Result<Message>
123 where
124 T: Into<String>,
125 {
126 let text: String = text.into();
127 let body = serde_json::json!({
128 "chat_id": chat_id,
129 "text": text,
130 });
131 self.request(Method::SendMessage, body.to_string().as_bytes())
132 }
133
134 pub fn send_message_with_parse_mode<T>(
135 &self,
136 chat_id: ChatId,
137 text: T,
138 parse_mode: ParseMode,
139 ) -> Result<Message>
140 where
141 T: Into<String>,
142 {
143 let text: String = text.into();
144 let body = serde_json::json!({
145 "chat_id": chat_id,
146 "text": text,
147 "parse_mode": parse_mode,
148 });
149 self.request(Method::SendMessage, body.to_string().as_bytes())
150 }
151
152 pub fn forward_message(&self, chat_id: ChatId, from_chat_id: ChatId) -> Result<Message> {
153 let body = serde_json::json!({
154 "chat_id": chat_id,
155 "from_chat_id": from_chat_id,
156 });
157 self.request(Method::ForwardMessage, body.to_string().as_bytes())
158 }
159
160 pub fn copy_message(
161 &self,
162 chat_id: ChatId,
163 from_chat_id: ChatId,
164 message_id: MessageId,
165 ) -> Result<Message> {
166 let body = serde_json::json!({
167 "chat_id": chat_id,
168 "from_chat_id": from_chat_id,
169 "message_id": message_id,
170 });
171 self.request(Method::CopyMessage, body.to_string().as_bytes())
172 }
173
174 pub fn send_photo(&self, chat_id: ChatId, photo: InputFile) -> Result<Message> {
176 if photo.needs_attach() {
177 panic!("unsupport attach currently")
178 } else {
179 let body = serde_json::json!({
180 "chat_id": chat_id,
181 "photo": photo,
182 });
183 self.request(Method::SendPhoto, body.to_string().as_bytes())
184 }
185 }
186
187 pub fn send_audio(&self, chat_id: ChatId, audio: InputFile) -> Result<Message> {
188 if audio.needs_attach() {
189 panic!("unsupport attach currently")
190 } else {
191 let body = serde_json::json!({
192 "chat_id": chat_id,
193 "audio": audio,
194 });
195 self.request(Method::SendAudio, body.to_string().as_bytes())
196 }
197 }
198
199 pub fn send_document(&self, chat_id: ChatId, document: InputFile) -> Result<Message> {
200 if document.needs_attach() {
201 panic!("unsupport attach currently")
202 } else {
203 let body = serde_json::json!({
204 "chat_id": chat_id,
205 "document": document,
206 });
207 self.request(Method::SendDocument, body.to_string().as_bytes())
208 }
209 }
210
211 pub fn send_video(&self, chat_id: ChatId, video: InputFile) -> Result<Message> {
212 if video.needs_attach() {
213 panic!("unsupport attach currently")
214 } else {
215 let body = serde_json::json!({
216 "chat_id": chat_id,
217 "video": video,
218 });
219 self.request(Method::SendVideo, body.to_string().as_bytes())
220 }
221 }
222
223 pub fn send_animation(&self, chat_id: ChatId, animation: InputFile) -> Result<Message> {
224 if animation.needs_attach() {
225 panic!("unsupport attach currently")
226 } else {
227 let body = serde_json::json!({
228 "chat_id": chat_id,
229 "animation": animation,
230 });
231 self.request(Method::SendAnimation, body.to_string().as_bytes())
232 }
233 }
234
235 pub fn send_voice(&self, chat_id: ChatId, voice: InputFile) -> Result<Message> {
236 if voice.needs_attach() {
237 panic!("unsupport attach currently")
238 } else {
239 let body = serde_json::json!({
240 "chat_id": chat_id,
241 "voice": voice,
242 });
243 self.request(Method::SendVoice, body.to_string().as_bytes())
244 }
245 }
246
247 pub fn send_video_note(&self, chat_id: ChatId, video_note: InputFile) -> Result<Message> {
248 if video_note.needs_attach() {
249 panic!("unsupport attach currently")
250 } else {
251 let body = serde_json::json!({
252 "chat_id": chat_id,
253 "video_note": video_note,
254 });
255 self.request(Method::SendVideoNote, body.to_string().as_bytes())
256 }
257 }
258
259 pub fn send_location(&self, chat_id: ChatId, latitude: f32, longitude: f32) -> Result<Message> {
262 let body = serde_json::json!({
263 "chat_id": chat_id,
264 "latitude": latitude,
265 "longitude": longitude,
266 });
267 self.request(Method::SendLocation, body.to_string().as_bytes())
268 }
269
270 pub fn send_venue(
271 &self,
272 chat_id: ChatId,
273 latitude: f32,
274 longitude: f32,
275 title: String,
276 address: String,
277 ) -> Result<Message> {
278 let body = serde_json::json!({
279 "chat_id": chat_id,
280 "latitude": latitude,
281 "longitude": longitude,
282 "title": title,
283 "address": address,
284 });
285 self.request(Method::SendLocation, body.to_string().as_bytes())
286 }
287
288 pub fn send_contract(
289 &self,
290 chat_id: ChatId,
291 photo_number: String,
292 first_name: String,
293 ) -> Result<Message> {
294 let body = serde_json::json!({
295 "chat_id": chat_id,
296 "photo_number":photo_number,
297 "first_name": first_name,
298 });
299 self.request(Method::SendContract, body.to_string().as_bytes())
300 }
301
302 pub fn send_poll(
303 &self,
304 chat_id: ChatId,
305 question: String,
306 options: Vec<String>,
307 ) -> Result<Message> {
308 let body = serde_json::json!({
309 "chat_id": chat_id,
310 "question": question,
311 "options": options,
312 });
313 self.request(Method::SendPoll, body.to_string().as_bytes())
314 }
315
316 pub fn send_dice(&self, chat_id: ChatId) -> Result<Message> {
317 let body = serde_json::json!({
318 "chat_id": chat_id,
319 });
320 self.request(Method::SendDice, body.to_string().as_bytes())
321 }
322
323 pub fn send_chat_action(&self, chat_id: ChatId, action: String) -> Result<Message> {
324 let body = serde_json::json!({
325 "chat_id": chat_id,
326 "action": action,
327 });
328 self.request(Method::SendChatAction, body.to_string().as_bytes())
329 }
330
331 pub fn get_user_profile_photos(&self, user_id: UserId) -> Result<UserProfilePhotos> {
332 let body = serde_json::json!({
333 "user_id": user_id,
334 });
335 self.request(Method::GetUserProfilePhotos, body.to_string().as_bytes())
336 }
337
338 pub fn get_file(&self, file_id: String) -> Result<File> {
339 let body = serde_json::json!({
340 "file_id": file_id,
341 });
342 self.request(Method::GetFile, body.to_string().as_bytes())
343 }
344
345 pub fn ban_chat_member(&self, chat_id: ChatId, user_id: UserId) -> Result<True> {
346 let body = serde_json::json!({
347 "chat_id": chat_id,
348 "user_id": user_id,
349 });
350 self.request(Method::BanChatMember, body.to_string().as_bytes())
351 }
352
353 pub fn unban_chat_member(&self, chat_id: ChatId, user_id: UserId) -> Result<True> {
354 let body = serde_json::json!({
355 "chat_id": chat_id,
356 "user_id": user_id,
357 });
358 self.request(Method::UnbanChatMember, body.to_string().as_bytes())
359 }
360
361 pub fn restrict_chat_member(
362 &self,
363 chat_id: ChatId,
364 user_id: UserId,
365 permissions: ChatPermissions,
366 ) -> Result<True> {
367 let body = serde_json::json!({
368 "chat_id": chat_id,
369 "user_id": user_id,
370 "permissions": permissions,
371 });
372 self.request(Method::RestrictChatMember, body.to_string().as_bytes())
373 }
374
375 pub fn promote_chat_member(&self, chat_id: ChatId, user_id: UserId) -> Result<True> {
376 let body = serde_json::json!({
377 "chat_id": chat_id,
378 "user_id": user_id,
379 });
380 self.request(Method::PromoteChatMember, body.to_string().as_bytes())
381 }
382
383 pub fn set_chat_administrator_custom_title(
384 &self,
385 chat_id: ChatId,
386 user_id: UserId,
387 custom_title: String,
388 ) -> Result<True> {
389 let body = serde_json::json!({
390 "chat_id": chat_id,
391 "user_id": user_id,
392 "custom_title": custom_title,
393 });
394 self.request(
395 Method::SetChatAdministratorCustomTitle,
396 body.to_string().as_bytes(),
397 )
398 }
399
400 pub fn ban_chat_sender_chat(&self, chat_id: ChatId, sender_chat_id: i32) -> Result<True> {
401 let body = serde_json::json!({
402 "chat_id": chat_id,
403 "sender_chat_id": sender_chat_id,
404 });
405 self.request(Method::BanChatSenderChat, body.to_string().as_bytes())
406 }
407
408 pub fn unban_chat_sender_chat(&self, chat_id: ChatId, sender_chat_id: i32) -> Result<True> {
409 let body = serde_json::json!({
410 "chat_id": chat_id,
411 "sender_chat_id": sender_chat_id,
412 });
413 self.request(Method::UnbanChatSenderChat, body.to_string().as_bytes())
414 }
415
416 pub fn set_chat_permissions(
417 &self,
418 chat_id: ChatId,
419 permissions: ChatPermissions,
420 ) -> Result<True> {
421 let body = serde_json::json!({
422 "chat_id": chat_id,
423 "permissions": permissions,
424 });
425 self.request(Method::SetChatPermissions, body.to_string().as_bytes())
426 }
427
428 pub fn export_chat_invite_link(&self, chat_id: ChatId) -> Result<String> {
429 let body = serde_json::json!({
430 "chat_id": chat_id,
431 });
432 self.request(Method::ExportChatInviteLink, body.to_string().as_bytes())
433 }
434
435 pub fn create_chat_invite_link(&self, chat_id: ChatId) -> Result<ChatInviteLink> {
436 let body = serde_json::json!({
437 "chat_id": chat_id,
438 });
439 self.request(Method::CreateChatInviteLink, body.to_string().as_bytes())
440 }
441
442 pub fn edit_chat_invite_link(
443 &self,
444 chat_id: ChatId,
445 invite_link: String,
446 ) -> Result<ChatInviteLink> {
447 let body = serde_json::json!({
448 "chat_id": chat_id,
449 "invite_link": invite_link,
450 });
451 self.request(Method::EditChatInviteLink, body.to_string().as_bytes())
452 }
453
454 pub fn revoke_chat_invite_link(
455 &self,
456 chat_id: ChatId,
457 invite_link: String,
458 ) -> Result<ChatInviteLink> {
459 let body = serde_json::json!({
460 "chat_id": chat_id,
461 "invite_link": invite_link,
462 });
463 self.request(Method::RevokeChatInviteLink, body.to_string().as_bytes())
464 }
465
466 pub fn approve_chat_join_request(&self, chat_id: ChatId, user_id: UserId) -> Result<True> {
467 let body = serde_json::json!({
468 "chat_id": chat_id,
469 "user_id": user_id,
470 });
471 self.request(Method::ApproveChatJoinRequest, body.to_string().as_bytes())
472 }
473
474 pub fn decline_chat_join_request(&self, chat_id: ChatId, user_id: UserId) -> Result<True> {
475 let body = serde_json::json!({
476 "chat_id": chat_id,
477 "user_id": user_id,
478 });
479 self.request(Method::DeclineChatJoinRequest, body.to_string().as_bytes())
480 }
481
482 pub fn set_chat_photo(&self, chat_id: ChatId, photo: InputFile) -> Result<True> {
483 if photo.needs_attach() {
484 panic!("unsupport attach currently");
485 } else {
486 let body = serde_json::json!({
487 "chat_id": chat_id,
488 "photo": photo,
489 });
490 self.request(Method::SetChatPhoto, body.to_string().as_bytes())
491 }
492 }
493
494 pub fn delete_chat_photo(&self, chat_id: ChatId) -> Result<True> {
495 let body = serde_json::json!({
496 "chat_id": chat_id,
497 });
498 self.request(Method::DeleteChatPhoto, body.to_string().as_bytes())
499 }
500
501 pub fn set_chat_title(&self, chat_id: ChatId, title: String) -> Result<True> {
502 let body = serde_json::json!({
503 "chat_id": chat_id,
504 "title": title,
505 });
506 self.request(Method::SetChatTitle, body.to_string().as_bytes())
507 }
508
509 pub fn set_chat_description(&self, chat_id: ChatId) -> Result<True> {
510 let body = serde_json::json!({
511 "chat_id": chat_id,
512 });
513 self.request(Method::SetChatDescription, body.to_string().as_bytes())
514 }
515
516 pub fn pin_chat_message(&self, chat_id: ChatId, message_id: i32) -> Result<True> {
517 let body = serde_json::json!({
518 "chat_id": chat_id,
519 "message_id": message_id,
520 });
521 self.request(Method::PinChatMessage, body.to_string().as_bytes())
522 }
523
524 pub fn unpin_chat_message(&self, chat_id: ChatId) -> Result<True> {
525 let body = serde_json::json!({
526 "chat_id": chat_id,
527 });
528 self.request(Method::UnpinChatMessage, body.to_string().as_bytes())
529 }
530
531 pub fn unpin_all_chat_message(&self, chat_id: ChatId) -> Result<True> {
532 let body = serde_json::json!({
533 "chat_id": chat_id,
534 });
535 self.request(Method::UnpinAllChatMessages, body.to_string().as_bytes())
536 }
537
538 pub fn leave_chat(&self, chat_id: ChatId) -> Result<True> {
539 let body = serde_json::json!({
540 "chat_id": chat_id,
541 });
542 self.request(Method::LeaveChat, body.to_string().as_bytes())
543 }
544
545 pub fn get_chat(&self, chat_id: ChatId) -> Result<Chat> {
546 let body = serde_json::json!({
547 "chat_id": chat_id,
548 });
549 self.request(Method::GetChat, body.to_string().as_bytes())
550 }
551
552 pub fn get_chat_administrators(&self, chat_id: ChatId) -> Result<ChatMember> {
553 let body = serde_json::json!({
554 "chat_id": chat_id,
555 });
556 self.request(Method::GetChatAdministrators, body.to_string().as_bytes())
557 }
558
559 pub fn get_chat_member_count(&self, chat_id: ChatId) -> Result<i32> {
560 let body = serde_json::json!({
561 "chat_id": chat_id,
562 });
563 self.request(Method::GetChatMemberCount, body.to_string().as_bytes())
564 }
565
566 pub fn get_chat_member(&self, chat_id: ChatId, user_id: UserId) -> Result<ChatMember> {
567 let body = serde_json::json!({
568 "chat_id": chat_id,
569 "user_id": user_id,
570 });
571 self.request(Method::GetChatMember, body.to_string().as_bytes())
572 }
573
574 pub fn edit_message_text<T>(
577 &self,
578 chat_id: ChatId,
579 message_id: MessageId,
580 text: T,
581 ) -> Result<Message>
582 where
583 T: Into<String>,
584 {
585 let text = text.into();
586 let body = serde_json::json!({
587 "chat_id": chat_id,
588 "message_id": message_id.0,
589 "text": text,
590 });
591 self.request(Method::EditMessageText, body.to_string().as_bytes())
592 }
593
594 pub fn edit_message_text_with_parse_mode<T>(
595 &self,
596 chat_id: ChatId,
597 message_id: MessageId,
598 text: T,
599 parse_mode: ParseMode,
600 ) -> Result<Message>
601 where
602 T: Into<String>,
603 {
604 let text = text.into();
605 let body = serde_json::json!({
606 "chat_id": chat_id,
607 "message_id": message_id.0,
608 "text": text,
609 "parse_mode": parse_mode,
610 });
611 self.request(Method::EditMessageText, body.to_string().as_bytes())
612 }
613
614 pub fn delete_message(&self, chat_id: ChatId, message_id: MessageId) -> Result<True> {
615 let body = serde_json::json!({
616 "chat_id": chat_id,
617 "message_id": message_id.0,
618 });
619 self.request(Method::DeleteMessage, body.to_string().as_bytes())
620 }
621
622 pub fn delete_messages(&self, chat_id: ChatId, message_ids: Vec<MessageId>) -> Result<True> {
623 let body = serde_json::json!({
624 "chat_id": chat_id,
625 "message_ids": message_ids.iter().map(|id| id.0).collect::<Vec<i32>>(),
626 });
627 self.request(Method::DeleteMessages, body.to_string().as_bytes())
628 }
629}