telexide_fork/api/api.rs
1use super::{response::Response, types::*, APIEndpoint};
2use crate::{
3 model::*,
4 utils::{
5 result::{Result, TelegramError},
6 FormDataFile,
7 },
8};
9use async_trait::async_trait;
10use std::vec::Vec;
11
12/// This trait provides methods for interacting with the telegram API.
13#[async_trait]
14pub trait API: Sync {
15 /// executes a get request to the given telegram api endpoint
16 async fn get(&self, endpoint: APIEndpoint, data: Option<serde_json::Value>)
17 -> Result<Response>;
18
19 /// executes a post request to the given telegram api endpoint
20 async fn post(
21 &self,
22 endpoint: APIEndpoint,
23 data: Option<serde_json::Value>,
24 ) -> Result<Response>;
25
26 /// executes a post request to the given api endpoint and uploads the given
27 /// files
28 async fn post_file(
29 &self,
30 endpoint: APIEndpoint,
31 data: Option<serde_json::Value>,
32 files: Option<Vec<FormDataFile>>,
33 ) -> Result<Response>;
34
35 /// A simple method for testing your bot's auth token. Requires no
36 /// parameters. Returns basic information about the bot in form of a
37 /// [`User`] object.
38 async fn get_me(&self) -> Result<User> {
39 self.get(APIEndpoint::GetMe, None).await?.into()
40 }
41
42 /// Use this method to log out from the cloud Bot API server before
43 /// launching the bot locally. You **must** log out the bot before
44 /// running it locally, otherwise there is no guarantee that
45 /// the bot will receive updates. After a successful call, you will not be
46 /// able to log in again using the same token for 10 minutes. Returns
47 /// True on success.
48 async fn log_out(&self) -> Result<bool> {
49 self.post(APIEndpoint::LogOut, None).await?.into()
50 }
51
52 /// Use this method to close the bot instance before moving it from one
53 /// local server to another. You need to delete the webhook before
54 /// calling this method to ensure that the bot isn't launched again
55 /// after server restart. The method will return error 429 in the first 10
56 /// minutes after the bot is launched.
57 async fn close(&self) -> Result<bool> {
58 self.post(APIEndpoint::Close, None).await?.into()
59 }
60
61 /// (**WARNING:** this method should not be used by the library user
62 /// themselves as this gets handled by the [`Client`] object,
63 /// to handle an update event, please subscribe to those using
64 /// [`subscribe_handler`]) Use this method to receive incoming updates
65 /// using long polling. A `Vec<`[`Update`]`>` is returned.
66 ///
67 /// [`Client`]: ../client/struct.Client.html
68 /// [`subscribe_handler`]:
69 /// ../client/struct.Client.html#method.subscribe_handler
70 async fn get_updates(&self, data: GetUpdates) -> Result<Vec<Update>> {
71 self.get(APIEndpoint::GetUpdates, Some(serde_json::to_value(data)?))
72 .await?
73 .into()
74 }
75
76 /// Use this method to specify a url and receive incoming updates via an
77 /// outgoing webhook. Whenever there is an update for the bot, we will
78 /// send an HTTPS POST request to the specified url, containing a
79 /// JSON-serialized [Update]. In case of an unsuccessful request,
80 /// we will give up after a reasonable amount of attempts. Returns True on
81 /// success.
82 async fn set_webhook(&self, data: SetWebhook) -> Result<bool> {
83 self.post(APIEndpoint::SetWebhook, Some(serde_json::to_value(data)?))
84 .await?
85 .into()
86 }
87
88 /// Use this method to remove webhook integration if you decide to switch
89 /// back to using [API::get_updates]. Returns True on success.
90 async fn delete_webhook(&self, data: DeleteWebhook) -> Result<bool> {
91 self.get(
92 APIEndpoint::DeleteWebhook,
93 Some(serde_json::to_value(data)?),
94 )
95 .await?
96 .into()
97 }
98
99 /// Use this method to get current webhook status. On success, returns a
100 /// [WebhookInfo] object. If the bot is using [API::get_updates], will
101 /// return a [WebhookInfo] object with the url field empty.
102 async fn get_webhook_info(&self) -> Result<WebhookInfo> {
103 self.get(APIEndpoint::GetWebhookInfo, None).await?.into()
104 }
105
106 /// Use this method to send text messages. On success, the sent [`Message`]
107 /// is returned.
108 async fn send_message(&self, data: SendMessage) -> Result<Message> {
109 self.post(APIEndpoint::SendMessage, Some(serde_json::to_value(data)?))
110 .await?
111 .into()
112 }
113
114 /// Use this method to change the list of the bot's commands. Returns True
115 /// on success.
116 async fn set_my_commands(&self, data: SetMyCommands) -> Result<bool> {
117 self.post(
118 APIEndpoint::SetMyCommands,
119 Some(serde_json::to_value(data)?),
120 )
121 .await?
122 .into()
123 }
124
125 /// Use this method to get the current list of the bot's commands. Requires
126 /// no parameters. Returns a `Vec<`[`BotCommand`]`>` on success.
127 async fn get_my_commands(&self) -> Result<Vec<BotCommand>> {
128 self.get(APIEndpoint::GetMyCommands, None).await?.into()
129 }
130
131 /// Use this method to forward messages of any kind. On success, the sent
132 /// [`Message`] is returned.
133 async fn forward_message(&self, data: ForwardMessage) -> Result<Message> {
134 self.post(
135 APIEndpoint::ForwardMessage,
136 Some(serde_json::to_value(data)?),
137 )
138 .await?
139 .into()
140 }
141
142 /// Use this method to copy messages of any kind. The method is analogous to
143 /// the method [`forward_message`], but the copied message doesn't have
144 /// a link to the original message. Returns the [`MessageId`] of the
145 /// sent message on success.
146 ///
147 /// [`forward_message`]: API::forward_message
148 async fn copy_message(&self, data: CopyMessage) -> Result<MessageId> {
149 self.post(APIEndpoint::CopyMessage, Some(serde_json::to_value(data)?))
150 .await?
151 .into()
152 }
153
154 /// Use this method to send photos. On success, the sent [`Message`] is
155 /// returned.
156 async fn send_photo(&self, data: SendPhoto) -> Result<Message> {
157 match &data.photo {
158 InputFile::String(_) => self
159 .post(APIEndpoint::SendPhoto, Some(serde_json::to_value(&data)?))
160 .await?
161 .into(),
162 InputFile::File(f) => self
163 .post_file(
164 APIEndpoint::SendPhoto,
165 Some(serde_json::to_value(&data)?),
166 Some(vec![f.clone()]),
167 )
168 .await?
169 .into(),
170 }
171 }
172
173 /// Use this method to send audio files, if you want Telegram clients to
174 /// display them in the music player. Your audio must be in the .MP3 or
175 /// .M4A format. On success, the sent [`Message`] is returned.
176 /// Bots can currently send audio files of up to 50 MB in size, this limit
177 /// may be changed in the future.
178 async fn send_audio(&self, data: SendAudio) -> Result<Message> {
179 let mut files = Vec::new();
180 if let InputFile::File(f) = &data.audio {
181 files.push(f.clone());
182 }
183 if data.thumb.is_some() {
184 if let InputFile::File(f) = data.thumb.as_ref().unwrap() {
185 files.push(f.clone());
186 }
187 }
188
189 self.post_file(
190 APIEndpoint::SendDocument,
191 Some(serde_json::to_value(&data)?),
192 Some(files),
193 )
194 .await?
195 .into()
196 }
197
198 /// Use this method to send general files. On success, the sent [`Message`]
199 /// is returned. Bots can currently send files of any type of up to 50
200 /// MB in size, this limit may be changed in the future.
201 async fn send_document(&self, data: SendDocument) -> Result<Message> {
202 let mut files = Vec::new();
203 if let InputFile::File(f) = &data.document {
204 files.push(f.clone());
205 }
206
207 if data.thumb.is_some() {
208 if let InputFile::File(f) = data.thumb.as_ref().unwrap() {
209 files.push(f.clone());
210 }
211 }
212
213 self.post_file(
214 APIEndpoint::SendDocument,
215 Some(serde_json::to_value(&data)?),
216 Some(files),
217 )
218 .await?
219 .into()
220 }
221
222 /// Use this method to send video files, Telegram clients support mp4 videos
223 /// (other formats may be sent as [`Document`]). On success, the sent
224 /// [`Message`] is returned. Bots can currently send video files of up to 50
225 /// MB in size, this limit may be changed in the future.
226 async fn send_video(&self, data: SendVideo) -> Result<Message> {
227 let mut files = Vec::new();
228 if let InputFile::File(f) = &data.video {
229 files.push(f.clone());
230 }
231
232 if data.thumb.is_some() {
233 if let InputFile::File(f) = data.thumb.as_ref().unwrap() {
234 files.push(f.clone());
235 }
236 }
237
238 self.post_file(
239 APIEndpoint::SendDocument,
240 Some(serde_json::to_value(&data)?),
241 Some(files),
242 )
243 .await?
244 .into()
245 }
246
247 /// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video
248 /// without sound). On success, the sent [`Message`] is returned. Bots
249 /// can currently send animation files of up to 50 MB in size, this limit
250 /// may be changed in the future.
251 async fn send_animation(&self, data: SendAnimation) -> Result<Message> {
252 let mut files = Vec::new();
253 if let InputFile::File(f) = &data.animation {
254 files.push(f.clone());
255 }
256
257 if data.thumb.is_some() {
258 if let InputFile::File(f) = data.thumb.as_ref().unwrap() {
259 files.push(f.clone());
260 }
261 }
262
263 self.post_file(
264 APIEndpoint::SendDocument,
265 Some(serde_json::to_value(&data)?),
266 Some(files),
267 )
268 .await?
269 .into()
270 }
271
272 /// Use this method to send audio files, if you want Telegram clients to
273 /// display the file as a playable voice message. For this to work, your
274 /// audio must be in an .OGG file encoded with OPUS (other formats may be
275 /// sent as [`Audio`] or [`Document`]). On success, the sent [`Message`]
276 /// is returned. Bots can currently send voice messages of up to 50 MB in
277 /// size, this limit may be changed in the future.
278 async fn send_voice(&self, data: SendVoice) -> Result<Message> {
279 let mut files = Vec::new();
280 if let InputFile::File(f) = &data.voice {
281 files.push(f.clone());
282 }
283
284 self.post_file(
285 APIEndpoint::SendDocument,
286 Some(serde_json::to_value(&data)?),
287 Some(files),
288 )
289 .await?
290 .into()
291 }
292
293 /// As of v.4.0, Telegram clients support rounded square mp4 videos of up to
294 /// 1 minute long. Use this method to send video messages. On success,
295 /// the sent [`Message`] is returned.
296 async fn send_video_note(&self, data: SendVideoNote) -> Result<Message> {
297 let mut files = Vec::new();
298 if let InputFile::File(f) = &data.video_note {
299 files.push(f.clone());
300 }
301
302 if data.thumb.is_some() {
303 if let InputFile::File(f) = data.thumb.as_ref().unwrap() {
304 files.push(f.clone());
305 }
306 }
307
308 self.post_file(
309 APIEndpoint::SendDocument,
310 Some(serde_json::to_value(&data)?),
311 Some(files),
312 )
313 .await?
314 .into()
315 }
316
317 /// Use this method to send a group of photos or videos as an album.
318 /// On success, a [`Vec<Message>`] is returned.
319 async fn send_media_group(&self, data: SendMediaGroup) -> Result<Vec<Message>> {
320 let mut files = Vec::new();
321 for media in &data.media {
322 if let InputFile::File(f) = media.get_media() {
323 files.push(f.clone());
324 }
325 }
326
327 files.dedup_by(|f1, f2| f1 == f2);
328
329 self.post_file(
330 APIEndpoint::SendMediaGroup,
331 Some(serde_json::to_value(&data)?),
332 Some(files),
333 )
334 .await?
335 .into()
336 }
337
338 /// Use this method to send a point on the map. On success, the sent
339 /// [`Message`] is returned.
340 async fn send_location(&self, data: SendLocation) -> Result<Message> {
341 self.post(APIEndpoint::SendLocation, Some(serde_json::to_value(data)?))
342 .await?
343 .into()
344 }
345
346 /// Use this method to send information about a venue. On success, the sent
347 /// [`Message`] is returned.
348 async fn send_venue(&self, data: SendVenue) -> Result<Message> {
349 self.post(APIEndpoint::SendVenue, Some(serde_json::to_value(data)?))
350 .await?
351 .into()
352 }
353
354 /// Use this method to send phone contacts. On success, the sent [`Message`]
355 /// is returned.
356 async fn send_contact(&self, data: SendContact) -> Result<Message> {
357 self.post(APIEndpoint::SendContact, Some(serde_json::to_value(data)?))
358 .await?
359 .into()
360 }
361
362 /// Use this method to send a native poll. On success, the sent [`Message`]
363 /// is returned.
364 async fn send_poll(&self, data: SendPoll) -> Result<Message> {
365 self.post(APIEndpoint::SendPoll, Some(serde_json::to_value(data)?))
366 .await?
367 .into()
368 }
369
370 /// Use this method to send a dice, which will have a random value from 1 to
371 /// 6. On success, the sent [Message] is returned.
372 async fn send_dice(&self, data: SendDice) -> Result<Message> {
373 self.post(APIEndpoint::SendDice, Some(serde_json::to_value(data)?))
374 .await?
375 .into()
376 }
377
378 /// Use this method when you need to tell the user that something is
379 /// happening on the bot's side. The status is set for 5 seconds or less
380 /// (when a message arrives from your bot, Telegram clients clear its typing
381 /// status). Returns True on success.
382 async fn send_chat_action(&self, data: SendChatAction) -> Result<bool> {
383 self.post(
384 APIEndpoint::SendChatAction,
385 Some(serde_json::to_value(data)?),
386 )
387 .await?
388 .into()
389 }
390
391 /// Use this method to edit text and game messages. On success, if edited
392 /// message is sent by the bot, the edited [`Message`] is returned,
393 /// otherwise True is returned.
394 async fn edit_message_text(&self, data: EditMessageText) -> Result<TrueOrObject<Message>> {
395 self.post(
396 APIEndpoint::EditMessageText,
397 Some(serde_json::to_value(data)?),
398 )
399 .await?
400 .into()
401 }
402
403 /// Use this method to edit captions of messages. On success, if edited
404 /// message is sent by the bot, the edited [`Message`] is returned,
405 /// otherwise True is returned.
406 async fn edit_message_caption(
407 &self,
408 data: EditMessageCaption,
409 ) -> Result<TrueOrObject<Message>> {
410 self.post(
411 APIEndpoint::EditMessageCaption,
412 Some(serde_json::to_value(data)?),
413 )
414 .await?
415 .into()
416 }
417
418 /// Use this method to edit animation, audio, document, photo, or video
419 /// messages. If a message is a part of a message album, then it can be
420 /// edited only to a photo or a video. Otherwise, message type can be
421 /// changed arbitrarily. When inline message is edited, new file can't be
422 /// uploaded. Use previously uploaded file via its file_id or specify a
423 /// URL. On success, if the edited message was sent by the bot, the
424 /// edited [`Message`] is returned, otherwise True is returned.
425 async fn edit_message_media(&self, data: EditMessageMedia) -> Result<TrueOrObject<Message>> {
426 self.post(
427 APIEndpoint::EditMessageMedia,
428 Some(serde_json::to_value(data)?),
429 )
430 .await?
431 .into()
432 }
433
434 /// Use this method to edit only the reply markup of messages. On success,
435 /// if edited message is sent by the bot, the edited [`Message`] is
436 /// returned, otherwise True is returned.
437 async fn edit_message_reply_markup(
438 &self,
439 data: EditMessageReplyMarkup,
440 ) -> Result<TrueOrObject<Message>> {
441 self.post(
442 APIEndpoint::EditMessageReplyMarkup,
443 Some(serde_json::to_value(data)?),
444 )
445 .await?
446 .into()
447 }
448
449 /// Use this method to stop a poll which was sent by the bot. On success,
450 /// the stopped [`Poll`] with the final results is returned.
451 async fn stop_poll(&self, data: StopPoll) -> Result<Poll> {
452 self.post(APIEndpoint::StopPoll, Some(serde_json::to_value(data)?))
453 .await?
454 .into()
455 }
456
457 /// Use this method to delete a message, including service messages, with
458 /// the following limitations:
459 /// - A message can only be deleted if it was sent less than 48 hours ago.
460 /// - A dice message in a private chat can only be deleted if it was sent
461 /// more than 24 hours ago.
462 /// - Bots can delete outgoing messages in private chats, groups, and
463 /// supergroups.
464 /// - Bots can delete incoming messages in private chats.
465 /// - Bots granted can_post_messages permissions can delete outgoing
466 /// messages in channels.
467 /// - If the bot is an administrator of a group, it can delete any message
468 /// there.
469 /// - If the bot has can_delete_messages permission in a supergroup or a
470 /// channel, it can delete any message there.
471 /// Returns True on success.
472 async fn delete_message(&self, data: DeleteMessage) -> Result<bool> {
473 self.post(
474 APIEndpoint::DeleteMessage,
475 Some(serde_json::to_value(data)?),
476 )
477 .await?
478 .into()
479 }
480
481 /// Use this method to edit live location messages.
482 /// A location can be edited until its live_period expires or editing is
483 /// explicitly disabled by a call to stopMessageLiveLocation.
484 /// On success, if the edited message was sent by the bot, the edited
485 /// [`Message`] is returned, otherwise True is returned.
486 async fn edit_message_live_location(
487 &self,
488 data: EditMessageLiveLocation,
489 ) -> Result<TrueOrObject<Message>> {
490 self.post(
491 APIEndpoint::EditMessageLiveLocation,
492 Some(serde_json::to_value(data)?),
493 )
494 .await?
495 .into()
496 }
497
498 /// Use this method to stop updating a live location message before
499 /// live_period expires. On success, if the message was sent by the bot,
500 /// the sent [`Message`] is returned, otherwise True is returned.
501 async fn stop_message_live_location(
502 &self,
503 data: StopMessageLiveLocation,
504 ) -> Result<TrueOrObject<Message>> {
505 self.post(
506 APIEndpoint::StopMessageLiveLocation,
507 Some(serde_json::to_value(data)?),
508 )
509 .await?
510 .into()
511 }
512
513 /// Use this method to get a list of profile pictures for a user. Returns a
514 /// [`UserProfilePhotos`] object.
515 async fn get_user_profile_photos(
516 &self,
517 data: GetUserProfilePhotos,
518 ) -> Result<UserProfilePhotos> {
519 self.post(
520 APIEndpoint::GetUserProfilePhotos,
521 Some(serde_json::to_value(data)?),
522 )
523 .await?
524 .into()
525 }
526
527 /// Use this method to get basic info about a file and prepare it for
528 /// downloading. For the moment, bots can download files of up to 20MB
529 /// in size. On success, a [`File`] object is returned. The file can then be downloaded via the link `https://api.telegram.org/file/bot<token>/<file_path>`, where <file_path> is taken from the response.
530 /// It is guaranteed that the link will be valid for at least 1 hour. When
531 /// the link expires, a new one can be requested by calling
532 /// [`API::get_file`] again.
533 async fn get_file(&self, data: GetFile) -> Result<File> {
534 self.post(APIEndpoint::GetFile, Some(serde_json::to_value(data)?))
535 .await?
536 .into()
537 }
538
539 /// Use this method to unban a previously kicked user in a supergroup or
540 /// channel. The user will not return to the group or channel
541 /// automatically, but will be able to join via link, etc. The bot must
542 /// be an administrator for this to work. Returns True on success.
543 async fn unban_chat_member(&self, data: UnbanChatMember) -> Result<bool> {
544 self.post(
545 APIEndpoint::UnbanChatMember,
546 Some(serde_json::to_value(data)?),
547 )
548 .await?
549 .into()
550 }
551
552 /// Use this method to kick a user from a group, a supergroup or a channel.
553 /// In the case of supergroups and channels, the user will not be able to
554 /// return to the group on their own using invite links, etc., unless
555 /// unbanned first. The bot must be an administrator in the chat for
556 /// this to work and must have the appropriate admin rights. Returns True on
557 /// success.
558 async fn kick_chat_member(&self, data: KickChatMember) -> Result<bool> {
559 self.post(
560 APIEndpoint::KickChatMember,
561 Some(serde_json::to_value(data)?),
562 )
563 .await?
564 .into()
565 }
566
567 /// Use this method to restrict a user in a supergroup.
568 /// The bot must be an administrator in the supergroup for this to work and
569 /// must have the appropriate admin rights. Pass True for all
570 /// permissions to lift restrictions from a user. Returns True on success.
571 async fn restrict_chat_member(&self, data: RestrictChatMember) -> Result<bool> {
572 self.post(
573 APIEndpoint::RestrictChatMember,
574 Some(serde_json::to_value(data)?),
575 )
576 .await?
577 .into()
578 }
579
580 /// Use this method to promote or demote a user in a supergroup or a
581 /// channel. The bot must be an administrator in the chat for this to
582 /// work and must have the appropriate admin rights. Pass False for all
583 /// boolean parameters to demote a user. Returns True on success.
584 async fn promote_chat_member(&self, data: PromoteChatMember) -> Result<bool> {
585 self.post(
586 APIEndpoint::PromoteChatMember,
587 Some(serde_json::to_value(data)?),
588 )
589 .await?
590 .into()
591 }
592
593 /// Use this method to set a custom title for an administrator in a
594 /// supergroup promoted by the bot. Returns True on success.
595 async fn set_chat_administrator_custom_title(
596 &self,
597 data: SetChatAdministratorCustomTitle,
598 ) -> Result<bool> {
599 self.post(
600 APIEndpoint::SetChatAdministratorCustomTitle,
601 Some(serde_json::to_value(data)?),
602 )
603 .await?
604 .into()
605 }
606
607 /// Use this method to set default chat permissions for all members.
608 /// The bot must be an administrator in the group or a supergroup for this
609 /// to work and must have the can_restrict_members admin rights. Returns
610 /// True on success.
611 async fn set_chat_permissions(&self, data: SetChatPermissions) -> Result<bool> {
612 self.post(
613 APIEndpoint::SetChatPermissions,
614 Some(serde_json::to_value(data)?),
615 )
616 .await?
617 .into()
618 }
619
620 /// Use this method to generate a new invite link for a chat; any previously
621 /// generated link is revoked. The bot must be an administrator in the
622 /// chat for this to work and must have the appropriate admin rights.
623 /// Returns the new invite link as String on success.
624 ///
625 /// Note: Each administrator in a chat generates their own invite links.
626 /// Bots can't use invite links generated by other administrators.
627 /// If you want your bot to work with invite links, it will need to generate
628 /// its own link using [`API::export_chat_invite_link`] – after this the
629 /// link will become available to the bot via the [`API::get_chat`] method.
630 /// If your bot needs to generate a new invite link replacing its previous
631 /// one, use [`API::export_chat_invite_link`] again.
632 async fn export_chat_invite_link(&self, data: ExportChatInviteLink) -> Result<String> {
633 self.post(
634 APIEndpoint::ExportChatInviteLink,
635 Some(serde_json::to_value(data)?),
636 )
637 .await?
638 .into()
639 }
640
641 /// Use this method to create an additional invite link for a chat. The bot
642 /// must be an administrator in the chat for this to work and must have
643 /// the appropriate admin rights. The link can be revoked using the
644 /// method [`API::revoke_chat_invite_link`]. Returns the new invite link as
645 /// [`ChatInviteLink`] object.
646 async fn create_chat_invite_link(&self, data: CreateChatInviteLink) -> Result<ChatInviteLink> {
647 self.post(
648 APIEndpoint::CreateChatInviteLink,
649 Some(serde_json::to_value(data)?),
650 )
651 .await?
652 .into()
653 }
654
655 /// Use this method to edit a non-primary invite link created by the bot.
656 /// The bot must be an administrator in the chat for this to work and
657 /// must have the appropriate admin rights. Returns the edited invite
658 /// link as a [`ChatInviteLink`] object.
659 async fn edit_chat_invite_link(&self, data: EditChatInviteLink) -> Result<ChatInviteLink> {
660 self.post(
661 APIEndpoint::EditChatInviteLink,
662 Some(serde_json::to_value(data)?),
663 )
664 .await?
665 .into()
666 }
667
668 /// Use this method to revoke an invite link created by the bot. If the
669 /// primary link is revoked, a new link is automatically generated. The
670 /// bot must be an administrator in the chat for this to work and must
671 /// have the appropriate admin rights. Returns the revoked invite link
672 /// as [`ChatInviteLink`] object.
673 async fn revoke_chat_invite_link(&self, data: RevokeChatInviteLink) -> Result<ChatInviteLink> {
674 self.post(
675 APIEndpoint::RevokeChatInviteLink,
676 Some(serde_json::to_value(data)?),
677 )
678 .await?
679 .into()
680 }
681
682 /// Use this method to set a new profile photo for the chat. Photos can't be
683 /// changed for private chats. The bot must be an administrator in the
684 /// chat for this to work and must have the appropriate admin rights.
685 /// Returns True on success.
686 async fn set_chat_photo(&self, data: SetChatPhoto) -> Result<bool> {
687 let mut files = Vec::new();
688 match &data.photo {
689 InputFile::File(f) => files.push(f.clone()),
690 InputFile::String(_) => {
691 return Err(TelegramError::InvalidArgument(
692 "this endpoint only accepts files to be uploaded".to_owned(),
693 )
694 .into())
695 }
696 }
697
698 self.post_file(
699 APIEndpoint::SetChatPhoto,
700 Some(serde_json::to_value(&data)?),
701 Some(files),
702 )
703 .await?
704 .into()
705 }
706
707 /// Use this method to delete a chat photo. Photos can't be changed for
708 /// private chats. The bot must be an administrator in the chat for this
709 /// to work and must have the appropriate admin rights. Returns True on
710 /// success.
711 async fn delete_chat_photo(&self, data: DeleteChatPhoto) -> Result<bool> {
712 self.post(
713 APIEndpoint::DeleteChatPhoto,
714 Some(serde_json::to_value(data)?),
715 )
716 .await?
717 .into()
718 }
719
720 /// Use this method to change the title of a chat. Titles can't be changed
721 /// for private chats. The bot must be an administrator in the chat for
722 /// this to work and must have the appropriate admin rights.
723 /// Returns True on success.
724 async fn set_chat_title(&self, data: SetChatTitle) -> Result<bool> {
725 self.post(APIEndpoint::SetChatTitle, Some(serde_json::to_value(data)?))
726 .await?
727 .into()
728 }
729
730 /// Use this method to change the description of a group, a supergroup or a
731 /// channel. The bot must be an administrator in the chat for this to
732 /// work and must have the appropriate admin rights. Returns True on
733 /// success.
734 async fn set_chat_description(&self, data: SetChatDescription) -> Result<bool> {
735 self.post(
736 APIEndpoint::SetChatDescription,
737 Some(serde_json::to_value(data)?),
738 )
739 .await?
740 .into()
741 }
742
743 /// Use this method to pin a message in a group, a supergroup, or a channel.
744 /// The bot must be an administrator in the chat for this to work and must
745 /// have the ‘can_pin_messages’ admin right in the supergroup
746 /// or ‘can_edit_messages’ admin right in the channel. Returns True on
747 /// success.
748 async fn pin_chat_message(&self, data: PinChatMessage) -> Result<bool> {
749 self.post(
750 APIEndpoint::PinChatMessage,
751 Some(serde_json::to_value(data)?),
752 )
753 .await?
754 .into()
755 }
756
757 /// Use this method to remove a message from the list of pinned messages in
758 /// a chat. If the chat is not a private chat, the bot must be an
759 /// administrator in the chat for this to work and must have the
760 /// 'can_pin_messages' admin right in a supergroup or 'can_edit_messages'
761 /// admin right in a channel. Returns True on success.
762 async fn unpin_chat_message(&self, data: UnpinChatMessage) -> Result<bool> {
763 self.post(
764 APIEndpoint::UnpinChatMessage,
765 Some(serde_json::to_value(data)?),
766 )
767 .await?
768 .into()
769 }
770
771 /// Use this method to clear the list of pinned messages in a chat. If the
772 /// chat is not a private chat, the bot must be an administrator in the
773 /// chat for this to work and must have the 'can_pin_messages' admin
774 /// right in a supergroup or 'can_edit_messages' admin right in a
775 /// channel. Returns True on success.
776 async fn unpin_all_chat_messages(&self, data: UnpinAllChatMessages) -> Result<bool> {
777 self.post(
778 APIEndpoint::UnpinAllChatMessages,
779 Some(serde_json::to_value(data)?),
780 )
781 .await?
782 .into()
783 }
784
785 /// Use this method for your bot to leave a group, supergroup or channel.
786 /// Returns True on success.
787 async fn leave_chat(&self, data: LeaveChat) -> Result<bool> {
788 self.post(APIEndpoint::LeaveChat, Some(serde_json::to_value(data)?))
789 .await?
790 .into()
791 }
792
793 /// Use this method to get up to date information about the chat
794 /// (current name of the user for one-on-one conversations, current username
795 /// of a user, group or channel, etc.). Returns a [`Chat`] object on
796 /// success.
797 async fn get_chat(&self, data: GetChat) -> Result<Chat> {
798 self.get(APIEndpoint::GetChat, Some(serde_json::to_value(data)?))
799 .await?
800 .into()
801 }
802
803 /// Use this method to get a list of administrators in a chat.
804 /// On success, returns a `Vec<`[`ChatMember`]`>` that contains information
805 /// about all chat administrators except other bots. If the chat is a
806 /// group or a supergroup and no administrators were appointed, only the
807 /// creator will be returned.
808 async fn get_chat_administrators(
809 &self,
810 data: GetChatAdministrators,
811 ) -> Result<Vec<ChatMember>> {
812 self.get(
813 APIEndpoint::GetChatAdministrators,
814 Some(serde_json::to_value(data)?),
815 )
816 .await?
817 .into()
818 }
819
820 /// Use this method to get the number of members in a chat. Returns i64 on
821 /// success.
822 async fn get_members_count(&self, data: GetChatMembersCount) -> Result<i64> {
823 self.get(
824 APIEndpoint::GetChatMembersCount,
825 Some(serde_json::to_value(data)?),
826 )
827 .await?
828 .into()
829 }
830
831 /// Use this method to get information about a member of a chat. Returns a
832 /// [`ChatMember`] object on success.
833 async fn get_chat_member(&self, data: GetChatMember) -> Result<ChatMember> {
834 self.get(
835 APIEndpoint::GetChatMember,
836 Some(serde_json::to_value(data)?),
837 )
838 .await?
839 .into()
840 }
841
842 /// Use this method to set a new group sticker set for a supergroup.
843 /// The bot must be an administrator in the chat for this to work and must
844 /// have the appropriate admin rights. Use the field can_set_sticker_set
845 /// optionally returned in [`API::get_chat`] requests to check if the bot
846 /// can use this method. Returns True on success.
847 async fn set_chat_sticker_set(&self, data: SetChatStickerSet) -> Result<bool> {
848 self.post(
849 APIEndpoint::SetChatStickerSet,
850 Some(serde_json::to_value(data)?),
851 )
852 .await?
853 .into()
854 }
855
856 /// Use this method to delete a group sticker set from a supergroup.
857 /// The bot must be an administrator in the chat for this to work and must
858 /// have the appropriate admin rights. Use the field can_set_sticker_set
859 /// optionally returned in [`API::get_chat`] requests to check if the bot
860 /// can use this method. Returns True on success.
861 async fn delete_chat_sticker_set(&self, data: DeleteChatStickerSet) -> Result<bool> {
862 self.post(
863 APIEndpoint::DeleteChatStickerSet,
864 Some(serde_json::to_value(data)?),
865 )
866 .await?
867 .into()
868 }
869
870 /// Use this method to send answers to callback queries sent from [inline keyboards](https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating).
871 /// The answer will be displayed to the user as a notification at the top of
872 /// the chat screen or as an alert. On success, True is returned.
873 async fn answer_callback_query(&self, data: AnswerCallbackQuery) -> Result<bool> {
874 self.post(
875 APIEndpoint::AnswerCallbackQuery,
876 Some(serde_json::to_value(data)?),
877 )
878 .await?
879 .into()
880 }
881
882 /// Use this method to send static .WEBP or animated .TGS stickers. On
883 /// success, the sent [Message] is returned.
884 async fn send_sticker(&self, data: SendSticker) -> Result<Message> {
885 match &data.sticker {
886 InputFile::String(_) => self
887 .post(APIEndpoint::SendSticker, Some(serde_json::to_value(&data)?))
888 .await?
889 .into(),
890 InputFile::File(f) => self
891 .post_file(
892 APIEndpoint::SendSticker,
893 Some(serde_json::to_value(&data)?),
894 Some(vec![f.clone()]),
895 )
896 .await?
897 .into(),
898 }
899 }
900
901 /// Use this method to get a sticker set. On success, a [StickerSet] object
902 /// is returned.
903 async fn get_sticker_set(&self, data: GetStickerSet) -> Result<StickerSet> {
904 self.post(
905 APIEndpoint::GetStickerSet,
906 Some(serde_json::to_value(data)?),
907 )
908 .await?
909 .into()
910 }
911
912 /// Use this method to upload a .PNG file with a sticker for later use in
913 /// createNewStickerSet and addStickerToSet methods (can be used
914 /// multiple times). Returns the uploaded [File] on success.
915 async fn upload_sticker_file(&self, data: UploadStickerFile) -> Result<File> {
916 match &data.png_sticker {
917 InputFile::File(f) => self
918 .post_file(
919 APIEndpoint::UploadStickerFile,
920 Some(serde_json::to_value(&data)?),
921 Some(vec![f.clone()]),
922 )
923 .await?
924 .into(),
925 InputFile::String(_) => Err(TelegramError::InvalidArgument(
926 "upload_sticker_file only accepts files, not urls/ids".to_owned(),
927 )
928 .into()),
929 }
930 }
931
932 /// Use this method to create a new sticker set owned by a user.
933 /// The bot will be able to edit the sticker set thus created.
934 /// You must use exactly one of the fields png_sticker or tgs_sticker.
935 /// Returns True on success.
936 async fn create_new_sticker_set(&self, data: CreateNewStickerSet) -> Result<bool> {
937 if (data.png_sticker.is_some() && data.tgs_sticker.is_some())
938 || (data.png_sticker.is_none() && data.tgs_sticker.is_none())
939 {
940 return Err(TelegramError::InvalidArgument(
941 "You must use exactly one of the fields png_sticker or tgs_sticker".to_owned(),
942 )
943 .into());
944 }
945
946 let mut files = Vec::new();
947
948 if data.png_sticker.is_some() {
949 if let InputFile::File(f) = data.png_sticker.as_ref().unwrap() {
950 files.push(f.clone());
951 }
952 }
953
954 if data.tgs_sticker.is_some() {
955 match data.tgs_sticker.as_ref().unwrap() {
956 InputFile::File(f) => files.push(f.clone()),
957 InputFile::String(_) => {
958 return Err(TelegramError::InvalidArgument(
959 "tgs_sticker only accepts files, not urls/ids".to_owned(),
960 )
961 .into())
962 }
963 }
964 }
965
966 self.post_file(
967 APIEndpoint::CreateNewStickerSet,
968 Some(serde_json::to_value(&data)?),
969 Some(files),
970 )
971 .await?
972 .into()
973 }
974
975 /// Use this method to add a new sticker to a set created by the bot.
976 /// You must use exactly one of the fields png_sticker or tgs_sticker.
977 /// Animated stickers can be added to animated sticker sets and only to
978 /// them. Animated sticker sets can have up to 50 stickers. Static
979 /// sticker sets can have up to 120 stickers. Returns True on success.
980 async fn add_sticker_to_set(&self, data: AddStickerToSet) -> Result<bool> {
981 if (data.png_sticker.is_some() && data.tgs_sticker.is_some())
982 || (data.png_sticker.is_none() && data.tgs_sticker.is_none())
983 {
984 return Err(TelegramError::InvalidArgument(
985 "You must use exactly one of the fields png_sticker or tgs_sticker.".to_owned(),
986 )
987 .into());
988 }
989
990 let mut files = Vec::new();
991
992 if data.png_sticker.is_some() {
993 if let InputFile::File(f) = data.png_sticker.as_ref().unwrap() {
994 files.push(f.clone());
995 }
996 }
997
998 if data.tgs_sticker.is_some() {
999 match data.tgs_sticker.as_ref().unwrap() {
1000 InputFile::File(f) => files.push(f.clone()),
1001 InputFile::String(_) => {
1002 return Err(TelegramError::InvalidArgument(
1003 "tgs_sticker only accepts files, not urls/ids.".to_owned(),
1004 )
1005 .into())
1006 }
1007 }
1008 }
1009
1010 self.post_file(
1011 APIEndpoint::AddStickerToSet,
1012 Some(serde_json::to_value(&data)?),
1013 Some(files),
1014 )
1015 .await?
1016 .into()
1017 }
1018
1019 /// Use this method to move a sticker in a set created by the bot to a
1020 /// specific position. Returns True on success.
1021 async fn set_sticker_position_in_set(&self, data: SetStickerPositionInSet) -> Result<bool> {
1022 self.post(
1023 APIEndpoint::SetStickerPositionInSet,
1024 Some(serde_json::to_value(data)?),
1025 )
1026 .await?
1027 .into()
1028 }
1029
1030 /// Use this method to delete a sticker from a set created by the bot.
1031 /// Returns True on success.
1032 async fn delete_sticker_from_set(&self, data: DeleteStickerFromSet) -> Result<bool> {
1033 self.post(
1034 APIEndpoint::DeleteStickerFromSet,
1035 Some(serde_json::to_value(data)?),
1036 )
1037 .await?
1038 .into()
1039 }
1040
1041 /// Use this method to set the thumbnail of a sticker set.
1042 /// Animated thumbnails can be set for animated sticker sets only. Returns
1043 /// True on success.
1044 async fn set_sticker_set_thumb(&self, data: SetStickerSetThumb) -> Result<bool> {
1045 match &data.thumb {
1046 Some(InputFile::String(_)) | None => self
1047 .post(
1048 APIEndpoint::SetStickerSetThumb,
1049 Some(serde_json::to_value(&data)?),
1050 )
1051 .await?
1052 .into(),
1053 Some(InputFile::File(f)) => self
1054 .post_file(
1055 APIEndpoint::SetStickerSetThumb,
1056 Some(serde_json::to_value(&data)?),
1057 Some(vec![f.clone()]),
1058 )
1059 .await?
1060 .into(),
1061 }
1062 }
1063
1064 /// Use this method to send answers to an inline query. On success, True is
1065 /// returned. No more than 50 results per query are allowed.
1066 async fn answer_inline_query(&self, data: AnswerInlineQuery) -> Result<bool> {
1067 if data.results.len() > 50 {
1068 return Err(TelegramError::InvalidArgument(
1069 "No more than 50 results per query are allowed.".to_owned(),
1070 )
1071 .into());
1072 }
1073
1074 self.post(
1075 APIEndpoint::AnswerInlineQuery,
1076 Some(serde_json::to_value(data)?),
1077 )
1078 .await?
1079 .into()
1080 }
1081
1082 /// Use this method to send invoices. On success, the sent [Message] is
1083 /// returned.
1084 async fn send_invoice(&self, data: SendInvoice) -> Result<Message> {
1085 self.post(APIEndpoint::SendInvoice, Some(serde_json::to_value(data)?))
1086 .await?
1087 .into()
1088 }
1089
1090 /// If you sent an invoice requesting a shipping address and the parameter
1091 /// is_flexible was specified, the Bot API will send an [Update] with a
1092 /// shipping_query field to the bot. Use this method to reply to
1093 /// shipping queries. On success, True is returned.
1094 async fn answer_shipping_query(&self, data: AnswerShippingQuery) -> Result<bool> {
1095 self.post(
1096 APIEndpoint::AnswerShippingQuery,
1097 Some(serde_json::to_value(data)?),
1098 )
1099 .await?
1100 .into()
1101 }
1102
1103 /// Once the user has confirmed their payment and shipping details, the Bot
1104 /// API sends the final confirmation in the form of an [Update] with the
1105 /// field pre_checkout_query. Use this method to respond to such
1106 /// pre-checkout queries. On success, True is returned.
1107 /// **Note:** The Bot API must receive an answer within 10 seconds after the
1108 /// pre-checkout query was sent.
1109 async fn answer_pre_checkout_query(&self, data: AnswerPreCheckoutQuery) -> Result<bool> {
1110 self.post(
1111 APIEndpoint::AnswerPreCheckoutQuery,
1112 Some(serde_json::to_value(data)?),
1113 )
1114 .await?
1115 .into()
1116 }
1117
1118 /// Use this method to send a game. On success, the sent [Message] is
1119 /// returned.
1120 async fn send_game(&self, data: SendGame) -> Result<Message> {
1121 self.post(APIEndpoint::SendGame, Some(serde_json::to_value(data)?))
1122 .await?
1123 .into()
1124 }
1125
1126 /// Use this method to set the score of the specified user in a game.
1127 /// On success, if the message was sent by the bot, returns the edited
1128 /// Message, otherwise returns True. Returns an error, if the new score
1129 /// is not greater than the user's current score in the chat and force is
1130 /// False.
1131 async fn set_game_score(&self, data: SetGameScore) -> Result<TrueOrObject<Message>> {
1132 self.post(APIEndpoint::SetGameScore, Some(serde_json::to_value(data)?))
1133 .await?
1134 .into()
1135 }
1136
1137 /// Use this method to get data for high score tables. Will return the score
1138 /// of the specified user and several of his neighbors in a game.
1139 /// On success, returns a Vec of [GameHighScore] objects.
1140 async fn get_game_high_scores(&self, data: GetGameHighScores) -> Result<Vec<GameHighScore>> {
1141 self.post(
1142 APIEndpoint::GetGameHighScores,
1143 Some(serde_json::to_value(data)?),
1144 )
1145 .await?
1146 .into()
1147 }
1148
1149 /// Informs a user that some of the Telegram Passport elements they provided
1150 /// contains errors. The user will not be able to re-submit their
1151 /// Passport to you until the errors are fixed (the contents of the
1152 /// field for which you returned the error must change). Returns True on
1153 /// success.
1154 ///
1155 /// Use this if the data submitted by the user doesn't satisfy the standards
1156 /// your service requires for any reason. For example, if a birthday
1157 /// date seems invalid, a submitted document is blurry, a scan shows
1158 /// evidence of tampering, etc. Supply some details in the error message
1159 /// to make sure the user knows how to correct the issues.
1160 async fn set_passport_data_errors(&self, data: SetPassportDataErrors) -> Result<bool> {
1161 self.post(
1162 APIEndpoint::SetPassportDataErrors,
1163 Some(serde_json::to_value(data)?),
1164 )
1165 .await?
1166 .into()
1167 }
1168}