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