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}