From 6102a02ed4cd415ed8ebdad7b6ddbb2ca9e45266 Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi Date: Sat, 6 Mar 2021 03:18:03 +0600 Subject: [PATCH] Integrate teloxide-core --- CHANGELOG.md | 9 + Cargo.toml | 2 +- src/bot/api.rs | 1733 ---------------- src/bot/download.rs | 67 - src/bot/mod.rs | 252 --- .../dialogue/dialogue_dispatcher.rs | 32 +- .../dialogue/dialogue_dispatcher_handler.rs | 22 +- src/dispatching/dialogue/dialogue_with_cx.rs | 12 +- src/dispatching/dialogue/get_chat_id.rs | 2 +- .../dialogue/storage/redis_storage.rs | 5 +- .../dialogue/storage/sqlite_storage.rs | 4 +- src/dispatching/dialogue/transition.rs | 15 +- src/dispatching/dispatcher.rs | 120 +- src/dispatching/dispatcher_handler.rs | 14 +- src/dispatching/dispatcher_handler_rx_ext.rs | 29 +- src/dispatching/mod.rs | 4 +- src/dispatching/repls/commands_repl.rs | 26 +- src/dispatching/repls/dialogues_repl.rs | 29 +- src/dispatching/repls/repl.rs | 28 +- src/dispatching/update_listeners.rs | 43 +- src/dispatching/update_with_cx.rs | 124 +- src/errors.rs | 515 ----- src/lib.rs | 18 +- src/net/download.rs | 51 - src/net/mod.rs | 63 - src/net/request.rs | 63 - src/net/telegram_response.rs | 70 - src/prelude.rs | 11 +- src/requests/all/add_sticker_to_set.rs | 109 - src/requests/all/answer_callback_query.rs | 101 - src/requests/all/answer_inline_query.rs | 146 -- src/requests/all/answer_pre_checkout_query.rs | 82 - src/requests/all/answer_shipping_query.rs | 86 - src/requests/all/create_new_sticker_set.rs | 134 -- src/requests/all/delete_chat_photo.rs | 50 - src/requests/all/delete_chat_sticker_set.rs | 55 - src/requests/all/delete_message.rs | 67 - src/requests/all/delete_sticker_from_set.rs | 47 - src/requests/all/delete_webhook.rs | 37 - .../all/edit_inline_message_caption.rs | 83 - .../all/edit_inline_message_live_location.rs | 77 - src/requests/all/edit_inline_message_media.rs | 78 - .../all/edit_inline_message_reply_markup.rs | 62 - src/requests/all/edit_inline_message_text.rs | 98 - src/requests/all/edit_message_caption.rs | 91 - .../all/edit_message_live_location.rs | 91 - src/requests/all/edit_message_media.rs | 85 - src/requests/all/edit_message_reply_markup.rs | 69 - src/requests/all/edit_message_text.rs | 107 - src/requests/all/export_chat_invite_link.rs | 65 - src/requests/all/forward_message.rs | 81 - src/requests/all/get_chat.rs | 50 - src/requests/all/get_chat_administrators.rs | 53 - src/requests/all/get_chat_member.rs | 55 - src/requests/all/get_chat_members_count.rs | 48 - src/requests/all/get_file.rs | 62 - src/requests/all/get_game_high_scores.rs | 63 - src/requests/all/get_me.rs | 33 - src/requests/all/get_my_commands.rs | 33 - src/requests/all/get_sticker_set.rs | 47 - src/requests/all/get_updates.rs | 122 -- src/requests/all/get_user_profile_photos.rs | 58 - src/requests/all/get_webhook_info.rs | 38 - src/requests/all/kick_chat_member.rs | 72 - src/requests/all/leave_chat.rs | 48 - src/requests/all/mod.rs | 152 -- src/requests/all/pin_chat_message.rs | 69 - src/requests/all/promote_chat_member.rs | 134 -- src/requests/all/restrict_chat_member.rs | 76 - src/requests/all/send_animation.rs | 193 -- src/requests/all/send_audio.rs | 206 -- src/requests/all/send_chat_action.rs | 105 - src/requests/all/send_contact.rs | 129 -- src/requests/all/send_dice.rs | 94 - src/requests/all/send_document.rs | 163 -- src/requests/all/send_game.rs | 92 - src/requests/all/send_invoice.rs | 299 --- src/requests/all/send_location.rs | 110 -- src/requests/all/send_media_group.rs | 85 - src/requests/all/send_message.rs | 121 -- src/requests/all/send_photo.rs | 140 -- src/requests/all/send_poll.rs | 217 -- src/requests/all/send_sticker.rs | 117 -- src/requests/all/send_venue.rs | 159 -- src/requests/all/send_video.rs | 207 -- src/requests/all/send_video_note.rs | 160 -- src/requests/all/send_voice.rs | 159 -- .../set_chat_administrator_custom_title.rs | 75 - src/requests/all/set_chat_description.rs | 62 - src/requests/all/set_chat_permissions.rs | 58 - src/requests/all/set_chat_photo.rs | 58 - src/requests/all/set_chat_sticker_set.rs | 64 - src/requests/all/set_chat_title.rs | 63 - src/requests/all/set_game_score.rs | 89 - src/requests/all/set_my_commands.rs | 50 - .../all/set_sticker_position_in_set.rs | 56 - src/requests/all/set_sticker_set_thumb.rs | 74 - src/requests/all/set_webhook.rs | 114 -- .../all/stop_inline_message_live_location.rs | 62 - .../all/stop_message_live_location.rs | 70 - src/requests/all/stop_poll.rs | 66 - src/requests/all/unban_chat_member.rs | 58 - src/requests/all/unpin_chat_message.rs | 52 - src/requests/all/upload_sticker_file.rs | 55 - src/requests/form_builder.rs | 156 -- src/requests/mod.rs | 37 - src/requests/utils.rs | 31 - src/types/allowed_update.rs | 14 - src/types/animation.rs | 165 -- src/types/audio.rs | 152 -- src/types/bot_command.rs | 42 - src/types/callback_game.rs | 13 - src/types/callback_query.rs | 158 -- src/types/chat.rs | 353 ---- src/types/chat_action.rs | 17 - src/types/chat_id.rs | 39 - src/types/chat_member.rs | 262 --- src/types/chat_permissions.rs | 48 - src/types/chat_photo.rs | 82 - src/types/chosen_inline_result.rs | 85 - src/types/contact.rs | 79 - src/types/dice.rs | 38 - src/types/dice_emoji.rs | 16 - src/types/document.rs | 92 - src/types/encrypted_credentials.rs | 94 - src/types/encrypted_passport_element.rs | 794 -------- src/types/file.rs | 75 - src/types/force_reply.rs | 41 - src/types/game.rs | 106 - src/types/game_high_score.rs | 40 - src/types/inline_keyboard_button.rs | 135 -- src/types/inline_keyboard_markup.rs | 109 - src/types/inline_query.rs | 74 - src/types/inline_query_result.rs | 102 - src/types/inline_query_result_article.rs | 128 -- src/types/inline_query_result_audio.rs | 133 -- src/types/inline_query_result_cached_audio.rs | 96 - .../inline_query_result_cached_document.rs | 121 -- src/types/inline_query_result_cached_gif.rs | 109 - .../inline_query_result_cached_mpeg4_gif.rs | 101 - src/types/inline_query_result_cached_photo.rs | 120 -- .../inline_query_result_cached_sticker.rs | 70 - src/types/inline_query_result_cached_video.rs | 121 -- src/types/inline_query_result_cached_voice.rs | 109 - src/types/inline_query_result_contact.rs | 140 -- src/types/inline_query_result_document.rs | 138 -- src/types/inline_query_result_game.rs | 55 - src/types/inline_query_result_gif.rs | 148 -- src/types/inline_query_result_location.rs | 128 -- src/types/inline_query_result_mpeg4_gif.rs | 149 -- src/types/inline_query_result_photo.rs | 152 -- src/types/inline_query_result_venue.rs | 157 -- src/types/inline_query_result_video.rs | 182 -- src/types/inline_query_result_voice.rs | 119 -- src/types/input_file.rs | 101 - src/types/input_media.rs | 511 ----- src/types/input_message_content.rs | 318 --- src/types/invoice.rs | 91 - src/types/keyboard_button.rs | 156 -- src/types/keyboard_button_poll_type.rs | 24 - src/types/label_price.rs | 56 - src/types/location.rs | 28 - src/types/login_url.rs | 61 - src/types/mask_position.rs | 58 - src/types/me.rs | 57 - src/types/message.rs | 1753 ----------------- src/types/message_entity.rs | 162 -- src/types/mod.rs | 194 -- src/types/non_telegram_types/country_code.rs | 254 --- src/types/non_telegram_types/currency.rs | 89 - src/types/non_telegram_types/mime_wrapper.rs | 46 - src/types/non_telegram_types/mod.rs | 7 - src/types/order_info.rs | 72 - src/types/parse_mode.rs | 189 -- src/types/passport_data.rs | 40 - src/types/passport_element_error.rs | 558 ------ src/types/passport_file.rs | 66 - src/types/photo_size.rs | 94 - src/types/poll.rs | 250 --- src/types/poll_answer.rs | 48 - src/types/poll_type.rs | 9 - src/types/pre_checkout_query.rs | 108 - src/types/reply_keyboard_markup.rs | 98 - src/types/reply_keyboard_remove.rs | 52 - src/types/reply_markup.rs | 27 - src/types/response_parameters.rs | 43 - src/types/send_invoice.rs | 229 --- src/types/shipping_address.rs | 100 - src/types/shipping_option.rs | 71 - src/types/shipping_query.rs | 63 - src/types/sticker.rs | 135 -- src/types/sticker_set.rs | 89 - src/types/sticker_type.rs | 28 - src/types/successful_payment.rs | 112 -- src/types/target_message.rs | 17 - src/types/unit_false.rs | 76 - src/types/unit_true.rs | 79 - src/types/update.rs | 321 --- src/types/user.rs | 132 -- src/types/user_profile_photos.rs | 40 - src/types/venue.rs | 74 - src/types/video.rs | 108 - src/types/video_note.rs | 89 - src/types/voice.rs | 74 - src/types/webhook_info.rs | 98 - src/utils/client_from_env.rs | 26 - src/utils/html.rs | 4 +- src/utils/markdown.rs | 5 +- src/utils/mod.rs | 3 +- 209 files changed, 326 insertions(+), 23551 deletions(-) delete mode 100644 src/bot/api.rs delete mode 100644 src/bot/download.rs delete mode 100644 src/bot/mod.rs delete mode 100644 src/errors.rs delete mode 100644 src/net/download.rs delete mode 100644 src/net/mod.rs delete mode 100644 src/net/request.rs delete mode 100644 src/net/telegram_response.rs delete mode 100644 src/requests/all/add_sticker_to_set.rs delete mode 100644 src/requests/all/answer_callback_query.rs delete mode 100644 src/requests/all/answer_inline_query.rs delete mode 100644 src/requests/all/answer_pre_checkout_query.rs delete mode 100644 src/requests/all/answer_shipping_query.rs delete mode 100644 src/requests/all/create_new_sticker_set.rs delete mode 100644 src/requests/all/delete_chat_photo.rs delete mode 100644 src/requests/all/delete_chat_sticker_set.rs delete mode 100644 src/requests/all/delete_message.rs delete mode 100644 src/requests/all/delete_sticker_from_set.rs delete mode 100644 src/requests/all/delete_webhook.rs delete mode 100644 src/requests/all/edit_inline_message_caption.rs delete mode 100644 src/requests/all/edit_inline_message_live_location.rs delete mode 100644 src/requests/all/edit_inline_message_media.rs delete mode 100644 src/requests/all/edit_inline_message_reply_markup.rs delete mode 100644 src/requests/all/edit_inline_message_text.rs delete mode 100644 src/requests/all/edit_message_caption.rs delete mode 100644 src/requests/all/edit_message_live_location.rs delete mode 100644 src/requests/all/edit_message_media.rs delete mode 100644 src/requests/all/edit_message_reply_markup.rs delete mode 100644 src/requests/all/edit_message_text.rs delete mode 100644 src/requests/all/export_chat_invite_link.rs delete mode 100644 src/requests/all/forward_message.rs delete mode 100644 src/requests/all/get_chat.rs delete mode 100644 src/requests/all/get_chat_administrators.rs delete mode 100644 src/requests/all/get_chat_member.rs delete mode 100644 src/requests/all/get_chat_members_count.rs delete mode 100644 src/requests/all/get_file.rs delete mode 100644 src/requests/all/get_game_high_scores.rs delete mode 100644 src/requests/all/get_me.rs delete mode 100644 src/requests/all/get_my_commands.rs delete mode 100644 src/requests/all/get_sticker_set.rs delete mode 100644 src/requests/all/get_updates.rs delete mode 100644 src/requests/all/get_user_profile_photos.rs delete mode 100644 src/requests/all/get_webhook_info.rs delete mode 100644 src/requests/all/kick_chat_member.rs delete mode 100644 src/requests/all/leave_chat.rs delete mode 100644 src/requests/all/mod.rs delete mode 100644 src/requests/all/pin_chat_message.rs delete mode 100644 src/requests/all/promote_chat_member.rs delete mode 100644 src/requests/all/restrict_chat_member.rs delete mode 100644 src/requests/all/send_animation.rs delete mode 100644 src/requests/all/send_audio.rs delete mode 100644 src/requests/all/send_chat_action.rs delete mode 100644 src/requests/all/send_contact.rs delete mode 100644 src/requests/all/send_dice.rs delete mode 100644 src/requests/all/send_document.rs delete mode 100644 src/requests/all/send_game.rs delete mode 100644 src/requests/all/send_invoice.rs delete mode 100644 src/requests/all/send_location.rs delete mode 100644 src/requests/all/send_media_group.rs delete mode 100644 src/requests/all/send_message.rs delete mode 100644 src/requests/all/send_photo.rs delete mode 100644 src/requests/all/send_poll.rs delete mode 100644 src/requests/all/send_sticker.rs delete mode 100644 src/requests/all/send_venue.rs delete mode 100644 src/requests/all/send_video.rs delete mode 100644 src/requests/all/send_video_note.rs delete mode 100644 src/requests/all/send_voice.rs delete mode 100644 src/requests/all/set_chat_administrator_custom_title.rs delete mode 100644 src/requests/all/set_chat_description.rs delete mode 100644 src/requests/all/set_chat_permissions.rs delete mode 100644 src/requests/all/set_chat_photo.rs delete mode 100644 src/requests/all/set_chat_sticker_set.rs delete mode 100644 src/requests/all/set_chat_title.rs delete mode 100644 src/requests/all/set_game_score.rs delete mode 100644 src/requests/all/set_my_commands.rs delete mode 100644 src/requests/all/set_sticker_position_in_set.rs delete mode 100644 src/requests/all/set_sticker_set_thumb.rs delete mode 100644 src/requests/all/set_webhook.rs delete mode 100644 src/requests/all/stop_inline_message_live_location.rs delete mode 100644 src/requests/all/stop_message_live_location.rs delete mode 100644 src/requests/all/stop_poll.rs delete mode 100644 src/requests/all/unban_chat_member.rs delete mode 100644 src/requests/all/unpin_chat_message.rs delete mode 100644 src/requests/all/upload_sticker_file.rs delete mode 100644 src/requests/form_builder.rs delete mode 100644 src/requests/mod.rs delete mode 100644 src/requests/utils.rs delete mode 100644 src/types/allowed_update.rs delete mode 100644 src/types/animation.rs delete mode 100644 src/types/audio.rs delete mode 100644 src/types/bot_command.rs delete mode 100644 src/types/callback_game.rs delete mode 100644 src/types/callback_query.rs delete mode 100644 src/types/chat.rs delete mode 100644 src/types/chat_action.rs delete mode 100644 src/types/chat_id.rs delete mode 100644 src/types/chat_member.rs delete mode 100644 src/types/chat_permissions.rs delete mode 100644 src/types/chat_photo.rs delete mode 100644 src/types/chosen_inline_result.rs delete mode 100644 src/types/contact.rs delete mode 100644 src/types/dice.rs delete mode 100644 src/types/dice_emoji.rs delete mode 100644 src/types/document.rs delete mode 100644 src/types/encrypted_credentials.rs delete mode 100644 src/types/encrypted_passport_element.rs delete mode 100644 src/types/file.rs delete mode 100644 src/types/force_reply.rs delete mode 100644 src/types/game.rs delete mode 100644 src/types/game_high_score.rs delete mode 100644 src/types/inline_keyboard_button.rs delete mode 100644 src/types/inline_keyboard_markup.rs delete mode 100644 src/types/inline_query.rs delete mode 100644 src/types/inline_query_result.rs delete mode 100644 src/types/inline_query_result_article.rs delete mode 100644 src/types/inline_query_result_audio.rs delete mode 100644 src/types/inline_query_result_cached_audio.rs delete mode 100644 src/types/inline_query_result_cached_document.rs delete mode 100644 src/types/inline_query_result_cached_gif.rs delete mode 100644 src/types/inline_query_result_cached_mpeg4_gif.rs delete mode 100644 src/types/inline_query_result_cached_photo.rs delete mode 100644 src/types/inline_query_result_cached_sticker.rs delete mode 100644 src/types/inline_query_result_cached_video.rs delete mode 100644 src/types/inline_query_result_cached_voice.rs delete mode 100644 src/types/inline_query_result_contact.rs delete mode 100644 src/types/inline_query_result_document.rs delete mode 100644 src/types/inline_query_result_game.rs delete mode 100644 src/types/inline_query_result_gif.rs delete mode 100644 src/types/inline_query_result_location.rs delete mode 100644 src/types/inline_query_result_mpeg4_gif.rs delete mode 100644 src/types/inline_query_result_photo.rs delete mode 100644 src/types/inline_query_result_venue.rs delete mode 100644 src/types/inline_query_result_video.rs delete mode 100644 src/types/inline_query_result_voice.rs delete mode 100644 src/types/input_file.rs delete mode 100644 src/types/input_media.rs delete mode 100644 src/types/input_message_content.rs delete mode 100644 src/types/invoice.rs delete mode 100644 src/types/keyboard_button.rs delete mode 100644 src/types/keyboard_button_poll_type.rs delete mode 100644 src/types/label_price.rs delete mode 100644 src/types/location.rs delete mode 100644 src/types/login_url.rs delete mode 100644 src/types/mask_position.rs delete mode 100644 src/types/me.rs delete mode 100644 src/types/message.rs delete mode 100644 src/types/message_entity.rs delete mode 100644 src/types/mod.rs delete mode 100644 src/types/non_telegram_types/country_code.rs delete mode 100644 src/types/non_telegram_types/currency.rs delete mode 100644 src/types/non_telegram_types/mime_wrapper.rs delete mode 100644 src/types/non_telegram_types/mod.rs delete mode 100644 src/types/order_info.rs delete mode 100644 src/types/parse_mode.rs delete mode 100644 src/types/passport_data.rs delete mode 100644 src/types/passport_element_error.rs delete mode 100644 src/types/passport_file.rs delete mode 100644 src/types/photo_size.rs delete mode 100644 src/types/poll.rs delete mode 100644 src/types/poll_answer.rs delete mode 100644 src/types/poll_type.rs delete mode 100644 src/types/pre_checkout_query.rs delete mode 100644 src/types/reply_keyboard_markup.rs delete mode 100644 src/types/reply_keyboard_remove.rs delete mode 100644 src/types/reply_markup.rs delete mode 100644 src/types/response_parameters.rs delete mode 100644 src/types/send_invoice.rs delete mode 100644 src/types/shipping_address.rs delete mode 100644 src/types/shipping_option.rs delete mode 100644 src/types/shipping_query.rs delete mode 100644 src/types/sticker.rs delete mode 100644 src/types/sticker_set.rs delete mode 100644 src/types/sticker_type.rs delete mode 100644 src/types/successful_payment.rs delete mode 100644 src/types/target_message.rs delete mode 100644 src/types/unit_false.rs delete mode 100644 src/types/unit_true.rs delete mode 100644 src/types/update.rs delete mode 100644 src/types/user.rs delete mode 100644 src/types/user_profile_photos.rs delete mode 100644 src/types/venue.rs delete mode 100644 src/types/video.rs delete mode 100644 src/types/video_note.rs delete mode 100644 src/types/voice.rs delete mode 100644 src/types/webhook_info.rs delete mode 100644 src/utils/client_from_env.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index d4e583b3..6f1a9643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] ### Added + - Integrate [teloxide-core]. - Allow arbitrary error types to be returned from (sub)transitions ([issue 242](https://github.com/teloxide/teloxide/issues/242)). - The `respond` function, a shortcut for `ResponseResult::Ok(())`. - The `sqlite-storage` feature -- enables SQLite support. +### Deprecated + + - `UpdateWithCx::answer_str` + +### Fixed + + - Hide `SubtransitionOutputType` from the docs. + ### Changed - Allow `bot_name` be `N`, where `N: Into + ...` in `commands_repl` & `commands_repl_with_listener`. - 'Edit methods' (namely `edit_message_live_location`, `stop_message_live_location`, `edit_message_text`, diff --git a/Cargo.toml b/Cargo.toml index fce35c78..10f575ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ macros = ["teloxide-macros"] nightly = [] # currently used for `README.md` tests and building docs for `docsrs` to add `This is supported on feature="..." only.` [dependencies] -teloxide-core = "0.1" +teloxide-core = { git = "https://github.com/teloxide/teloxide-core.git", rev = "b465da5f1650893cc033d995343858371505eaf1", features = ["full"] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } diff --git a/src/bot/api.rs b/src/bot/api.rs deleted file mode 100644 index 10df2dd5..00000000 --- a/src/bot/api.rs +++ /dev/null @@ -1,1733 +0,0 @@ -use crate::{ - requests::{ - AddStickerToSet, AnswerCallbackQuery, AnswerInlineQuery, AnswerPreCheckoutQuery, - AnswerShippingQuery, CreateNewStickerSet, DeleteChatPhoto, DeleteChatStickerSet, - DeleteMessage, DeleteStickerFromSet, DeleteWebhook, EditInlineMessageCaption, - EditInlineMessageLiveLocation, EditInlineMessageMedia, EditInlineMessageReplyMarkup, - EditInlineMessageText, EditMessageCaption, EditMessageLiveLocation, EditMessageMedia, - EditMessageReplyMarkup, EditMessageText, ExportChatInviteLink, ForwardMessage, GetChat, - GetChatAdministrators, GetChatMember, GetChatMembersCount, GetFile, GetGameHighScores, - GetMe, GetMyCommands, GetStickerSet, GetUpdates, GetUserProfilePhotos, GetWebhookInfo, - KickChatMember, LeaveChat, PinChatMessage, PromoteChatMember, RestrictChatMember, - SendAnimation, SendAudio, SendChatAction, SendChatActionKind, SendContact, SendDice, - SendDocument, SendGame, SendInvoice, SendLocation, SendMediaGroup, SendMessage, SendPhoto, - SendPoll, SendSticker, SendVenue, SendVideo, SendVideoNote, SendVoice, - SetChatAdministratorCustomTitle, SetChatDescription, SetChatPermissions, SetChatPhoto, - SetChatStickerSet, SetChatTitle, SetGameScore, SetMyCommands, SetStickerPositionInSet, - SetStickerSetThumb, SetWebhook, StopInlineMessageLiveLocation, StopMessageLiveLocation, - StopPoll, UnbanChatMember, UnpinChatMessage, UploadStickerFile, - }, - types::{ - BotCommand, ChatId, ChatPermissions, InlineQueryResult, InputFile, InputMedia, - LabeledPrice, ParseMode, StickerType, TargetMessage, - }, - Bot, -}; - -impl Bot { - /// Use this method to receive incoming updates using long polling ([wiki]). - /// - /// **Notes:** - /// 1. This method will not work if an outgoing webhook is set up. - /// 2. In order to avoid getting duplicate updates, - /// recalculate offset after each server response. - /// - /// [The official docs](https://core.telegram.org/bots/api#getupdates). - /// - /// [wiki]: https://en.wikipedia.org/wiki/Push_technology#Long_polling - pub fn get_updates(&self) -> GetUpdates { - GetUpdates::new(self.clone()) - } - - /// 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. - /// - /// If you'd like to make sure that the Webhook request comes from Telegram, - /// we recommend using a secret path in the URL, e.g. - /// `https://www.example.com/`. Since nobody else knows your bot‘s - /// token, you can be pretty sure it’s us. - /// - /// [The official docs](https://core.telegram.org/bots/api#setwebhook). - /// - /// # Params - /// - `url`: HTTPS url to send updates to. - /// - /// Use an empty string to remove webhook integration. - /// - /// [`Update`]: crate::types::Update - pub fn set_webhook(&self, url: U) -> SetWebhook - where - U: Into, - { - SetWebhook::new(self.clone(), url) - } - - /// Use this method to remove webhook integration if you decide to switch - /// back to [Bot::get_updates]. - /// - /// [The official docs](https://core.telegram.org/bots/api#deletewebhook). - /// - /// [Bot::get_updates]: crate::Bot::get_updates - pub fn delete_webhook(&self) -> DeleteWebhook { - DeleteWebhook::new(self.clone()) - } - - /// Use this method to get current webhook status. - /// - /// If the bot is using [`Bot::get_updates`], will return an object with the - /// url field empty. - /// - /// [The official docs](https://core.telegram.org/bots/api#getwebhookinfo). - /// - /// [`Bot::get_updates`]: crate::Bot::get_updates - pub fn get_webhook_info(&self) -> GetWebhookInfo { - GetWebhookInfo::new(self.clone()) - } - - /// A simple method for testing your bot's auth token. Requires no - /// parameters. - /// - /// [The official docs](https://core.telegram.org/bots/api#getme). - pub fn get_me(&self) -> GetMe { - GetMe::new(self.clone()) - } - - /// Use this method to send text messages. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendmessage). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `text`: Text of the message to be sent. - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_message(&self, chat_id: C, text: T) -> SendMessage - where - C: Into, - T: Into, - { - self.with_default_parse_mode_if_specified( - SendMessage::new(self.clone(), chat_id, text), - SendMessage::parse_mode, - ) - } - - /// Use this method to forward messages of any kind. - /// - /// [`The official docs`](https://core.telegram.org/bots/api#forwardmessage). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `from_chat_id`: Unique identifier for the chat where the original - /// message was sent (or channel username in the format - /// `@channelusername`). - /// - `message_id`: Message identifier in the chat specified in - /// [`from_chat_id`]. - /// - /// [`from_chat_id`]: ForwardMessage::from_chat_id - pub fn forward_message( - &self, - chat_id: C, - from_chat_id: F, - message_id: i32, - ) -> ForwardMessage - where - C: Into, - F: Into, - { - ForwardMessage::new(self.clone(), chat_id, from_chat_id, message_id) - } - - /// Use this method to send photos. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendphoto). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `photo`: Pass [`InputFile::FileId`] to send a photo that exists on - /// the Telegram servers (recommended), pass an [`InputFile::Url`] for - /// Telegram to get a photo from the Internet (5MB max.), pass - /// [`InputFile::File`] to upload a picture from the file system or - /// [`InputFile::Memory`] to upload a photo from memory (10MB max. - /// each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_photo(&self, chat_id: C, photo: InputFile) -> SendPhoto - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendPhoto::new(self.clone(), chat_id, photo), - SendPhoto::parse_mode, - ) - } - - /// Use this method to send audio files - /// - /// [The official docs](https://core.telegram.org/bots/api#sendaudio). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `audio`: Pass [`InputFile::FileId`] to send an audio file that - /// exists on the Telegram servers (recommended), pass an - /// [`InputFile::Url`] for Telegram to get a file from the Internet - /// (20MB max.), pass [`InputFile::File`] to upload a file from the file - /// system or [`InputFile::Memory`] to upload a file from memory (50MB - /// max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_audio(&self, chat_id: C, audio: InputFile) -> SendAudio - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendAudio::new(self.clone(), chat_id, audio), - SendAudio::parse_mode, - ) - } - - /// Use this method to send general files. - /// - /// [The official docs](https://core.telegram.org/bots/api#senddocument). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `document`: Pass [`InputFile::FileId`] to send a file that exists on - /// the Telegram servers (recommended), pass an [`InputFile::Url`] for - /// Telegram to get a file from the Internet (20MB max.), pass - /// [`InputFile::File`] to upload a file from the file system or - /// [`InputFile::Memory`] to upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_document(&self, chat_id: C, document: InputFile) -> SendDocument - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendDocument::new(self.clone(), chat_id, document), - SendDocument::parse_mode, - ) - } - - /// Use this method to send video files, Telegram clients support mp4 videos - /// (other formats may be sent as Document). - /// - /// [The official docs](https://core.telegram.org/bots/api#sendvideo). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `video`: Pass [`InputFile::FileId`] to send a file that exists on - /// the Telegram servers (recommended), pass an [`InputFile::Url`] for - /// Telegram to get a file from the Internet (20MB max.), pass - /// [`InputFile::File`] to upload a file from the file system or - /// [`InputFile::Memory`] to upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_video(&self, chat_id: C, video: InputFile) -> SendVideo - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendVideo::new(self.clone(), chat_id, video), - SendVideo::parse_mode, - ) - } - - /// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video - /// without sound). - /// - /// [The official docs](https://core.telegram.org/bots/api#sendanimation). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `animation`: Pass [`InputFile::FileId`] to send a file that exists - /// on the Telegram servers (recommended), pass an [`InputFile::Url`] - /// for Telegram to get a file from the Internet (20MB max.), pass - /// [`InputFile::File`] to upload a file from the file system or - /// [`InputFile::Memory`] to upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_animation(&self, chat_id: C, animation: InputFile) -> SendAnimation - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendAnimation::new(self.clone(), chat_id, animation), - SendAnimation::parse_mode, - ) - } - - /// 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`]). - /// - /// [The official docs](https://core.telegram.org/bots/api#sendvoice). - /// - /// [`Audio`]: crate::types::Audio - /// [`Document`]: crate::types::Document - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `voice`: Pass [`InputFile::FileId`] to send a file that exists on - /// the Telegram servers (recommended), pass an [`InputFile::Url`] for - /// Telegram to get a file from the Internet (20MB max.), pass - /// [`InputFile::File`] to upload a file from the file system or - /// [`InputFile::Memory`] to upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn send_voice(&self, chat_id: C, voice: InputFile) -> SendVoice - where - C: Into, - { - self.with_default_parse_mode_if_specified( - SendVoice::new(self.clone(), chat_id, voice), - SendVoice::parse_mode, - ) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendvideonote). - /// - /// [v.4.0]: https://telegram.org/blog/video-messages-and-telescope - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `video_note`: Pass [`InputFile::FileId`] to send a file that exists - /// on the Telegram servers (recommended), pass an [`InputFile::Url`] - /// for Telegram to get a file from the Internet (20MB max.), pass - /// [`InputFile::File`] to upload a file from the file system or - /// [`InputFile::Memory`] to upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - - pub fn send_video_note(&self, chat_id: C, video_note: InputFile) -> SendVideoNote - where - C: Into, - { - SendVideoNote::new(self.clone(), chat_id, video_note) - } - - /// Use this method to send a group of photos or videos as an album. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendmediagroup). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `media`: A vector of photos and videos as [`InputMedia`] to be sent, - /// must include 2–10 items. - pub fn send_media_group(&self, chat_id: C, media: M) -> SendMediaGroup - where - C: Into, - M: Into>, - { - SendMediaGroup::new(self.clone(), chat_id, media) - } - - /// Use this method to send point on the map. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendlocation). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `latitude`: Latitude of the location. - /// - `longitude`: Latitude of the location. - pub fn send_location(&self, chat_id: C, latitude: f32, longitude: f32) -> SendLocation - where - C: Into, - { - SendLocation::new(self.clone(), chat_id, latitude, longitude) - } - - /// 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, - /// the edited [`Message`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). - /// - /// [`Message`]: crate::types::Message - /// - /// # Params - /// - `latitude`: Latitude of new location. - /// - `longitude`: Longitude of new location. - pub fn edit_message_live_location( - &self, - chat_id: C, - message_id: i32, - latitude: f32, - longitude: f32, - ) -> EditMessageLiveLocation - where - C: Into, - { - EditMessageLiveLocation::new(self.clone(), chat_id, message_id, latitude, longitude) - } - - /// Use this method to edit live location messages sent via the bot. - /// - /// A location can be edited until its live_period expires or editing is - /// explicitly disabled by a call to stopMessageLiveLocation. On success, - /// [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). - /// - /// [`True`]: crate::types::True - /// - /// # Params - /// - `latitude`: Latitude of new location. - /// - `longitude`: Longitude of new location. - pub fn edit_inline_message_live_location( - &self, - inline_message_id: I, - latitude: f32, - longitude: f32, - ) -> EditInlineMessageLiveLocation - where - I: Into, - { - EditInlineMessageLiveLocation::new(self.clone(), inline_message_id, latitude, longitude) - } - - /// Use this method to stop updating a live location message before - /// `live_period` expires. - /// - /// On success, the sent [`Message`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). - /// - /// [`Message`]: crate::types::Message - pub fn stop_message_live_location( - &self, - chat_id: C, - message_id: i32, - ) -> StopMessageLiveLocation - where - C: Into, - { - StopMessageLiveLocation::new(self.clone(), chat_id, message_id) - } - - /// Use this method to stop updating a live location message (sent via the - /// bot) before `live_period` expires. - /// - /// On success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). - /// - /// [`True`]: crate::types::True - pub fn stop_inline_message_live_location( - &self, - inline_message_id: I, - ) -> StopInlineMessageLiveLocation - where - I: Into, - { - StopInlineMessageLiveLocation::new(self.clone(), inline_message_id) - } - - /// Use this method to send information about a venue. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendvenue). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `latitude`: Latitude of the venue. - /// - `longitude`: Longitude of the venue. - /// - `title`: Name of the venue. - /// - `address`: Address of the venue. - pub fn send_venue( - &self, - chat_id: C, - latitude: f32, - longitude: f32, - title: T, - address: A, - ) -> SendVenue - where - C: Into, - T: Into, - A: Into, - { - SendVenue::new(self.clone(), chat_id, latitude, longitude, title, address) - } - - /// Use this method to send phone contacts. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendcontact). - /// - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `phone_number`: Contact's phone number. - /// - `first_name`: Contact's first name. - pub fn send_contact(&self, chat_id: C, phone_number: P, first_name: F) -> SendContact - where - C: Into, - P: Into, - F: Into, - { - SendContact::new(self.clone(), chat_id, phone_number, first_name) - } - - /// Use this method to send a native poll. A native poll can't be sent to a - /// private chat. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendpoll). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `question`: Poll question, 1-255 characters. - /// - `options`: List of answer options, 2-10 strings 1-100 characters - /// each. - /// - /// # Notes - /// Uses [a default parse mode] ([`SendPoll::explanation_parse_mode`]) if - /// specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - /// [`SendPoll::explanation_parse_mode`]: - /// [`SendPoll::explanation_parse_mode`]: - /// crate::types::SendPoll::explanation_parse_mode - pub fn send_poll(&self, chat_id: C, question: Q, options: O) -> SendPoll - where - C: Into, - Q: Into, - O: Into>, - { - self.with_default_parse_mode_if_specified( - SendPoll::new(self.clone(), chat_id, question, options), - SendPoll::explanation_parse_mode, - ) - } - - /// 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). - /// - /// ## Note - /// Example: The [ImageBot] needs some time to process a request and upload - /// the image. Instead of sending a text message along the lines of - /// “Retrieving image, please wait…”, the bot may use - /// [`Bot::send_chat_action`] with `action = upload_photo`. The user - /// will see a `sending photo` status for the bot. - /// - /// We only recommend using this method when a response from the bot will - /// take a **noticeable** amount of time to arrive. - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - /// [ImageBot]: https://t.me/imagebot - /// [`Bot::send_chat_action`]: crate::Bot::send_chat_action - pub fn send_chat_action(&self, chat_id: C, action: SendChatActionKind) -> SendChatAction - where - C: Into, - { - SendChatAction::new(self.clone(), chat_id, action) - } - - /// Use this method to get a list of profile pictures for a user. - /// - /// [The official docs](https://core.telegram.org/bots/api#getuserprofilephotos). - /// - /// # Params - /// - `user_id`: Unique identifier of the target user. - pub fn get_user_profile_photos(&self, user_id: i32) -> GetUserProfilePhotos { - GetUserProfilePhotos::new(self.clone(), user_id) - } - - /// 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. - /// - /// The file can then be downloaded via the link - /// `https://api.telegram.org/file/bot/`, where `` - /// 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 [`GetFile`] again. - /// - /// **Note**: This function may not preserve the original file name and MIME - /// type. You should save the file's MIME type and name (if available) when - /// the [`File`] object is received. - /// - /// [The official docs](https://core.telegram.org/bots/api#getfile). - /// - /// # Params - /// - `file_id`: File identifier to get info about. - /// - /// [`File`]: crate::types::File - /// [`GetFile`]: self::GetFile - pub fn get_file(&self, file_id: F) -> GetFile - where - F: Into, - { - GetFile::new(self.clone(), file_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#kickchatmember). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - /// - /// [unbanned]: crate::Bot::unban_chat_member - pub fn kick_chat_member(&self, chat_id: C, user_id: i32) -> KickChatMember - where - C: Into, - { - KickChatMember::new(self.clone(), chat_id, user_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#unbanchatmember). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - pub fn unban_chat_member(&self, chat_id: C, user_id: i32) -> UnbanChatMember - where - C: Into, - { - UnbanChatMember::new(self.clone(), chat_id, user_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#restrictchatmember). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - /// - `permissions`: New user permissions. - pub fn restrict_chat_member( - &self, - chat_id: C, - user_id: i32, - permissions: ChatPermissions, - ) -> RestrictChatMember - where - C: Into, - { - RestrictChatMember::new(self.clone(), chat_id, user_id, permissions) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#promotechatmember). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - pub fn promote_chat_member(&self, chat_id: C, user_id: i32) -> PromoteChatMember - where - C: Into, - { - PromoteChatMember::new(self.clone(), chat_id, user_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchatpermissions). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `permissions`: New default chat permissions. - pub fn set_chat_permissions( - &self, - chat_id: C, - permissions: ChatPermissions, - ) -> SetChatPermissions - where - C: Into, - { - SetChatPermissions::new(self.clone(), chat_id, permissions) - } - - /// 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. - /// - /// # 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 [`Bot::export_chat_invite_link`] – after this the - /// link will become available to the bot via the [`Bot::get_chat`] - /// method. If your bot needs to generate a new invite link replacing - /// its previous one, use [`Bot::export_chat_invite_link`] again. - /// - /// [The official docs](https://core.telegram.org/bots/api#exportchatinvitelink). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - /// [`Bot::export_chat_invite_link`]: crate::Bot::export_chat_invite_link - /// [`Bot::get_chat`]: crate::Bot::get_chat - pub fn export_chat_invite_link(&self, chat_id: C) -> ExportChatInviteLink - where - C: Into, - { - ExportChatInviteLink::new(self.clone(), chat_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchatphoto). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `photo`: New chat photo, pass [`InputFile::File`] to upload a file - /// from the file system or [`InputFile::Memory`] to upload a file from - /// memory (10MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn set_chat_photo(&self, chat_id: C, photo: InputFile) -> SetChatPhoto - where - C: Into, - { - SetChatPhoto::new(self.clone(), chat_id, photo) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#deletechatphoto). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn delete_chat_photo(&self, chat_id: C) -> DeleteChatPhoto - where - C: Into, - { - DeleteChatPhoto::new(self.clone(), chat_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchattitle). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `title`: New chat title, 1-255 characters. - pub fn set_chat_title(&self, chat_id: C, title: T) -> SetChatTitle - where - C: Into, - T: Into, - { - SetChatTitle::new(self.clone(), chat_id, title) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchatdescription). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn set_chat_description(&self, chat_id: C) -> SetChatDescription - where - C: Into, - { - SetChatDescription::new(self.clone(), chat_id) - } - - /// 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#pinchatmessage). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `message_id`: Identifier of a message to pin. - pub fn pin_chat_message(&self, chat_id: C, message_id: i32) -> PinChatMessage - where - C: Into, - { - PinChatMessage::new(self.clone(), chat_id, message_id) - } - - /// Use this method to unpin 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#unpinchatmessage). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn unpin_chat_message(&self, chat_id: C) -> UnpinChatMessage - where - C: Into, - { - UnpinChatMessage::new(self.clone(), chat_id) - } - - /// Use this method for your bot to leave a group, supergroup or channel. - /// - /// [The official docs](https://core.telegram.org/bots/api#leavechat). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn leave_chat(&self, chat_id: C) -> LeaveChat - where - C: Into, - { - LeaveChat::new(self.clone(), chat_id) - } - - /// 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.). - /// - /// [The official docs](https://core.telegram.org/bots/api#getchat). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn get_chat(&self, chat_id: C) -> GetChat - where - C: Into, - { - GetChat::new(self.clone(), chat_id) - } - - /// Use this method to get a list of administrators in a chat. - /// - /// If the chat is a group or a supergroup and no administrators were - /// appointed, only the creator will be returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#getchatadministrators). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn get_chat_administrators(&self, chat_id: C) -> GetChatAdministrators - where - C: Into, - { - GetChatAdministrators::new(self.clone(), chat_id) - } - - /// Use this method to get the number of members in a chat. - /// - /// [The official docs](https://core.telegram.org/bots/api#getchatmemberscount). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - pub fn get_chat_members_count(&self, chat_id: C) -> GetChatMembersCount - where - C: Into, - { - GetChatMembersCount::new(self.clone(), chat_id) - } - - /// Use this method to get information about a member of a chat. - /// - /// [The official docs](https://core.telegram.org/bots/api#getchatmember). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup or channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - pub fn get_chat_member(&self, chat_id: C, user_id: i32) -> GetChatMember - where - C: Into, - { - GetChatMember::new(self.clone(), chat_id, user_id) - } - - /// 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 getChat requests to check if the bot can use - /// this method. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchatstickerset). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup (in the format `@supergroupusername`). - /// - `sticker_set_name`: Name of the sticker set to be set as the group - /// sticker set. - pub fn set_chat_sticker_set(&self, chat_id: C, sticker_set_name: S) -> SetChatStickerSet - where - C: Into, - S: Into, - { - SetChatStickerSet::new(self.clone(), chat_id, sticker_set_name) - } - - /// 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 [`Bot::get_chat`] - /// requests to check if the bot can use this method. - /// - /// [The official docs](https://core.telegram.org/bots/api#deletechatstickerset). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target supergroup (in the format `@supergroupusername`). - /// - /// [`Bot::get_chat`]: crate::Bot::get_chat - pub fn delete_chat_sticker_set(&self, chat_id: C) -> DeleteChatStickerSet - where - C: Into, - { - DeleteChatStickerSet::new(self.clone(), chat_id) - } - - /// Use this method to send answers to callback queries sent from [inline - /// keyboards]. - /// - /// The answer will be displayed to the user as a notification at - /// the top of the chat screen or as an alert. - /// - /// [The official docs](https://core.telegram.org/bots/api#answercallbackquery). - /// - /// # Params - /// - `callback_query_id`: Unique identifier for the query to be answered. - /// - /// [inline keyboards]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn answer_callback_query(&self, callback_query_id: C) -> AnswerCallbackQuery - where - C: Into, - { - AnswerCallbackQuery::new(self.clone(), callback_query_id) - } - - /// Use this method to edit text and game messages. - /// - /// On success, the edited [`Message`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagetext). - /// - /// [`Message`]: crate::types::Message - /// - /// # Params - /// - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - /// - `message_id`: Identifier of the message to edit. - /// - `text`: New text of the message. - /// - /// # Notes - /// - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_message_text(&self, chat_id: C, message_id: i32, text: T) -> EditMessageText - where - C: Into, - T: Into, - { - match self.parse_mode { - None => EditMessageText::new(self.clone(), chat_id, message_id, text), - Some(parse_mode) => { - EditMessageText::new(self.clone(), chat_id, message_id, text).parse_mode(parse_mode) - } - } - } - - /// Use this method to edit text and game messages sent via the bot. - /// - /// On success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagetext). - /// - /// [`True`]: crate::types::True - /// - /// # Params - /// - /// - `inline_message_id`: Identifier of the inline message. - /// - `text`: New text of the message. - /// - /// # Notes - /// - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_inline_message_text( - &self, - inline_message_id: I, - text: T, - ) -> EditInlineMessageText - where - I: Into, - T: Into, - { - match self.parse_mode { - None => EditInlineMessageText::new(self.clone(), inline_message_id, text), - Some(parse_mode) => EditInlineMessageText::new(self.clone(), inline_message_id, text) - .parse_mode(parse_mode), - } - } - - /// Use this method to edit captions of messages sent via the bot. - /// - /// On success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). - /// - /// [`True`]: crate::types::True - /// - /// # Notes - /// - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_message_caption(&self, chat_id: C, message_id: i32) -> EditMessageCaption - where - C: Into, - { - match self.parse_mode { - None => EditMessageCaption::new(self.clone(), chat_id, message_id), - Some(parse_mode) => { - EditMessageCaption::new(self.clone(), chat_id, message_id).parse_mode(parse_mode) - } - } - } - - /// Use this method to edit captions of messages sent via the bot. - /// - /// On success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). - /// - /// [`True`]: crate::types::True - /// - /// # Notes - /// Uses [a default parse mode] if specified in [`BotBuilder`]. - /// - /// [a default parse mode]: crate::BotBuilder::parse_mode - /// [`BotBuilder`]: crate::BotBuilder - pub fn edit_inline_message_caption(&self, inline_message_id: I) -> EditInlineMessageCaption - where - I: Into, - { - match self.parse_mode { - None => EditInlineMessageCaption::new(self.clone(), inline_message_id), - Some(parse_mode) => EditInlineMessageCaption::new(self.clone(), inline_message_id) - .parse_mode(parse_mode), - } - } - - /// 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. On success, the edited [`Message`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). - /// - /// [`Message`]: crate::types::Message - pub fn edit_message_media( - &self, - chat_id: C, - message_id: i32, - media: InputMedia, - ) -> EditMessageMedia - where - C: Into, - { - EditMessageMedia::new(self.clone(), chat_id, message_id, media) - } - - /// Use this method to edit animation, audio, document, photo, or video - /// messages sent via the bot. - /// - /// 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 this method is used, new file can't be uploaded. - /// Use previously uploaded file via its `file_id` or specify a URL. On - /// success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). - /// - /// [`True`]: crate::types::True - pub fn edit_inline_message_media( - &self, - inline_message_id: I, - media: InputMedia, - ) -> EditInlineMessageMedia - where - I: Into, - { - EditInlineMessageMedia::new(self.clone(), inline_message_id, media) - } - - /// Use this method to edit only the reply markup of messages. - /// - /// On success, the edited [`Message`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). - /// - /// [`Message`]: crate::types::Message - pub fn edit_message_reply_markup( - &self, - chat_id: C, - message_id: i32, - ) -> EditMessageReplyMarkup - where - C: Into, - { - EditMessageReplyMarkup::new(self.clone(), chat_id, message_id) - } - - /// Use this method to edit only the reply markup of messages sent via the - /// bot. - /// - /// On success, [`True`] is returned. - /// - /// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). - /// - /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True - pub fn edit_inline_message_reply_markup( - &self, - inline_message_id: I, - ) -> EditInlineMessageReplyMarkup - where - I: Into, - { - EditInlineMessageReplyMarkup::new(self.clone(), inline_message_id) - } - - /// Use this method to stop a poll which was sent by the bot. - /// - /// [The official docs](https://core.telegram.org/bots/api#stoppoll). - /// - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - /// - `message_id`: Identifier of the original message with the poll. - pub fn stop_poll(&self, chat_id: C, message_id: i32) -> StopPoll - where - C: Into, - { - StopPoll::new(self.clone(), chat_id, message_id) - } - - /// Use this method to delete a message, including service messages. - /// - /// The limitations are: - /// - A message can only be deleted if it was sent less than 48 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. - /// - /// [The official docs](https://core.telegram.org/bots/api#deletemessage). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - /// - `message_id`: Identifier of the message to delete. - pub fn delete_message(&self, chat_id: C, message_id: i32) -> DeleteMessage - where - C: Into, - { - DeleteMessage::new(self.clone(), chat_id, message_id) - } - - /// Use this method to send static .WEBP or [animated] .TGS stickers. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendsticker). - /// - /// [animated]: https://telegram.org/blog/animated-stickers - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - /// - `sticker`: Pass [`InputFile::FileId`] to send a sticker that exists - /// on the Telegram servers (recommended), pass an [`InputFile::Url`] - /// for Telegram to get a sticker (.WEBP file) from the Internet, pass - /// [`InputFile::File`] to upload a sticker from the file system or - /// [`InputFile::Memory`] to upload a sticker from memory [More info on - /// Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn send_sticker(&self, chat_id: C, sticker: InputFile) -> SendSticker - where - C: Into, - { - SendSticker::new(self.clone(), chat_id, sticker) - } - - /// Use this method to get a sticker set. - /// - /// [The official docs](https://core.telegram.org/bots/api#getstickerset). - /// - /// # Params - /// - `name`: Name of the sticker set. - pub fn get_sticker_set(&self, name: N) -> GetStickerSet - where - N: Into, - { - GetStickerSet::new(self.clone(), name) - } - - /// Use this method to upload a .png file with a sticker for later use in - /// [`Bot::create_new_sticker_set`] and [`Bot::add_sticker_to_set`] methods - /// (can be used multiple times). - /// - /// [The official docs](https://core.telegram.org/bots/api#uploadstickerfile). - /// - /// # Params - /// - `user_id`: User identifier of sticker file owner. - /// - `png_sticker`: **Png** image with the sticker, must be up to 512 - /// kilobytes in size, dimensions must not exceed 512px, and either - /// width or height must be exactly 512px. Pass [`InputFile::File`] to - /// upload a file from the file system or [`InputFile::Memory`] to - /// upload a file from memory. [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn upload_sticker_file(&self, user_id: i32, png_sticker: InputFile) -> UploadStickerFile { - UploadStickerFile::new(self.clone(), user_id, png_sticker) - } - - /// Use this method to create new sticker set owned by a user. The bot will - /// be able to edit the created sticker set. - /// - /// [The official docs](https://core.telegram.org/bots/api#createnewstickerset). - /// - /// # Params - /// - `user_id`: User identifier of created sticker set owner. - /// - `name`: Short name of sticker set, to be used in `t.me/addstickers/` - /// URLs (e.g., animals). Can contain only english letters, digits and - /// underscores. - /// - /// Must begin with a letter, can't contain consecutive underscores and must - /// end in `_by_`. `` is case insensitive. 1-64 - /// characters. - /// - `title`: Sticker set title, 1-64 characters. - pub fn create_new_sticker_set( - &self, - user_id: i32, - name: N, - title: T, - sticker_type: StickerType, - emojis: E, - ) -> CreateNewStickerSet - where - N: Into, - T: Into, - E: Into, - { - CreateNewStickerSet::new(self.clone(), user_id, name, title, sticker_type, emojis) - } - - /// Use this method to add a new sticker to a set created by the bot. - /// - /// [The official docs](https://core.telegram.org/bots/api#addstickertoset). - /// - /// # Params - /// - `user_id`: User identifier of sticker set owner. - /// - `name`: Sticker set name. - /// - `emojis`: One or more emoji corresponding to the sticker. - pub fn add_sticker_to_set( - &self, - user_id: i32, - name: N, - sticker_type: StickerType, - emojis: E, - ) -> AddStickerToSet - where - N: Into, - E: Into, - { - AddStickerToSet::new(self.clone(), user_id, name, sticker_type, emojis) - } - - /// Use this method to move a sticker in a set created by the bot to a - /// specific position. - /// - /// [The official docs](https://core.telegram.org/bots/api#setstickerpositioninset). - /// - /// # Params - /// - `sticker`: File identifier of the sticker. - /// - `position`: New sticker position in the set, zero-based. - pub fn set_sticker_position_in_set( - &self, - sticker: S, - position: i32, - ) -> SetStickerPositionInSet - where - S: Into, - { - SetStickerPositionInSet::new(self.clone(), sticker, position) - } - - /// Use this method to delete a sticker from a set created by the bot. - /// - /// [The official docs](https://core.telegram.org/bots/api#deletestickerfromset). - /// - /// # Params - /// - `sticker`: File identifier of the sticker. - pub fn delete_sticker_from_set(&self, sticker: S) -> DeleteStickerFromSet - where - S: Into, - { - DeleteStickerFromSet::new(self.clone(), sticker) - } - - /// Use this method to send answers to an inline query. - /// - /// No more than **50** results per query are allowed. - /// - /// [The official docs](https://core.telegram.org/bots/api#answerinlinequery). - /// - /// # Params - /// - `inline_query_id`: Unique identifier for the answered query. - /// - `results`: A JSON-serialized array of results for the inline query. - pub fn answer_inline_query(&self, inline_query_id: I, results: R) -> AnswerInlineQuery - where - I: Into, - R: Into>, - { - AnswerInlineQuery::new(self.clone(), inline_query_id, results) - } - - /// Use this method to send invoices. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendinvoice). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target private chat. - /// - `title`: Product name, 1-32 characters. - /// - `description`: Product description, 1-255 characters. - /// - `payload`: Bot-defined invoice payload, 1-128 bytes. This will not - /// be displayed to the user, use for your internal processes. - /// - `provider_token`: Payments provider token, obtained via - /// [@Botfather]. - /// - `start_parameter`: Unique deep-linking parameter that can be used to - /// generate this invoice when used as a start parameter. - /// - `currency`: Three-letter ISO 4217 currency code, see [more on - /// currencies]. - /// - `prices`: Price breakdown, a list of components (e.g. product price, - /// tax, discount, delivery cost, delivery tax, bonus, etc.). - /// - /// [more on currencies]: https://core.telegram.org/bots/payments#supported-currencies - /// [@Botfather]: https://t.me/botfather - #[allow(clippy::too_many_arguments)] - pub fn send_invoice( - &self, - chat_id: i32, - title: T, - description: D, - payload: Pl, - provider_token: Pt, - start_parameter: S, - currency: C, - prices: Pr, - ) -> SendInvoice - where - T: Into, - D: Into, - Pl: Into, - Pt: Into, - S: Into, - C: Into, - Pr: Into>, - { - SendInvoice::new( - self.clone(), - chat_id, - title, - description, - payload, - provider_token, - start_parameter, - currency, - prices, - ) - } - - /// 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. Note: The Bot API must receive an answer - /// within 10 seconds after the pre-checkout query was sent. - /// - /// [The official docs](https://core.telegram.org/bots/api#answerprecheckoutquery). - /// - /// # Params - /// - `shipping_query_id`: Unique identifier for the query to be answered. - /// - `ok`: Specify `true` if delivery to the specified address is - /// possible and `false` if there are any problems (for example, if - /// delivery to the specified address is not possible). - /// - /// [`Update`]: crate::types::Update - pub fn answer_shipping_query(&self, shipping_query_id: S, ok: bool) -> AnswerShippingQuery - where - S: Into, - { - AnswerShippingQuery::new(self.clone(), shipping_query_id, ok) - } - - /// 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. Note: The Bot API must receive an answer - /// within 10 seconds after the pre-checkout query was sent. - /// - /// [The official docs](https://core.telegram.org/bots/api#answerprecheckoutquery). - /// - /// # Params - /// - `pre_checkout_query_id`: Unique identifier for the query to be - /// answered. - /// - `ok`: Specify `true` if everything is alright (goods are available, - /// etc.) and the bot is ready to proceed with the order. Use False if - /// there are any problems. - /// - /// [`Update`]: crate::types::Update - pub fn answer_pre_checkout_query

( - &self, - pre_checkout_query_id: P, - ok: bool, - ) -> AnswerPreCheckoutQuery - where - P: Into, - { - AnswerPreCheckoutQuery::new(self.clone(), pre_checkout_query_id, ok) - } - - /// Use this method to send a game. - /// - /// [The official docs](https://core.telegram.org/bots/api#sendgame). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat. - /// - `game_short_name`: Short name of the game, serves as the unique - /// identifier for the game. Set up your games via [@Botfather]. - /// - /// [@Botfather]: https://t.me/botfather - pub fn send_game(&self, chat_id: i32, game_short_name: G) -> SendGame - where - G: Into, - { - SendGame::new(self.clone(), chat_id, game_short_name) - } - - /// 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`. - /// - /// [The official docs](https://core.telegram.org/bots/api#setgamescore). - /// - /// # Params - /// - `target`: Target message, either chat id and message id or inline - /// message id. - /// - `user_id`: User identifier. - /// - `score`: New score, must be non-negative. - /// - /// [`Message`]: crate::types::Message - /// [`True`]: crate::types::True - pub fn set_game_score(&self, target: T, user_id: i32, score: i32) -> SetGameScore - where - T: Into, - { - SetGameScore::new(self.clone(), target, user_id, score) - } - - /// 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. - /// - /// # Note - /// This method will currently return scores for the target user, plus two - /// of his closest neighbors on each side. Will also return the top - /// three users if the user and his neighbors are not among them. Please - /// note that this behavior is subject to change. - /// - /// [The official docs](https://core.telegram.org/bots/api#getgamehighscores). - /// - /// # Params - /// - `target`: Target message, either chat id and message id or inline - /// message id. - /// - `user_id`: Target user id. - pub fn get_game_high_scores(&self, target: T, user_id: i32) -> GetGameHighScores - where - T: Into, - { - GetGameHighScores::new(self.clone(), target, user_id) - } - - /// Use this method to set a custom title for an administrator in a - /// supergroup promoted by the bot. - /// - /// [The official docs](https://core.telegram.org/bots/api#setchatadministratorcustomtitle). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - /// - `user_id`: Unique identifier of the target user. - /// - `custom_title`: New custom title for the administrator; 0-16 - /// characters, emoji are not allowed. - pub fn set_chat_administrator_custom_title( - &self, - chat_id: C, - user_id: i32, - custom_title: CT, - ) -> SetChatAdministratorCustomTitle - where - C: Into, - CT: Into, - { - SetChatAdministratorCustomTitle::new(self.clone(), chat_id, user_id, custom_title) - } - - /// Use this method to send an animated emoji that will display a random - /// value. - /// - /// [The official docs](https://core.telegram.org/bots/api#senddice). - /// - /// # Params - /// - `chat_id`: Unique identifier for the target chat or username of the - /// target channel (in the format `@channelusername`). - pub fn send_dice(&self, chat_id: C) -> SendDice - where - C: Into, - { - SendDice::new(self.clone(), chat_id) - } - - /// Use this method to get the current list of the bot's commands. - /// - /// [The official docs](https://core.telegram.org/bots/api#getmycommands). - pub fn get_my_commands(&self) -> GetMyCommands { - GetMyCommands::new(self.clone()) - } - - /// Use this method to change the list of the bot's commands. - /// - /// [The official docs](https://core.telegram.org/bots/api#setmycommands). - /// - /// # Params - /// - `commands`: A JSON-serialized list of bot commands to be set as the - /// list of the bot's commands. At most 100 commands can be specified. - pub fn set_my_commands(&self, commands: C) -> SetMyCommands - where - C: Into>, - { - SetMyCommands::new(self.clone(), commands) - } - - /// Use this method to set the thumbnail of a sticker set. Animated - /// thumbnails can be set for animated sticker sets only. - /// - /// [The official docs](https://core.telegram.org/bots/api#setstickersetthumb). - /// - /// # Params - /// - `name`: Sticker set name. - /// - `user_id`: User identifier of the sticker set owner. - pub fn set_sticker_set_thumb(&self, name: S, user_id: i32) -> SetStickerSetThumb - where - S: Into, - { - SetStickerSetThumb::new(self.clone(), name, user_id) - } - - fn with_default_parse_mode_if_specified( - &self, - builder: Builder, - f: fn(Builder, ParseMode) -> Builder, - ) -> Builder { - match self.parse_mode { - None => builder, - Some(parse_mode) => f(builder, parse_mode), - } - } -} diff --git a/src/bot/download.rs b/src/bot/download.rs deleted file mode 100644 index 0dec6543..00000000 --- a/src/bot/download.rs +++ /dev/null @@ -1,67 +0,0 @@ -use tokio::io::AsyncWrite; - -#[cfg(feature = "unstable-stream")] -use ::{bytes::Bytes, tokio::stream::Stream}; - -#[cfg(feature = "unstable-stream")] -use crate::net::download_file_stream; -use crate::{bot::Bot, net::download_file, DownloadError}; - -impl Bot { - /// Download a file from Telegram into `destination`. - /// - /// `path` can be obtained from [`Bot::get_file`]. - /// - /// To download as a stream of chunks, see [`Bot::download_file_stream`]. - /// - /// ## Examples - /// - /// ```no_run - /// use teloxide::types::File as TgFile; - /// use tokio::fs::File; - /// # use teloxide::RequestError; - /// use teloxide::{requests::Request, Bot}; - /// - /// # async fn run() -> Result<(), Box> { - /// let bot = Bot::new("TOKEN"); - /// let mut file = File::create("/home/waffle/Pictures/test.png").await?; - /// - /// let TgFile { file_path, .. } = bot.get_file("*file_id*").send().await?; - /// bot.download_file(&file_path, &mut file).await?; - /// # Ok(()) } - /// ``` - /// - /// [`Bot::get_file`]: crate::Bot::get_file - /// [`Bot::download_file_stream`]: crate::Bot::download_file_stream - pub async fn download_file( - &self, - path: &str, - destination: &mut D, - ) -> Result<(), DownloadError> - where - D: AsyncWrite + Unpin, - { - download_file(&self.client, &self.token, path, destination).await - } - - /// Download a file from Telegram. - /// - /// `path` can be obtained from the [`Bot::get_file`]. - /// - /// To download into [`AsyncWrite`] (e.g. [`tokio::fs::File`]), see - /// [`Bot::download_file`]. - /// - /// [`Bot::get_file`]: crate::bot::Bot::get_file - /// [`AsyncWrite`]: tokio::io::AsyncWrite - /// [`tokio::fs::File`]: tokio::fs::File - /// [`Bot::download_file`]: crate::Bot::download_file - #[cfg(feature = "unstable-stream")] - // FIXME(waffle): use `docsrs` here when issue with combine is resolved - #[cfg_attr(all(teloxide_docsrs, feature = "nightly"), doc(cfg(feature = "unstable-stream")))] - pub async fn download_file_stream( - &self, - path: &str, - ) -> Result>, reqwest::Error> { - download_file_stream(&self.client, &self.token, path).await - } -} diff --git a/src/bot/mod.rs b/src/bot/mod.rs deleted file mode 100644 index b936266f..00000000 --- a/src/bot/mod.rs +++ /dev/null @@ -1,252 +0,0 @@ -use crate::types::ParseMode; -use reqwest::{ - header::{HeaderMap, CONNECTION}, - Client, ClientBuilder, -}; -use std::{sync::Arc, time::Duration}; - -mod api; -mod download; - -pub(crate) const TELOXIDE_TOKEN: &str = "TELOXIDE_TOKEN"; -pub(crate) const TELOXIDE_PROXY: &str = "TELOXIDE_PROXY"; - -/// A requests sender. -/// -/// No need to put it into [`Arc`], because it's already in. -/// -/// [`Arc`]: std::sync::Arc -#[derive(Debug, Clone)] -pub struct Bot { - token: Arc, - client: Client, - parse_mode: Option, -} - -impl Bot { - /// Creates new [`BotBuilder`] see it's [docs] for more - /// - /// [docs]: BotBuilder - #[must_use] - pub fn builder() -> BotBuilder { - BotBuilder::new() - } - - /// Creates a new `Bot` with the `TELOXIDE_TOKEN` & `TELOXIDE_PROXY` - /// environmental variables (a bot's token & a proxy) and the default - /// [`reqwest::Client`]. - /// - /// This function passes the value of `TELOXIDE_PROXY` into - /// [`reqwest::Proxy::all`], if it exists, otherwise returns the default - /// client. - /// - /// # Panics - /// - If cannot get the `TELOXIDE_TOKEN` environmental variable. - /// - If it cannot create [`reqwest::Client`]. - /// - /// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html - /// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all - #[must_use] - pub fn from_env() -> Self { - BotBuilder::new().build() - } - - /// Creates a new `Bot` with the `TELOXIDE_TOKEN` environmental variable (a - /// bot's token) and your [`reqwest::Client`]. - /// - /// # Panics - /// If cannot get the `TELOXIDE_TOKEN` environmental variable. - /// - /// # Caution - /// Your custom client might not be configured correctly to be able to work - /// in long time durations, see [issue 223]. - /// - /// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html - /// [issue 223]: https://github.com/teloxide/teloxide/issues/223 - #[deprecated = "Deprecated in favour of BotBuilder because the later provides more options \ - (notably default parse_mode)"] - pub fn from_env_with_client(client: Client) -> Self { - #[allow(deprecated)] - Self::with_client(&get_env(TELOXIDE_TOKEN), client) - } - - /// Creates a new `Bot` with the specified token and the default - /// [`reqwest::Client`]. - /// - /// # Panics - /// If it cannot create [`reqwest::Client`]. - /// - /// [`reqwest::Client`]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html - #[deprecated = "Deprecated in favour of BotBuilder because the later provides more options \ - (notably default parse_mode)"] - pub fn new(token: S) -> Self - where - S: Into, - { - #[allow(deprecated)] - Self::with_client(token, build_sound_bot()) - } - - /// Creates a new `Bot` with the specified token and your - /// [`reqwest::Client`]. - /// - /// # Caution - /// Your custom client might not be configured correctly to be able to work - /// in long time durations, see [issue 223]. - /// - /// [`reqwest::Client`]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html - /// [issue 223]: https://github.com/teloxide/teloxide/issues/223 - #[deprecated = "Deprecated in favour of BotBuilder because the later provides more options \ - (notably default parse_mode)"] - pub fn with_client(token: S, client: Client) -> Self - where - S: Into, - { - Self { - token: Into::>::into(Into::::into(token)), - client, - parse_mode: None, - } - } -} - -/// Returns a builder with safe settings. -/// -/// By "safe settings" I mean that a client will be able to work in long time -/// durations, see the [issue 223]. -/// -/// [issue 223]: https://github.com/teloxide/teloxide/issues/223 -pub(crate) fn sound_bot() -> ClientBuilder { - let mut headers = HeaderMap::new(); - headers.insert(CONNECTION, "keep-alive".parse().unwrap()); - - let connect_timeout = Duration::from_secs(5); - let timeout = 10; - - ClientBuilder::new() - .connect_timeout(connect_timeout) - .timeout(Duration::from_secs(connect_timeout.as_secs() + timeout + 2)) - .tcp_nodelay(true) - .default_headers(headers) -} - -pub(crate) fn build_sound_bot() -> Client { - sound_bot().build().expect("creating reqwest::Client") -} - -fn get_env(env: &'static str) -> String { - std::env::var(env).unwrap_or_else(|_| panic!("Cannot get the {} env variable", env)) -} - -impl Bot { - // TODO: const fn - pub fn token(&self) -> &str { - &self.token - } - - // TODO: const fn - pub fn client(&self) -> &Client { - &self.client - } -} - -/// A builder of [`Bot`], supporting some extra settings. -/// -/// [`Bot`]: crate::Bot -#[derive(Debug, Default)] -pub struct BotBuilder { - token: Option, - client: Option, - parse_mode: Option, -} - -impl BotBuilder { - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Specifies a custom HTTPS client. Otherwise, the default will be used. - /// - /// # Caution - /// - Your custom client might not be configured correctly to be able to - /// work - /// in long time durations, see [issue 223]. - /// - /// - If this method is used, the `TELOXIDE_PROXY` environmental variable - /// won't be extracted in [`BotBuilder::build`]. - /// - /// [issue 223]: https://github.com/teloxide/teloxide/issues/223 - /// [`BotBuilder::build`]: crate::BotBuilder::build - #[must_use] - pub fn client(mut self, client: Client) -> Self { - self.client = Some(client); - self - } - - /// Specified a custom token. - /// - /// Otherwise, a token will be extracted from the `TELOXIDE_TOKEN` - /// environmental variable. - #[must_use] - pub fn token(mut self, token: S) -> Self - where - S: Into, - { - self.token = Some(token.into()); - self - } - - /// Specifies [`ParseMode`], which will be used during all calls to: - /// - /// - [`send_message`] - /// - [`send_photo`] - /// - [`send_video`] - /// - [`send_audio`] - /// - [`send_document`] - /// - [`send_animation`] - /// - [`send_voice`] - /// - [`send_poll`] - /// - [`edit_message_text`] - /// - [`edit_message_caption`] - /// - /// [`send_message`]: crate::Bot::send_message - /// [`send_photo`]: crate::Bot::send_photo - /// [`send_video`]: crate::Bot::send_video - /// [`send_audio`]: crate::Bot::send_audio - /// [`send_document`]: crate::Bot::send_document - /// [`send_animation`]: crate::Bot::send_animation - /// [`send_voice`]: crate::Bot::send_voice - /// [`send_poll`]: crate::Bot::send_poll - /// [`edit_message_text`]: crate::Bot::edit_message_text - /// [`edit_message_caption`]: crate::Bot::edit_message_caption - #[must_use] - pub fn parse_mode(mut self, parse_mode: ParseMode) -> Self { - self.parse_mode = Some(parse_mode); - self - } - - /// Builds [`Bot`]. - /// - /// This method will attempt to build a new client with a proxy, specified - /// in the `TELOXIDE_PROXY` (passed into [`reqwest::Proxy::all`]) - /// environmental variable, if a client haven't been specified. If - /// `TELOXIDE_PROXY` is unspecified, it'll use no proxy. - /// - /// # Panics - /// - If cannot get the `TELOXIDE_TOKEN` environmental variable. - /// - If it cannot create [`reqwest::Client`]. - /// - /// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html - /// - /// [`Bot`]: crate::Bot - /// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all - #[must_use] - pub fn build(self) -> Bot { - Bot { - client: self.client.unwrap_or_else(crate::utils::client_from_env), - token: self.token.unwrap_or_else(|| get_env(TELOXIDE_TOKEN)).into(), - parse_mode: self.parse_mode, - } - } -} diff --git a/src/dispatching/dialogue/dialogue_dispatcher.rs b/src/dispatching/dialogue/dialogue_dispatcher.rs index e555d84e..2e722d70 100644 --- a/src/dispatching/dialogue/dialogue_dispatcher.rs +++ b/src/dispatching/dialogue/dialogue_dispatcher.rs @@ -11,6 +11,7 @@ use tokio::sync::mpsc; use lockfree::map::Map; use std::sync::{Arc, Mutex}; +use teloxide_core::requests::Requester; use tokio_stream::wrappers::UnboundedReceiverStream; /// A dispatcher of dialogues. @@ -23,7 +24,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream; /// /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`DispatcherHandler`]: crate::dispatching::DispatcherHandler -pub struct DialogueDispatcher { +pub struct DialogueDispatcher { storage: Arc, handler: Arc, _phantom: PhantomData>, @@ -34,12 +35,12 @@ pub struct DialogueDispatcher { /// A value is the TX part of an unbounded asynchronous MPSC channel. A /// handler that executes updates from the same chat ID sequentially /// handles the RX part. - senders: Arc>>>, + senders: Arc>>>, } -impl DialogueDispatcher, H, Upd> +impl DialogueDispatcher, H, Upd> where - H: DialogueDispatcherHandler + Send + Sync + 'static, + H: DialogueDispatcherHandler + Send + Sync + 'static, Upd: GetChatId + Send + 'static, D: Default + Send + 'static, { @@ -58,9 +59,9 @@ where } } -impl DialogueDispatcher +impl DialogueDispatcher where - H: DialogueDispatcherHandler + Send + Sync + 'static, + H: DialogueDispatcherHandler + Send + Sync + 'static, Upd: GetChatId + Send + 'static, D: Default + Send + 'static, S: Storage + Send + Sync + 'static, @@ -78,14 +79,17 @@ where } #[must_use] - fn new_tx(&self) -> mpsc::UnboundedSender> { + fn new_tx(&self) -> mpsc::UnboundedSender> + where + R: Requester + Send + 'static, + { let (tx, rx) = mpsc::unbounded_channel(); let storage = Arc::clone(&self.storage); let handler = Arc::clone(&self.handler); let senders = Arc::clone(&self.senders); - tokio::spawn(UnboundedReceiverStream::new(rx).for_each(move |cx: UpdateWithCx| { + tokio::spawn(UnboundedReceiverStream::new(rx).for_each(move |cx: UpdateWithCx| { let storage = Arc::clone(&storage); let handler = Arc::clone(&handler); let senders = Arc::clone(&senders); @@ -124,17 +128,21 @@ where } } -impl DispatcherHandler for DialogueDispatcher +impl DispatcherHandler for DialogueDispatcher where - H: DialogueDispatcherHandler + Send + Sync + 'static, + H: DialogueDispatcherHandler + Send + Sync + 'static, Upd: GetChatId + Send + 'static, D: Default + Send + 'static, S: Storage + Send + Sync + 'static, S::Error: Send + 'static, + R: Requester + Send, { - fn handle(self, updates: mpsc::UnboundedReceiver>) -> BoxFuture<'static, ()> + fn handle( + self, + updates: mpsc::UnboundedReceiver>, + ) -> BoxFuture<'static, ()> where - UpdateWithCx: 'static, + UpdateWithCx: 'static, { let this = Arc::new(self); diff --git a/src/dispatching/dialogue/dialogue_dispatcher_handler.rs b/src/dispatching/dialogue/dialogue_dispatcher_handler.rs index 1a596bcc..827809ea 100644 --- a/src/dispatching/dialogue/dialogue_dispatcher_handler.rs +++ b/src/dispatching/dialogue/dialogue_dispatcher_handler.rs @@ -8,24 +8,32 @@ use std::{future::Future, sync::Arc}; /// overview](crate::dispatching::dialogue). /// /// [`DialogueDispatcher`]: crate::dispatching::dialogue::DialogueDispatcher -pub trait DialogueDispatcherHandler { +pub trait DialogueDispatcherHandler { #[must_use] fn handle( self: Arc, - cx: DialogueWithCx, + cx: DialogueWithCx, ) -> BoxFuture<'static, DialogueStage> where - DialogueWithCx: Send + 'static; + DialogueWithCx: Send + 'static, + R: Send, + Upd: Send, + D: Send, + E: Send; } -impl DialogueDispatcherHandler for F +impl DialogueDispatcherHandler for F where - F: Fn(DialogueWithCx) -> Fut + Send + Sync + 'static, + F: Fn(DialogueWithCx) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, { - fn handle(self: Arc, cx: DialogueWithCx) -> BoxFuture<'static, Fut::Output> + fn handle(self: Arc, cx: DialogueWithCx) -> BoxFuture<'static, Fut::Output> where - DialogueWithCx: Send + 'static, + DialogueWithCx: Send + 'static, + R: Send, + Upd: Send, + D: Send, + E: Send, { Box::pin(async move { self(cx).await }) } diff --git a/src/dispatching/dialogue/dialogue_with_cx.rs b/src/dispatching/dialogue/dialogue_with_cx.rs index 90ab4556..8b718122 100644 --- a/src/dispatching/dialogue/dialogue_with_cx.rs +++ b/src/dispatching/dialogue/dialogue_with_cx.rs @@ -1,5 +1,6 @@ use crate::dispatching::{dialogue::GetChatId, UpdateWithCx}; use std::fmt::Debug; +use teloxide_core::requests::Requester; /// A context of a [`DialogueDispatcher`]'s message handler. /// @@ -8,21 +9,22 @@ use std::fmt::Debug; /// /// [`DialogueDispatcher`]: crate::dispatching::dialogue::DialogueDispatcher #[derive(Debug)] -pub struct DialogueWithCx { - pub cx: UpdateWithCx, +pub struct DialogueWithCx { + pub cx: UpdateWithCx, pub dialogue: Result, } -impl DialogueWithCx { +impl DialogueWithCx { /// Creates a new instance with the provided fields. - pub fn new(cx: UpdateWithCx, dialogue: D) -> Self { + pub fn new(cx: UpdateWithCx, dialogue: D) -> Self { Self { cx, dialogue: Ok(dialogue) } } } -impl GetChatId for DialogueWithCx +impl GetChatId for DialogueWithCx where Upd: GetChatId, + R: Requester, { fn chat_id(&self) -> i64 { self.cx.update.chat_id() diff --git a/src/dispatching/dialogue/get_chat_id.rs b/src/dispatching/dialogue/get_chat_id.rs index d7e64206..9d492a43 100644 --- a/src/dispatching/dialogue/get_chat_id.rs +++ b/src/dispatching/dialogue/get_chat_id.rs @@ -1,4 +1,4 @@ -use crate::types::Message; +use teloxide_core::types::Message; /// Something that has a chat ID. pub trait GetChatId { diff --git a/src/dispatching/dialogue/storage/redis_storage.rs b/src/dispatching/dialogue/storage/redis_storage.rs index a8514355..31a358e8 100644 --- a/src/dispatching/dialogue/storage/redis_storage.rs +++ b/src/dispatching/dialogue/storage/redis_storage.rs @@ -91,14 +91,13 @@ where Box::pin(async move { let dialogue = self.serializer.serialize(&dialogue).map_err(RedisStorageError::SerdeError)?; - Ok(self - .conn + self.conn .lock() .await .getset::<_, Vec, Option>>(chat_id, dialogue) .await? .map(|d| self.serializer.deserialize(&d).map_err(RedisStorageError::SerdeError)) - .transpose()?) + .transpose() }) } } diff --git a/src/dispatching/dialogue/storage/sqlite_storage.rs b/src/dispatching/dialogue/storage/sqlite_storage.rs index ca68b693..244da6d0 100644 --- a/src/dispatching/dialogue/storage/sqlite_storage.rs +++ b/src/dispatching/dialogue/storage/sqlite_storage.rs @@ -114,7 +114,7 @@ where } #[derive(sqlx::FromRow)] -struct DialogueDBRow { +struct DialogueDbRow { dialogue: Vec, } @@ -123,7 +123,7 @@ async fn get_dialogue( chat_id: i64, ) -> Result>>, sqlx::Error> { Ok( - match sqlx::query_as::<_, DialogueDBRow>( + match sqlx::query_as::<_, DialogueDbRow>( "SELECT dialogue FROM teloxide_dialogues WHERE chat_id = ?", ) .bind(chat_id) diff --git a/src/dispatching/dialogue/transition.rs b/src/dispatching/dialogue/transition.rs index 3150db98..5674ae3c 100644 --- a/src/dispatching/dialogue/transition.rs +++ b/src/dispatching/dialogue/transition.rs @@ -1,20 +1,19 @@ -use crate::{ - dispatching::{dialogue::DialogueStage, UpdateWithCx}, - types::Message, -}; +use crate::dispatching::{dialogue::DialogueStage, UpdateWithCx}; use futures::future::BoxFuture; +use teloxide_core::types::Message; /// Represents a transition function of a dialogue FSM. pub trait Transition: Sized { type Aux; type Error; + type Requester; /// Turns itself into another state, depending on the input message. /// /// `aux` will be passed to each subtransition function. fn react( self, - cx: TransitionIn, + cx: TransitionIn, aux: Self::Aux, ) -> BoxFuture<'static, TransitionOut>; } @@ -29,6 +28,7 @@ where type Aux; type Dialogue; type Error; + type Requester; /// Turns itself into another state, depending on the input message. /// @@ -36,7 +36,7 @@ where /// message's text. fn react( self, - cx: TransitionIn, + cx: TransitionIn, aux: Self::Aux, ) -> BoxFuture<'static, TransitionOut>; } @@ -44,6 +44,7 @@ where /// A type returned from a FSM subtransition function. /// /// Now it is used only inside `#[teloxide(subtransition)]` for type inference. +#[doc(hidden)] pub trait SubtransitionOutputType { type Output; type Error; @@ -55,7 +56,7 @@ impl SubtransitionOutputType for TransitionOut { } /// An input passed into a FSM (sub)transition function. -pub type TransitionIn = UpdateWithCx; +pub type TransitionIn = UpdateWithCx; /// A type returned from a FSM (sub)transition function. pub type TransitionOut = Result, E>; diff --git a/src/dispatching/dispatcher.rs b/src/dispatching/dispatcher.rs index 95b067c2..fa5eb7de 100644 --- a/src/dispatching/dispatcher.rs +++ b/src/dispatching/dispatcher.rs @@ -3,34 +3,37 @@ use crate::{ update_listeners, update_listeners::UpdateListener, DispatcherHandler, UpdateWithCx, }, error_handlers::{ErrorHandler, LoggingErrorHandler}, +}; +use futures::StreamExt; +use std::{fmt::Debug, sync::Arc}; +use teloxide_core::{ + requests::Requester, types::{ CallbackQuery, ChosenInlineResult, InlineQuery, Message, Poll, PollAnswer, PreCheckoutQuery, ShippingQuery, UpdateKind, }, - Bot, }; -use futures::StreamExt; -use std::{fmt::Debug, sync::Arc}; use tokio::sync::mpsc; -type Tx = Option>>; +type Tx = Option>>; #[macro_use] mod macros { /// Pushes an update to a queue. macro_rules! send { - ($bot:expr, $tx:expr, $update:expr, $variant:expr) => { - send($bot, $tx, $update, stringify!($variant)); + ($requester:expr, $tx:expr, $update:expr, $variant:expr) => { + send($requester, $tx, $update, stringify!($variant)); }; } } -fn send<'a, Upd>(bot: &'a Bot, tx: &'a Tx, update: Upd, variant: &'static str) +fn send<'a, R, Upd>(requester: &'a R, tx: &'a Tx, update: Upd, variant: &'static str) where Upd: Debug, + R: Requester + Clone, { if let Some(tx) = tx { - if let Err(error) = tx.send(UpdateWithCx { bot: bot.clone(), update }) { + if let Err(error) = tx.send(UpdateWithCx { requester: requester.clone(), update }) { log::error!( "The RX part of the {} channel is closed, but an update is received.\nError:{}\n", variant, @@ -44,28 +47,31 @@ where /// /// See the [module-level documentation](crate::dispatching) for the design /// overview. -pub struct Dispatcher { - bot: Bot, +pub struct Dispatcher { + requester: R, - messages_queue: Tx, - edited_messages_queue: Tx, - channel_posts_queue: Tx, - edited_channel_posts_queue: Tx, - inline_queries_queue: Tx, - chosen_inline_results_queue: Tx, - callback_queries_queue: Tx, - shipping_queries_queue: Tx, - pre_checkout_queries_queue: Tx, - polls_queue: Tx, - poll_answers_queue: Tx, + messages_queue: Tx, + edited_messages_queue: Tx, + channel_posts_queue: Tx, + edited_channel_posts_queue: Tx, + inline_queries_queue: Tx, + chosen_inline_results_queue: Tx, + callback_queries_queue: Tx, + shipping_queries_queue: Tx, + pre_checkout_queries_queue: Tx, + polls_queue: Tx, + poll_answers_queue: Tx, } -impl Dispatcher { - /// Constructs a new dispatcher with the specified `bot`. +impl Dispatcher +where + R: Send + 'static, +{ + /// Constructs a new dispatcher with the specified `requester`. #[must_use] - pub fn new(bot: Bot) -> Self { + pub fn new(requester: R) -> Self { Self { - bot, + requester, messages_queue: None, edited_messages_queue: None, channel_posts_queue: None, @@ -81,10 +87,12 @@ impl Dispatcher { } #[must_use] - fn new_tx(&self, h: H) -> Tx + #[allow(clippy::unnecessary_wraps)] + fn new_tx(&self, h: H) -> Tx where - H: DispatcherHandler + Send + 'static, + H: DispatcherHandler + Send + 'static, Upd: Send + 'static, + R: Send + 'static, { let (tx, rx) = mpsc::unbounded_channel(); tokio::spawn(async move { @@ -97,7 +105,7 @@ impl Dispatcher { #[must_use] pub fn messages_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.messages_queue = self.new_tx(h); self @@ -106,7 +114,7 @@ impl Dispatcher { #[must_use] pub fn edited_messages_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.edited_messages_queue = self.new_tx(h); self @@ -115,7 +123,7 @@ impl Dispatcher { #[must_use] pub fn channel_posts_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.channel_posts_queue = self.new_tx(h); self @@ -124,7 +132,7 @@ impl Dispatcher { #[must_use] pub fn edited_channel_posts_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.edited_channel_posts_queue = self.new_tx(h); self @@ -133,7 +141,7 @@ impl Dispatcher { #[must_use] pub fn inline_queries_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.inline_queries_queue = self.new_tx(h); self @@ -142,7 +150,7 @@ impl Dispatcher { #[must_use] pub fn chosen_inline_results_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.chosen_inline_results_queue = self.new_tx(h); self @@ -151,7 +159,7 @@ impl Dispatcher { #[must_use] pub fn callback_queries_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.callback_queries_queue = self.new_tx(h); self @@ -160,7 +168,7 @@ impl Dispatcher { #[must_use] pub fn shipping_queries_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.shipping_queries_queue = self.new_tx(h); self @@ -169,7 +177,7 @@ impl Dispatcher { #[must_use] pub fn pre_checkout_queries_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.pre_checkout_queries_queue = self.new_tx(h); self @@ -178,7 +186,7 @@ impl Dispatcher { #[must_use] pub fn polls_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.polls_queue = self.new_tx(h); self @@ -187,7 +195,7 @@ impl Dispatcher { #[must_use] pub fn poll_answers_handler(mut self, h: H) -> Self where - H: DispatcherHandler + 'static + Send, + H: DispatcherHandler + 'static + Send, { self.poll_answers_queue = self.new_tx(h); self @@ -197,9 +205,13 @@ impl Dispatcher { /// /// The default parameters are a long polling update listener and log all /// errors produced by this listener). - pub async fn dispatch(&self) { + pub async fn dispatch(&self) + where + R: Requester + Clone, + ::GetUpdatesFaultTolerant: Send, + { self.dispatch_with_listener( - update_listeners::polling_default(self.bot.clone()), + update_listeners::polling_default(self.requester.clone()), LoggingErrorHandler::with_custom_text("An error from the update listener"), ) .await; @@ -215,6 +227,7 @@ impl Dispatcher { UListener: UpdateListener + 'a, Eh: ErrorHandler + 'a, ListenerE: Debug, + R: Requester + Clone, { let update_listener = Box::pin(update_listener); @@ -235,11 +248,16 @@ impl Dispatcher { match update.kind { UpdateKind::Message(message) => { - send!(&self.bot, &self.messages_queue, message, UpdateKind::Message); + send!( + &self.requester, + &self.messages_queue, + message, + UpdateKind::Message + ); } UpdateKind::EditedMessage(message) => { send!( - &self.bot, + &self.requester, &self.edited_messages_queue, message, UpdateKind::EditedMessage @@ -247,7 +265,7 @@ impl Dispatcher { } UpdateKind::ChannelPost(post) => { send!( - &self.bot, + &self.requester, &self.channel_posts_queue, post, UpdateKind::ChannelPost @@ -255,7 +273,7 @@ impl Dispatcher { } UpdateKind::EditedChannelPost(post) => { send!( - &self.bot, + &self.requester, &self.edited_channel_posts_queue, post, UpdateKind::EditedChannelPost @@ -263,7 +281,7 @@ impl Dispatcher { } UpdateKind::InlineQuery(query) => { send!( - &self.bot, + &self.requester, &self.inline_queries_queue, query, UpdateKind::InlineQuery @@ -271,7 +289,7 @@ impl Dispatcher { } UpdateKind::ChosenInlineResult(result) => { send!( - &self.bot, + &self.requester, &self.chosen_inline_results_queue, result, UpdateKind::ChosenInlineResult @@ -279,7 +297,7 @@ impl Dispatcher { } UpdateKind::CallbackQuery(query) => { send!( - &self.bot, + &self.requester, &self.callback_queries_queue, query, UpdateKind::CallbackQuer @@ -287,7 +305,7 @@ impl Dispatcher { } UpdateKind::ShippingQuery(query) => { send!( - &self.bot, + &self.requester, &self.shipping_queries_queue, query, UpdateKind::ShippingQuery @@ -295,18 +313,18 @@ impl Dispatcher { } UpdateKind::PreCheckoutQuery(query) => { send!( - &self.bot, + &self.requester, &self.pre_checkout_queries_queue, query, UpdateKind::PreCheckoutQuery ); } UpdateKind::Poll(poll) => { - send!(&self.bot, &self.polls_queue, poll, UpdateKind::Poll); + send!(&self.requester, &self.polls_queue, poll, UpdateKind::Poll); } UpdateKind::PollAnswer(answer) => { send!( - &self.bot, + &self.requester, &self.poll_answers_queue, answer, UpdateKind::PollAnswer diff --git a/src/dispatching/dispatcher_handler.rs b/src/dispatching/dispatcher_handler.rs index 94ec6dbd..cd05f3cd 100644 --- a/src/dispatching/dispatcher_handler.rs +++ b/src/dispatching/dispatcher_handler.rs @@ -9,21 +9,21 @@ use futures::future::BoxFuture; /// overview. /// /// [`Dispatcher`]: crate::dispatching::Dispatcher -pub trait DispatcherHandler { +pub trait DispatcherHandler { #[must_use] - fn handle(self, updates: DispatcherHandlerRx) -> BoxFuture<'static, ()> + fn handle(self, updates: DispatcherHandlerRx) -> BoxFuture<'static, ()> where - UpdateWithCx: Send + 'static; + UpdateWithCx: Send + 'static; } -impl DispatcherHandler for F +impl DispatcherHandler for F where - F: FnOnce(DispatcherHandlerRx) -> Fut + Send + 'static, + F: FnOnce(DispatcherHandlerRx) -> Fut + Send + 'static, Fut: Future + Send + 'static, { - fn handle(self, updates: DispatcherHandlerRx) -> BoxFuture<'static, ()> + fn handle(self, updates: DispatcherHandlerRx) -> BoxFuture<'static, ()> where - UpdateWithCx: Send + 'static, + UpdateWithCx: Send + 'static, { Box::pin(async move { self(updates).await }) } diff --git a/src/dispatching/dispatcher_handler_rx_ext.rs b/src/dispatching/dispatcher_handler_rx_ext.rs index 6142b133..7a0dddf6 100644 --- a/src/dispatching/dispatcher_handler_rx_ext.rs +++ b/src/dispatching/dispatcher_handler_rx_ext.rs @@ -1,5 +1,6 @@ -use crate::{prelude::UpdateWithCx, types::Message, utils::command::BotCommand}; +use crate::{dispatching::UpdateWithCx, utils::command::BotCommand}; use futures::{stream::BoxStream, Stream, StreamExt}; +use teloxide_core::types::Message; /// An extension trait to be used with [`DispatcherHandlerRx`]. /// @@ -7,37 +8,41 @@ use futures::{stream::BoxStream, Stream, StreamExt}; /// overview. /// /// [`DispatcherHandlerRx`]: crate::dispatching::DispatcherHandlerRx -pub trait DispatcherHandlerRxExt { +pub trait DispatcherHandlerRxExt { /// Extracts only text messages from this stream of arbitrary messages. - fn text_messages(self) -> BoxStream<'static, (UpdateWithCx, String)> + fn text_messages(self) -> BoxStream<'static, (UpdateWithCx, String)> where - Self: Stream>; + Self: Stream>, + R: Send + 'static; /// Extracts only commands with their arguments from this stream of /// arbitrary messages. - fn commands(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx, C)> + fn commands(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx, C)> where - Self: Stream>, + Self: Stream>, C: BotCommand, - N: Into + Send; + N: Into + Send, + R: Send + 'static; } -impl DispatcherHandlerRxExt for T +impl DispatcherHandlerRxExt for T where T: Send + 'static, { - fn text_messages(self) -> BoxStream<'static, (UpdateWithCx, String)> + fn text_messages(self) -> BoxStream<'static, (UpdateWithCx, String)> where - Self: Stream>, + Self: Stream>, + R: Send + 'static, { self.filter_map(|cx| async move { cx.update.text_owned().map(|text| (cx, text)) }).boxed() } - fn commands(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx, C)> + fn commands(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx, C)> where - Self: Stream>, + Self: Stream>, C: BotCommand, N: Into + Send, + R: Send + 'static, { let bot_name = bot_name.into(); diff --git a/src/dispatching/mod.rs b/src/dispatching/mod.rs index 05e367dd..373202f3 100644 --- a/src/dispatching/mod.rs +++ b/src/dispatching/mod.rs @@ -55,9 +55,9 @@ pub use dispatcher::Dispatcher; pub use dispatcher_handler::DispatcherHandler; pub use dispatcher_handler_rx_ext::DispatcherHandlerRxExt; use tokio::sync::mpsc::UnboundedReceiver; -pub use update_with_cx::UpdateWithCx; +pub use update_with_cx::{UpdateWithCx, UpdateWithCxRequesterType}; /// A type of a stream, consumed by [`Dispatcher`]'s handlers. /// /// [`Dispatcher`]: crate::dispatching::Dispatcher -pub type DispatcherHandlerRx = UnboundedReceiver>; +pub type DispatcherHandlerRx = UnboundedReceiver>; diff --git a/src/dispatching/repls/commands_repl.rs b/src/dispatching/repls/commands_repl.rs index cc90ad0c..249d4861 100644 --- a/src/dispatching/repls/commands_repl.rs +++ b/src/dispatching/repls/commands_repl.rs @@ -4,12 +4,11 @@ use crate::{ DispatcherHandlerRxExt, UpdateWithCx, }, error_handlers::{LoggingErrorHandler, OnError}, - types::Message, utils::command::BotCommand, - Bot, }; use futures::StreamExt; use std::{fmt::Debug, future::Future, sync::Arc}; +use teloxide_core::{requests::Requester, types::Message}; use tokio_stream::wrappers::UnboundedReceiverStream; /// A [REPL] for commands. @@ -23,22 +22,24 @@ use tokio_stream::wrappers::UnboundedReceiverStream; /// /// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop /// [`Dispatcher`]: crate::dispatching::Dispatcher -pub async fn commands_repl(bot: Bot, bot_name: N, handler: H) +pub async fn commands_repl(requester: R, bot_name: N, handler: H) where Cmd: BotCommand + Send + 'static, - H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, + H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, Result<(), HandlerE>: OnError, HandlerE: Debug + Send, N: Into + Send + 'static, + R: Requester + Send + Clone + 'static, + ::GetUpdatesFaultTolerant: Send, { - let cloned_bot = bot.clone(); + let cloned_requester = requester.clone(); commands_repl_with_listener( - bot, + requester, bot_name, handler, - update_listeners::polling_default(cloned_bot), + update_listeners::polling_default(cloned_requester), ) .await; } @@ -55,25 +56,26 @@ where /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`commands_repl`]: crate::dispatching::repls::commands_repl() /// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener -pub async fn commands_repl_with_listener<'a, Cmd, H, Fut, L, ListenerE, HandlerE, N>( - bot: Bot, +pub async fn commands_repl_with_listener<'a, R, Cmd, H, Fut, L, ListenerE, HandlerE, N>( + requester: R, bot_name: N, handler: H, listener: L, ) where Cmd: BotCommand + Send + 'static, - H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, + H: Fn(UpdateWithCx, Cmd) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, L: UpdateListener + Send + 'a, ListenerE: Debug + Send + 'a, Result<(), HandlerE>: OnError, HandlerE: Debug + Send, N: Into + Send + 'static, + R: Requester + Clone + Send + 'static, { let handler = Arc::new(handler); - Dispatcher::new(bot) - .messages_handler(move |rx: DispatcherHandlerRx| { + Dispatcher::::new(requester) + .messages_handler(move |rx: DispatcherHandlerRx| { UnboundedReceiverStream::new(rx).commands::(bot_name).for_each_concurrent( None, move |(cx, cmd)| { diff --git a/src/dispatching/repls/dialogues_repl.rs b/src/dispatching/repls/dialogues_repl.rs index 883e74de..706d26a1 100644 --- a/src/dispatching/repls/dialogues_repl.rs +++ b/src/dispatching/repls/dialogues_repl.rs @@ -6,10 +6,9 @@ use crate::{ Dispatcher, UpdateWithCx, }, error_handlers::LoggingErrorHandler, - types::Message, - Bot, }; use std::{convert::Infallible, fmt::Debug, future::Future, sync::Arc}; +use teloxide_core::{requests::Requester, types::Message}; /// A [REPL] for dialogues. /// @@ -24,15 +23,22 @@ use std::{convert::Infallible, fmt::Debug, future::Future, sync::Arc}; /// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`InMemStorage`]: crate::dispatching::dialogue::InMemStorage -pub async fn dialogues_repl<'a, H, D, Fut>(bot: Bot, handler: H) +pub async fn dialogues_repl<'a, R, H, D, Fut>(requester: R, handler: H) where - H: Fn(UpdateWithCx, D) -> Fut + Send + Sync + 'static, + H: Fn(UpdateWithCx, D) -> Fut + Send + Sync + 'static, D: Default + Send + 'static, Fut: Future> + Send + 'static, + R: Requester + Send + Clone + 'static, + ::GetUpdatesFaultTolerant: Send, { - let cloned_bot = bot.clone(); + let cloned_requester = requester.clone(); - dialogues_repl_with_listener(bot, handler, update_listeners::polling_default(cloned_bot)).await; + dialogues_repl_with_listener( + requester, + handler, + update_listeners::polling_default(cloned_requester), + ) + .await; } /// Like [`dialogues_repl`], but with a custom [`UpdateListener`]. @@ -49,22 +55,23 @@ where /// [`dialogues_repl`]: crate::dispatching::repls::dialogues_repl() /// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener /// [`InMemStorage`]: crate::dispatching::dialogue::InMemStorage -pub async fn dialogues_repl_with_listener<'a, H, D, Fut, L, ListenerE>( - bot: Bot, +pub async fn dialogues_repl_with_listener<'a, R, H, D, Fut, L, ListenerE>( + requester: R, handler: H, listener: L, ) where - H: Fn(UpdateWithCx, D) -> Fut + Send + Sync + 'static, + H: Fn(UpdateWithCx, D) -> Fut + Send + Sync + 'static, D: Default + Send + 'static, Fut: Future> + Send + 'static, L: UpdateListener + Send + 'a, ListenerE: Debug + Send + 'a, + R: Requester + Send + Clone + 'static, { let handler = Arc::new(handler); - Dispatcher::new(bot) + Dispatcher::new(requester) .messages_handler(DialogueDispatcher::new( - move |DialogueWithCx { cx, dialogue }: DialogueWithCx| { + move |DialogueWithCx { cx, dialogue }: DialogueWithCx| { let handler = Arc::clone(&handler); async move { diff --git a/src/dispatching/repls/repl.rs b/src/dispatching/repls/repl.rs index 877c6869..31075f60 100644 --- a/src/dispatching/repls/repl.rs +++ b/src/dispatching/repls/repl.rs @@ -4,11 +4,10 @@ use crate::{ UpdateWithCx, }, error_handlers::{LoggingErrorHandler, OnError}, - types::Message, - Bot, }; use futures::StreamExt; use std::{fmt::Debug, future::Future, sync::Arc}; +use teloxide_core::{requests::Requester, types::Message}; use tokio_stream::wrappers::UnboundedReceiverStream; /// A [REPL] for messages. @@ -22,15 +21,18 @@ use tokio_stream::wrappers::UnboundedReceiverStream; /// /// [REPL]: https://en.wikipedia.org/wiki/Read-eval-print_loop /// [`Dispatcher`]: crate::dispatching::Dispatcher -pub async fn repl(bot: Bot, handler: H) +pub async fn repl(requester: R, handler: H) where - H: Fn(UpdateWithCx) -> Fut + Send + Sync + 'static, + H: Fn(UpdateWithCx) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, Result<(), E>: OnError, E: Debug + Send, + R: Requester + Send + Clone + 'static, + ::GetUpdatesFaultTolerant: Send, { - let cloned_bot = bot.clone(); - repl_with_listener(bot, handler, update_listeners::polling_default(cloned_bot)).await; + let cloned_requester = requester.clone(); + repl_with_listener(requester, handler, update_listeners::polling_default(cloned_requester)) + .await; } /// Like [`repl`], but with a custom [`UpdateListener`]. @@ -45,19 +47,23 @@ where /// [`Dispatcher`]: crate::dispatching::Dispatcher /// [`repl`]: crate::dispatching::repls::repl() /// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener -pub async fn repl_with_listener<'a, H, Fut, E, L, ListenerE>(bot: Bot, handler: H, listener: L) -where - H: Fn(UpdateWithCx) -> Fut + Send + Sync + 'static, +pub async fn repl_with_listener<'a, R, H, Fut, E, L, ListenerE>( + requester: R, + handler: H, + listener: L, +) where + H: Fn(UpdateWithCx) -> Fut + Send + Sync + 'static, Fut: Future> + Send + 'static, L: UpdateListener + Send + 'a, ListenerE: Debug, Result<(), E>: OnError, E: Debug + Send, + R: Requester + Clone + Send + 'static, { let handler = Arc::new(handler); - Dispatcher::new(bot) - .messages_handler(|rx: DispatcherHandlerRx| { + Dispatcher::new(requester) + .messages_handler(|rx: DispatcherHandlerRx| { UnboundedReceiverStream::new(rx).for_each_concurrent(None, move |message| { let handler = Arc::clone(&handler); diff --git a/src/dispatching/update_listeners.rs b/src/dispatching/update_listeners.rs index 05b30cc7..8f7432c7 100644 --- a/src/dispatching/update_listeners.rs +++ b/src/dispatching/update_listeners.rs @@ -105,14 +105,11 @@ use futures::{stream, Stream, StreamExt}; -use crate::{ - bot::Bot, - requests::Request, - types::{AllowedUpdate, Update}, - RequestError, -}; - use std::{convert::TryInto, time::Duration}; +use teloxide_core::{ + requests::{HasPayload, Request, Requester}, + types::{AllowedUpdate, SemiparsedVec, Update}, +}; /// A generic update listener. pub trait UpdateListener: Stream> { @@ -123,8 +120,12 @@ impl UpdateListener for S where S: Stream> {} /// Returns a long polling update listener with `timeout` of 10 seconds. /// /// See also: [`polling`](polling). -pub fn polling_default(bot: Bot) -> impl UpdateListener { - polling(bot, Some(Duration::from_secs(10)), None, None) +pub fn polling_default(requester: R) -> impl UpdateListener +where + R: Requester, + ::GetUpdatesFaultTolerant: Send, +{ + polling(requester, Some(Duration::from_secs(10)), None, None) } /// Returns a long/short polling update listener with some additional options. @@ -139,25 +140,31 @@ pub fn polling_default(bot: Bot) -> impl UpdateListener { /// See also: [`polling_default`](polling_default). /// /// [`GetUpdates`]: crate::requests::GetUpdates -pub fn polling( - bot: Bot, +pub fn polling( + requester: R, timeout: Option, limit: Option, allowed_updates: Option>, -) -> impl UpdateListener { +) -> impl UpdateListener +where + R: Requester, + ::GetUpdatesFaultTolerant: Send, +{ let timeout = timeout.map(|t| t.as_secs().try_into().expect("timeout is too big")); stream::unfold( - (allowed_updates, bot, 0), + (allowed_updates, requester, 0), move |(mut allowed_updates, bot, mut offset)| async move { - let mut req = bot.get_updates().offset(offset); - req.timeout = timeout; - req.limit = limit; - req.allowed_updates = allowed_updates.take(); + let mut req = bot.get_updates_fault_tolerant(); + let payload = &mut req.payload_mut().0; + payload.offset = Some(offset); + payload.timeout = timeout; + payload.limit = limit; + payload.allowed_updates = allowed_updates.take(); let updates = match req.send().await { Err(err) => vec![Err(err)], - Ok(updates) => { + Ok(SemiparsedVec(updates)) => { // Set offset to the last update's id + 1 if let Some(upd) = updates.last() { let id: i32 = match upd { diff --git a/src/dispatching/update_with_cx.rs b/src/dispatching/update_with_cx.rs index f3fa74e1..6ac78034 100644 --- a/src/dispatching/update_with_cx.rs +++ b/src/dispatching/update_with_cx.rs @@ -1,13 +1,8 @@ -use crate::{ - dispatching::dialogue::GetChatId, - requests::{ - DeleteMessage, EditMessageCaption, EditMessageText, ForwardMessage, PinChatMessage, - Request, ResponseResult, SendAnimation, SendAudio, SendContact, SendDice, SendDocument, - SendLocation, SendMediaGroup, SendMessage, SendPhoto, SendSticker, SendVenue, SendVideo, - SendVideoNote, SendVoice, - }, +use crate::dispatching::dialogue::GetChatId; +use teloxide_core::{ + payloads::SendMessageSetters, + requests::{Request, Requester}, types::{ChatId, InputFile, InputMedia, Message}, - Bot, }; /// A [`Dispatcher`]'s handler's context of a bot and an update. @@ -17,12 +12,12 @@ use crate::{ /// /// [`Dispatcher`]: crate::dispatching::Dispatcher #[derive(Debug)] -pub struct UpdateWithCx { - pub bot: Bot, +pub struct UpdateWithCx { + pub requester: R, pub update: Upd, } -impl GetChatId for UpdateWithCx +impl GetChatId for UpdateWithCx where Upd: GetChatId, { @@ -31,121 +26,136 @@ where } } -impl UpdateWithCx { +#[doc(hidden)] +// Now it is used only inside `#[teloxide(subtransition)]` for type inference. +pub trait UpdateWithCxRequesterType { + type Requester; +} + +impl UpdateWithCxRequesterType for UpdateWithCx { + type Requester = R; +} + +impl UpdateWithCx +where + R: Requester, +{ /// A shortcut for `.answer(text).send().await`. - pub async fn answer_str(&self, text: T) -> ResponseResult + #[deprecated(note = "Use .answer(text).await instead")] + pub async fn answer_str(&self, text: T) -> Result where T: Into, + R::SendMessage: std::future::Future, { self.answer(text).send().await } - pub fn answer(&self, text: T) -> SendMessage + pub fn answer(&self, text: T) -> R::SendMessage where T: Into, { - self.bot.send_message(self.chat_id(), text) + self.requester.send_message(self.chat_id(), text) } - pub fn reply_to(&self, text: T) -> SendMessage + pub fn reply_to(&self, text: T) -> R::SendMessage where T: Into, { - self.bot.send_message(self.chat_id(), text).reply_to_message_id(self.update.id) + self.requester.send_message(self.chat_id(), text).reply_to_message_id(self.update.id) } - pub fn answer_photo(&self, photo: InputFile) -> SendPhoto { - self.bot.send_photo(self.update.chat.id, photo) + pub fn answer_photo(&self, photo: InputFile) -> R::SendPhoto { + self.requester.send_photo(self.update.chat.id, photo) } - pub fn answer_audio(&self, audio: InputFile) -> SendAudio { - self.bot.send_audio(self.update.chat.id, audio) + pub fn answer_audio(&self, audio: InputFile) -> R::SendAudio { + self.requester.send_audio(self.update.chat.id, audio) } - pub fn answer_animation(&self, animation: InputFile) -> SendAnimation { - self.bot.send_animation(self.update.chat.id, animation) + pub fn answer_animation(&self, animation: InputFile) -> R::SendAnimation { + self.requester.send_animation(self.update.chat.id, animation) } - pub fn answer_document(&self, document: InputFile) -> SendDocument { - self.bot.send_document(self.update.chat.id, document) + pub fn answer_document(&self, document: InputFile) -> R::SendDocument { + self.requester.send_document(self.update.chat.id, document) } - pub fn answer_video(&self, video: InputFile) -> SendVideo { - self.bot.send_video(self.update.chat.id, video) + pub fn answer_video(&self, video: InputFile) -> R::SendVideo { + self.requester.send_video(self.update.chat.id, video) } - pub fn answer_voice(&self, voice: InputFile) -> SendVoice { - self.bot.send_voice(self.update.chat.id, voice) + pub fn answer_voice(&self, voice: InputFile) -> R::SendVoice { + self.requester.send_voice(self.update.chat.id, voice) } - pub fn answer_media_group(&self, media_group: T) -> SendMediaGroup + pub fn answer_media_group(&self, media_group: T) -> R::SendMediaGroup where - T: Into>, + T: IntoIterator, { - self.bot.send_media_group(self.update.chat.id, media_group) + self.requester.send_media_group(self.update.chat.id, media_group) } - pub fn answer_location(&self, latitude: f32, longitude: f32) -> SendLocation { - self.bot.send_location(self.update.chat.id, latitude, longitude) + pub fn answer_location(&self, latitude: f64, longitude: f64) -> R::SendLocation { + self.requester.send_location(self.update.chat.id, latitude, longitude) } pub fn answer_venue( &self, - latitude: f32, - longitude: f32, + latitude: f64, + longitude: f64, title: T, address: U, - ) -> SendVenue + ) -> R::SendVenue where T: Into, U: Into, { - self.bot.send_venue(self.update.chat.id, latitude, longitude, title, address) + self.requester.send_venue(self.update.chat.id, latitude, longitude, title, address) } - pub fn answer_video_note(&self, video_note: InputFile) -> SendVideoNote { - self.bot.send_video_note(self.update.chat.id, video_note) + pub fn answer_video_note(&self, video_note: InputFile) -> R::SendVideoNote { + self.requester.send_video_note(self.update.chat.id, video_note) } - pub fn answer_contact(&self, phone_number: T, first_name: U) -> SendContact + pub fn answer_contact(&self, phone_number: T, first_name: U) -> R::SendContact where T: Into, U: Into, { - self.bot.send_contact(self.chat_id(), phone_number, first_name) + self.requester.send_contact(self.chat_id(), phone_number, first_name) } - pub fn answer_sticker(&self, sticker: InputFile) -> SendSticker { - self.bot.send_sticker(self.update.chat.id, sticker) + pub fn answer_sticker(&self, sticker: InputFile) -> R::SendSticker { + self.requester.send_sticker(self.update.chat.id, sticker) } - pub fn forward_to(&self, chat_id: T) -> ForwardMessage + pub fn forward_to(&self, chat_id: T) -> R::ForwardMessage where T: Into, { - self.bot.forward_message(chat_id, self.update.chat.id, self.update.id) + self.requester.forward_message(chat_id, self.update.chat.id, self.update.id) } - pub fn edit_message_text(&self, text: T) -> EditMessageText + pub fn edit_message_text(&self, text: T) -> R::EditMessageText where T: Into, { - self.bot.edit_message_text(self.update.chat.id, self.update.id, text) + self.requester.edit_message_text(self.update.chat.id, self.update.id, text) } - pub fn edit_message_caption(&self) -> EditMessageCaption { - self.bot.edit_message_caption(self.update.chat.id, self.update.id) + pub fn edit_message_caption(&self) -> R::EditMessageCaption { + self.requester.edit_message_caption(self.update.chat.id, self.update.id) } - pub fn delete_message(&self) -> DeleteMessage { - self.bot.delete_message(self.update.chat.id, self.update.id) + pub fn delete_message(&self) -> R::DeleteMessage { + self.requester.delete_message(self.update.chat.id, self.update.id) } - pub fn pin_message(&self) -> PinChatMessage { - self.bot.pin_chat_message(self.update.chat.id, self.update.id) + pub fn pin_message(&self) -> R::PinChatMessage { + self.requester.pin_chat_message(self.update.chat.id, self.update.id) } - pub fn answer_dice(&self) -> SendDice { - self.bot.send_dice(self.update.chat.id) + pub fn answer_dice(&self) -> R::SendDice { + self.requester.send_dice(self.update.chat.id) } } diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 466cc501..00000000 --- a/src/errors.rs +++ /dev/null @@ -1,515 +0,0 @@ -use derive_more::From; -use reqwest::StatusCode; -use serde::Deserialize; -use thiserror::Error; - -/// An error caused by downloading a file. -#[derive(Debug, Error, From)] -pub enum DownloadError { - #[error("A network error: {0}")] - NetworkError(#[source] reqwest::Error), - - #[error("An I/O error: {0}")] - Io(#[source] std::io::Error), -} - -/// An error caused by sending a request to Telegram. -#[derive(Debug, Error)] -pub enum RequestError { - #[error("A Telegram's error #{status_code}: {kind:?}")] - ApiError { status_code: StatusCode, kind: ApiErrorKind }, - - /// The group has been migrated to a supergroup with the specified - /// identifier. - #[error("The group has been migrated to a supergroup with ID #{0}")] - MigrateToChatId(i64), - - /// In case of exceeding flood control, the number of seconds left to wait - /// before the request can be repeated. - #[error("Retry after {0} seconds")] - RetryAfter(i32), - - #[error("A network error: {0}")] - NetworkError(#[source] reqwest::Error), - - #[error("An error while parsing JSON: {0}")] - InvalidJson(#[source] serde_json::Error), -} - -/// A kind of an API error. -/// -/// If you receive [`ApiErrorKind::Unknown`], please [open an issue] with -/// the description of the error. -/// -/// [`ApiErrorKind::Unknown`]: crate::ApiErrorKind::Unknown -/// [open an issue]: https://github.com/teloxide/teloxide/issues/new -#[derive(Debug, Deserialize, PartialEq, Hash, Eq, Clone)] -#[serde(untagged)] -pub enum ApiErrorKind { - Known(KnownApiErrorKind), - Unknown(String), -} - -/// A kind of a known API error. -#[derive(Debug, Deserialize, PartialEq, Copy, Hash, Eq, Clone)] -pub enum KnownApiErrorKind { - /// Occurs when the bot tries to send message to user who blocked the bot. - #[serde(rename = "Forbidden: bot was blocked by the user")] - BotBlocked, - - /// Occurs when bot tries to modify a message without modification content. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::requests::EditMessageText - #[serde(rename = "Bad Request: message is not modified: specified new message content and \ - reply markup are exactly the same as a current content and reply markup \ - of the message")] - MessageNotModified, - - /// Occurs when bot tries to forward or delete a message which was deleted. - /// - /// May happen in methods: - /// 1. [`ForwardMessage`] - /// 2. [`DeleteMessage`] - /// - /// [`ForwardMessage`]: crate::requests::ForwardMessage - /// [`DeleteMessage`]: crate::requests::DeleteMessage - #[serde(rename = "Bad Request: MESSAGE_ID_INVALID")] - MessageIdInvalid, - - /// Occurs when bot tries to forward a message which does not exists. - /// - /// May happen in methods: - /// 1. [`ForwardMessage`] - /// - /// [`ForwardMessage`]: crate::requests::ForwardMessage - #[serde(rename = "Bad Request: message to forward not found")] - MessageToForwardNotFound, - - /// Occurs when bot tries to delete a message which does not exists. - /// - /// May happen in methods: - /// 1. [`DeleteMessage`] - /// - /// [`DeleteMessage`]: crate::requests::DeleteMessage - #[serde(rename = "Bad Request: message to delete not found")] - MessageToDeleteNotFound, - - /// Occurs when bot tries to send a text message without text. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: message text is empty")] - MessageTextIsEmpty, - - /// Occurs when bot tries to edit a message after long time. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::requests::EditMessageText - #[serde(rename = "Bad Request: message can't be edited")] - MessageCantBeEdited, - - /// Occurs when bot tries to delete a someone else's message in group where - /// it does not have enough rights. - /// - /// May happen in methods: - /// 1. [`DeleteMessage`] - /// - /// [`DeleteMessage`]: crate::requests::DeleteMessage - #[serde(rename = "Bad Request: message can't be deleted")] - MessageCantBeDeleted, - - /// Occurs when bot tries to edit a message which does not exists. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::requests::EditMessageText - #[serde(rename = "Bad Request: message to edit not found")] - MessageToEditNotFound, - - /// Occurs when bot tries to reply to a message which does not exists. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: reply message not found")] - MessageToReplyNotFound, - - /// Occurs when bot tries to - #[serde(rename = "Bad Request: message identifier is not specified")] - MessageIdentifierNotSpecified, - - /// Occurs when bot tries to send a message with text size greater then - /// 4096 symbols. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: message is too long")] - MessageIsTooLong, - - /// Occurs when bot tries to send media group with more than 10 items. - /// - /// May happen in methods: - /// 1. [`SendMediaGroup`] - /// - /// [`SendMediaGroup`]: crate::requests::SendMediaGroup - #[serde(rename = "Bad Request: Too much messages to send as an album")] - ToMuchMessages, - - /// Occurs when bot tries to stop poll that has already been stopped. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll has already been closed")] - PollHasAlreadyClosed, - - /// Occurs when bot tries to send poll with less than 2 options. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll must have at least 2 option")] - PollMustHaveMoreOptions, - - /// Occurs when bot tries to send poll with more than 10 options. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll can't have more than 10 options")] - PollCantHaveMoreOptions, - - /// Occurs when bot tries to send poll with empty option (without text). - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll options must be non-empty")] - PollOptionsMustBeNonEmpty, - - /// Occurs when bot tries to send poll with empty question (without text). - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll question must be non-empty")] - PollQuestionMustBeNonEmpty, - - /// Occurs when bot tries to send poll with total size of options more than - /// 100 symbols. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll options length must not exceed 100")] - PollOptionsLengthTooLong, - - /// Occurs when bot tries to send poll with question size more than 255 - /// symbols. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::requests::SendPoll - #[serde(rename = "Bad Request: poll question length must not exceed 255")] - PollQuestionLengthTooLong, - - /// Occurs when bot tries to stop poll with message without poll. - /// - /// May happen in methods: - /// 1. [`StopPoll`] - /// - /// [`StopPoll`]: crate::requests::StopPoll - #[serde(rename = "Bad Request: message with poll to stop not found")] - MessageWithPollNotFound, - - /// Occurs when bot tries to stop poll with message without poll. - /// - /// May happen in methods: - /// 1. [`StopPoll`] - /// - /// [`StopPoll`]: crate::requests::StopPoll - #[serde(rename = "Bad Request: message is not a poll")] - MessageIsNotAPoll, - - /// Occurs when bot tries to send a message to chat in which it is not a - /// member. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: chat not found")] - ChatNotFound, - - /// Occurs when bot tries to send method with unknown user_id. - /// - /// May happen in methods: - /// 1. [`getUserProfilePhotos`] - /// - /// [`getUserProfilePhotos`]: - /// crate::requests::GetUserProfilePhotos - #[serde(rename = "Bad Request: user not found")] - UserNotFound, - - /// Occurs when bot tries to send [`SetChatDescription`] with same text as - /// in the current description. - /// - /// May happen in methods: - /// 1. [`SetChatDescription`] - /// - /// [`SetChatDescription`]: crate::requests::SetChatDescription - #[serde(rename = "Bad Request: chat description is not modified")] - ChatDescriptionIsNotModified, - - /// Occurs when bot tries to answer to query after timeout expire. - /// - /// May happen in methods: - /// 1. [`AnswerCallbackQuery`] - /// - /// [`AnswerCallbackQuery`]: crate::requests::AnswerCallbackQuery - #[serde(rename = "Bad Request: query is too old and response timeout expired or query id is \ - invalid")] - InvalidQueryID, - - /// Occurs when bot tries to send InlineKeyboardMarkup with invalid button - /// url. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: BUTTON_URL_INVALID")] - ButtonURLInvalid, - - /// Occurs when bot tries to send button with data size more than 64 bytes. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: BUTTON_DATA_INVALID")] - ButtonDataInvalid, - - /// Occurs when bot tries to send button with data size == 0. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: can't parse inline keyboard button: Text buttons are \ - unallowed in the inline keyboard")] - TextButtonsAreUnallowed, - - /// Occurs when bot tries to get file by wrong file id. - /// - /// May happen in methods: - /// 1. [`GetFile`] - /// - /// [`GetFile`]: crate::requests::GetFile - #[serde(rename = "Bad Request: wrong file id")] - WrongFileID, - - /// Occurs when bot tries to do some with group which was deactivated. - #[serde(rename = "Bad Request: group is deactivated")] - GroupDeactivated, - - /// Occurs when bot tries to set chat photo from file ID - /// - /// May happen in methods: - /// 1. [`SetChatPhoto`] - /// - /// [`SetChatPhoto`]: crate::requests::SetChatPhoto - #[serde(rename = "Bad Request: Photo should be uploaded as an InputFile")] - PhotoAsInputFileRequired, - - /// Occurs when bot tries to add sticker to stickerset by invalid name. - /// - /// May happen in methods: - /// 1. [`AddStickerToSet`] - /// - /// [`AddStickerToSet`]: crate::requests::AddStickerToSet - #[serde(rename = "Bad Request: STICKERSET_INVALID")] - InvalidStickersSet, - - /// Occurs when bot tries to pin a message without rights to pin in this - /// chat. - /// - /// May happen in methods: - /// 1. [`PinChatMessage`] - /// - /// [`PinChatMessage`]: crate::requests::PinChatMessage - #[serde(rename = "Bad Request: not enough rights to pin a message")] - NotEnoughRightsToPinMessage, - - /// Occurs when bot tries to use method in group which is allowed only in a - /// supergroup or channel. - #[serde(rename = "Bad Request: method is available only for supergroups and channel")] - MethodNotAvailableInPrivateChats, - - /// Occurs when bot tries to demote chat creator. - /// - /// May happen in methods: - /// 1. [`PromoteChatMember`] - /// - /// [`PromoteChatMember`]: crate::requests::PromoteChatMember - #[serde(rename = "Bad Request: can't demote chat creator")] - CantDemoteChatCreator, - - /// Occurs when bot tries to restrict self in group chats. - /// - /// May happen in methods: - /// 1. [`RestrictChatMember`] - /// - /// [`RestrictChatMember`]: crate::requests::RestrictChatMember - #[serde(rename = "Bad Request: can't restrict self")] - CantRestrictSelf, - - /// Occurs when bot tries to restrict chat member without rights to - /// restrict in this chat. - /// - /// May happen in methods: - /// 1. [`RestrictChatMember`] - /// - /// [`RestrictChatMember`]: crate::requests::RestrictChatMember - #[serde(rename = "Bad Request: not enough rights to restrict/unrestrict chat member")] - NotEnoughRightsToRestrict, - - /// Occurs when bot tries set webhook to protocol other than HTTPS. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::requests::SetWebhook - #[serde(rename = "Bad Request: bad webhook: HTTPS url must be provided for webhook")] - WebhookRequireHTTPS, - - /// Occurs when bot tries to set webhook to port other than 80, 88, 443 or - /// 8443. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::requests::SetWebhook - #[serde(rename = "Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 \ - or 8443")] - BadWebhookPort, - - /// Occurs when bot tries to set webhook to unknown host. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::requests::SetWebhook - #[serde(rename = "Bad Request: bad webhook: Failed to resolve host: Name or service not known")] - UnknownHost, - - /// Occurs when bot tries to set webhook to invalid URL. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::requests::SetWebhook - #[serde(rename = "Bad Request: can't parse URL")] - CantParseUrl, - - /// Occurs when bot tries to send message with unfinished entities. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: can't parse entities")] - CantParseEntities, - - /// Occurs when bot tries to use getUpdates while webhook is active. - /// - /// May happen in methods: - /// 1. [`GetUpdates`] - /// - /// [`GetUpdates`]: crate::requests::GetUpdates - #[serde(rename = "can't use getUpdates method while webhook is active")] - CantGetUpdates, - - /// Occurs when bot tries to do some in group where bot was kicked. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Unauthorized: bot was kicked from a chat")] - BotKicked, - - /// Occurs when bot tries to send message to deactivated user. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Unauthorized: user is deactivated")] - UserDeactivated, - - /// Occurs when you tries to initiate conversation with a user. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Unauthorized: bot can't initiate conversation with a user")] - CantInitiateConversation, - - /// Occurs when you tries to send message to bot. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Unauthorized: bot can't send messages to bots")] - CantTalkWithBots, - - /// Occurs when bot tries to send button with invalid http url. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::requests::SendMessage - #[serde(rename = "Bad Request: wrong HTTP URL")] - WrongHTTPurl, - - /// Occurs when bot tries GetUpdate before the timeout. Make sure that only - /// one Updater is running. - /// - /// May happen in methods: - /// 1. [`GetUpdates`] - /// - /// [`GetUpdates`]: crate::requests::GetUpdates - #[serde(rename = "Conflict: terminated by other getUpdates request; make sure that only one \ - bot instance is running")] - TerminatedByOtherGetUpdates, - - /// Occurs when bot tries to get file by invalid file id. - /// - /// May happen in methods: - /// 1. [`GetFile`] - /// - /// [`GetFile`]: crate::requests::GetFile - #[serde(rename = "Bad Request: invalid file id")] - FileIdInvalid, -} diff --git a/src/lib.rs b/src/lib.rs index 8639abd6..47f37e90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,25 +51,22 @@ // FIXME(waffle): use `docsrs` here when issue with combine is resolved #![cfg_attr(all(teloxide_docsrs, feature = "nightly"), feature(doc_cfg))] -pub use bot::{Bot, BotBuilder}; pub use dispatching::repls::{ commands_repl, commands_repl_with_listener, dialogues_repl, dialogues_repl_with_listener, repl, repl_with_listener, }; -pub use errors::{ApiErrorKind, DownloadError, KnownApiErrorKind, RequestError}; +pub use teloxide_core::{ApiError, DownloadError, RequestError}; -mod errors; -mod net; +mod logging; -mod bot; pub mod dispatching; pub mod error_handlers; -mod logging; pub mod prelude; -pub mod requests; -pub mod types; pub mod utils; +pub use teloxide_core as core; + +use teloxide_core::requests::ResponseResult; #[cfg(feature = "macros")] // FIXME(waffle): use `docsrs` here when issue with combine is resolved #[cfg_attr(all(teloxide_docsrs, feature = "nightly"), doc(cfg(feature = "macros")))] @@ -78,3 +75,8 @@ pub use teloxide_macros::teloxide; #[cfg(all(feature = "nightly", doctest))] #[doc(include = "../README.md")] enum ReadmeDocTests {} + +/// A shortcut for `ResponseResult::Ok(val)`. +pub fn respond(val: T) -> ResponseResult { + ResponseResult::Ok(val) +} diff --git a/src/net/download.rs b/src/net/download.rs deleted file mode 100644 index 6f9c87b0..00000000 --- a/src/net/download.rs +++ /dev/null @@ -1,51 +0,0 @@ -use reqwest::Client; -use tokio::io::{AsyncWrite, AsyncWriteExt}; - -use crate::errors::DownloadError; - -use super::TELEGRAM_API_URL; - -pub async fn download_file( - client: &Client, - token: &str, - path: &str, - destination: &mut D, -) -> Result<(), DownloadError> -where - D: AsyncWrite + Unpin, -{ - let mut res = client - .get(&super::file_url(TELEGRAM_API_URL, token, path)) - .send() - .await? - .error_for_status()?; - - while let Some(chunk) = res.chunk().await? { - destination.write_all(&chunk).await?; - } - - Ok(()) -} - -#[cfg(feature = "unstable-stream")] -// FIXME(waffle): use `docsrs` here when issue with combine is resolved -#[cfg_attr(all(teloxide_docsrs, feature = "nightly"), doc(cfg(feature = "unstable-stream")))] -pub async fn download_file_stream( - client: &Client, - token: &str, - path: &str, -) -> Result>, reqwest::Error> { - let res = client - .get(&super::file_url(TELEGRAM_API_URL, token, path)) - .send() - .await? - .error_for_status()?; - - Ok(futures::stream::unfold(res, |mut res| async { - match res.chunk().await { - Err(err) => Some((Err(err), res)), - Ok(Some(c)) => Some((Ok(c), res)), - Ok(None) => None, - } - })) -} diff --git a/src/net/mod.rs b/src/net/mod.rs deleted file mode 100644 index 118b6036..00000000 --- a/src/net/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -#[cfg(feature = "unstable-stream")] -// FIXME(waffle): use `docsrs` here when issue with combine is resolved -#[cfg_attr(all(teloxide_docsrs, feature = "nightly"), doc(cfg(feature = "unstable-stream")))] -pub use download::download_file_stream; - -pub use self::{ - download::download_file, - request::{request_json, request_multipart}, - telegram_response::TelegramResponse, -}; - -mod download; -mod request; -mod telegram_response; - -const TELEGRAM_API_URL: &str = "https://api.telegram.org"; - -/// Creates URL for making HTTPS requests. See the [Telegram documentation]. -/// -/// [Telegram documentation]: https://core.telegram.org/bots/api#making-requests -fn method_url(base: &str, token: &str, method_name: &str) -> String { - format!("{url}/bot{token}/{method}", url = base, token = token, method = method_name,) -} - -/// Creates URL for downloading a file. See the [Telegram documentation]. -/// -/// [Telegram documentation]: https://core.telegram.org/bots/api#file -fn file_url(base: &str, token: &str, file_path: &str) -> String { - format!("{url}/file/bot{token}/{file}", url = base, token = token, file = file_path,) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn method_url_test() { - let url = method_url( - TELEGRAM_API_URL, - "535362388:AAF7-g0gYncWnm5IyfZlpPRqRRv6kNAGlao", - "methodName", - ); - - assert_eq!( - url, - "https://api.telegram.org/bot535362388:AAF7-g0gYncWnm5IyfZlpPRqRRv6kNAGlao/methodName" - ); - } - - #[test] - fn file_url_test() { - let url = file_url( - TELEGRAM_API_URL, - "535362388:AAF7-g0gYncWnm5IyfZlpPRqRRv6kNAGlao", - "AgADAgADyqoxG2g8aEsu_KjjVsGF4-zetw8ABAEAAwIAA20AA_8QAwABFgQ", - ); - - assert_eq!( - url, - "https://api.telegram.org/file/bot535362388:AAF7-g0gYncWnm5IyfZlpPRqRRv6kNAGlao/AgADAgADyqoxG2g8aEsu_KjjVsGF4-zetw8ABAEAAwIAA20AA_8QAwABFgQ" - ); - } -} diff --git a/src/net/request.rs b/src/net/request.rs deleted file mode 100644 index 05f0af5e..00000000 --- a/src/net/request.rs +++ /dev/null @@ -1,63 +0,0 @@ -use reqwest::{multipart::Form, Client, Response}; -use serde::{de::DeserializeOwned, Serialize}; - -use crate::{requests::ResponseResult, RequestError}; - -use super::{TelegramResponse, TELEGRAM_API_URL}; -use std::time::Duration; - -const DELAY_ON_SERVER_ERROR: Duration = Duration::from_secs(10); - -pub async fn request_multipart( - client: &Client, - token: &str, - method_name: &str, - params: Form, -) -> ResponseResult -where - T: DeserializeOwned, -{ - let response = client - .post(&super::method_url(TELEGRAM_API_URL, token, method_name)) - .multipart(params) - .send() - .await - .map_err(RequestError::NetworkError)?; - - process_response(response).await -} - -pub async fn request_json( - client: &Client, - token: &str, - method_name: &str, - params: &P, -) -> ResponseResult -where - T: DeserializeOwned, - P: Serialize, -{ - let response = client - .post(&super::method_url(TELEGRAM_API_URL, token, method_name)) - .json(params) - .send() - .await - .map_err(RequestError::NetworkError)?; - - process_response(response).await -} - -async fn process_response(response: Response) -> ResponseResult -where - T: DeserializeOwned, -{ - if response.status().is_server_error() { - tokio::time::sleep(DELAY_ON_SERVER_ERROR).await; - } - - serde_json::from_str::>( - &response.text().await.map_err(RequestError::NetworkError)?, - ) - .map_err(RequestError::InvalidJson)? - .into() -} diff --git a/src/net/telegram_response.rs b/src/net/telegram_response.rs deleted file mode 100644 index d5062e8f..00000000 --- a/src/net/telegram_response.rs +++ /dev/null @@ -1,70 +0,0 @@ -use reqwest::StatusCode; -use serde::Deserialize; - -use crate::{ - requests::ResponseResult, - types::{False, ResponseParameters, True}, - ApiErrorKind, RequestError, -}; - -#[derive(Deserialize)] -#[serde(untagged)] -pub enum TelegramResponse { - Ok { - /// A dummy field. Used only for deserialization. - #[allow(dead_code)] - ok: True, - - result: R, - }, - Err { - /// A dummy field. Used only for deserialization. - #[allow(dead_code)] - ok: False, - - #[serde(rename = "description")] - kind: ApiErrorKind, - error_code: u16, - response_parameters: Option, - }, -} - -impl Into> for TelegramResponse { - fn into(self) -> Result { - match self { - TelegramResponse::Ok { result, .. } => Ok(result), - TelegramResponse::Err { kind, error_code, response_parameters, .. } => { - if let Some(params) = response_parameters { - match params { - ResponseParameters::RetryAfter(i) => Err(RequestError::RetryAfter(i)), - ResponseParameters::MigrateToChatId(to) => { - Err(RequestError::MigrateToChatId(to)) - } - } - } else { - Err(RequestError::ApiError { - kind, - status_code: StatusCode::from_u16(error_code).unwrap(), - }) - } - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{errors::KnownApiErrorKind, types::Update}; - - #[test] - fn terminated_by_other_get_updates() { - let expected = ApiErrorKind::Known(KnownApiErrorKind::TerminatedByOtherGetUpdates); - if let TelegramResponse::Err{ kind, .. } = serde_json::from_str::>(r#"{"ok":false,"error_code":409,"description":"Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"}"#).unwrap() { - assert_eq!(expected, kind); - } - else { - panic!("Expected ApiErrorKind::TerminatedByOtherGetUpdates"); - } - } -} diff --git a/src/prelude.rs b/src/prelude.rs index 61773b4e..1a5741e7 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -9,9 +9,16 @@ pub use crate::{ Dispatcher, DispatcherHandlerRx, DispatcherHandlerRxExt, UpdateWithCx, }, error_handlers::{LoggingErrorHandler, OnError}, - requests::{respond, Request, ResponseResult}, + respond, +}; + +pub use teloxide_core::prelude::*; + +pub use teloxide_core::{ + adaptors::AutoSend, + requests::{Request, ResponseResult}, types::{Message, Update}, - Bot, RequestError, + RequestError, }; #[cfg(feature = "frunk")] diff --git a/src/requests/all/add_sticker_to_set.rs b/src/requests/all/add_sticker_to_set.rs deleted file mode 100644 index 8cc0188f..00000000 --- a/src/requests/all/add_sticker_to_set.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::{ - net, - requests::form_builder::FormBuilder, - types::{MaskPosition, True}, - Bot, -}; - -use crate::{ - requests::{RequestWithFile, ResponseResult}, - types::StickerType, -}; - -/// Use this method to add a new sticker to a set created by the bot. -/// -/// [The official docs](https://core.telegram.org/bots/api#addstickertoset). -#[derive(Debug, Clone)] -pub struct AddStickerToSet { - bot: Bot, - user_id: i32, - name: String, - sticker_type: StickerType, - emojis: String, - mask_position: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for AddStickerToSet { - type Output = True; - - async fn send(&self) -> tokio::io::Result> { - let builder = - FormBuilder::new().add_text("user_id", &self.user_id).add_text("name", &self.name); - - let builder = match &self.sticker_type { - StickerType::Png(file) => builder.add_input_file("png_sticker", &file), - StickerType::Tgs(file) => builder.add_input_file("tgs_sticker", &file), - } - .await? - .add_text("emojis", &self.emojis) - .add_text("mask_position", &self.mask_position); - - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "addStickerToSet", - builder.build(), - ) - .await) - } -} - -impl AddStickerToSet { - pub(crate) fn new( - bot: Bot, - user_id: i32, - name: N, - sticker_type: StickerType, - emojis: E, - ) -> Self - where - N: Into, - E: Into, - { - Self { - bot, - user_id, - name: name.into(), - sticker_type, - emojis: emojis.into(), - mask_position: None, - } - } - - /// User identifier of sticker set owner. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// Sticker set name. - pub fn name(mut self, val: T) -> Self - where - T: Into, - { - self.name = val.into(); - self - } - - pub fn sticker_type(mut self, val: StickerType) -> Self { - self.sticker_type = val; - self - } - - /// One or more emoji corresponding to the sticker. - pub fn emojis(mut self, val: T) -> Self - where - T: Into, - { - self.emojis = val.into(); - self - } - - /// A JSON-serialized object for position where the mask should be placed on - /// faces. - pub fn mask_position(mut self, val: MaskPosition) -> Self { - self.mask_position = Some(val); - self - } -} diff --git a/src/requests/all/answer_callback_query.rs b/src/requests/all/answer_callback_query.rs deleted file mode 100644 index c74b1e88..00000000 --- a/src/requests/all/answer_callback_query.rs +++ /dev/null @@ -1,101 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::True, - Bot, -}; - -/// Use this method to send answers to callback queries sent from [inline -/// keyboards]. -/// -/// The answer will be displayed to the user as a notification at -/// the top of the chat screen or as an alert. -/// -/// [The official docs](https://core.telegram.org/bots/api#answercallbackquery). -/// -/// [inline keyboards]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct AnswerCallbackQuery { - #[serde(skip_serializing)] - bot: Bot, - callback_query_id: String, - text: Option, - show_alert: Option, - url: Option, - cache_time: Option, -} - -#[async_trait::async_trait] -impl Request for AnswerCallbackQuery { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "answerCallbackQuery", &self).await - } -} - -impl AnswerCallbackQuery { - pub(crate) fn new(bot: Bot, callback_query_id: C) -> Self - where - C: Into, - { - let callback_query_id = callback_query_id.into(); - Self { bot, callback_query_id, text: None, show_alert: None, url: None, cache_time: None } - } - - /// Unique identifier for the query to be answered. - pub fn callback_query_id(mut self, val: T) -> Self - where - T: Into, - { - self.callback_query_id = val.into(); - self - } - - /// Text of the notification. If not specified, nothing will be shown to the - /// user, 0-200 characters. - pub fn text(mut self, val: T) -> Self - where - T: Into, - { - self.text = Some(val.into()); - self - } - - /// If `true`, an alert will be shown by the client instead of a - /// notification at the top of the chat screen. Defaults to `false`. - pub fn show_alert(mut self, val: bool) -> Self { - self.show_alert = Some(val); - self - } - - /// URL that will be opened by the user's client. If you have created a - /// [`Game`] and accepted the conditions via [@Botfather], specify the - /// URL that opens your game – note that this will only work if the - /// query comes from a [`callback_game`] button. - /// - /// Otherwise, you may use links like `t.me/your_bot?start=XXXX` that open - /// your bot with a parameter. - /// - /// [@Botfather]: https://t.me/botfather - /// [`callback_game`]: crate::types::InlineKeyboardButton - /// [`Game`]: crate::types::Game - pub fn url(mut self, val: T) -> Self - where - T: Into, - { - self.url = Some(val.into()); - self - } - - /// The maximum amount of time in seconds that the result of the callback - /// query may be cached client-side. Telegram apps will support caching - /// starting in version 3.14. Defaults to 0. - pub fn cache_time(mut self, val: i32) -> Self { - self.cache_time = Some(val); - self - } -} diff --git a/src/requests/all/answer_inline_query.rs b/src/requests/all/answer_inline_query.rs deleted file mode 100644 index dd1b6a38..00000000 --- a/src/requests/all/answer_inline_query.rs +++ /dev/null @@ -1,146 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineQueryResult, True}, - Bot, -}; - -/// Use this method to send answers to an inline query. -/// -/// No more than **50** results per query are allowed. -/// -/// [The official docs](https://core.telegram.org/bots/api#answerinlinequery). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct AnswerInlineQuery { - #[serde(skip_serializing)] - bot: Bot, - inline_query_id: String, - results: Vec, - cache_time: Option, - is_personal: Option, - next_offset: Option, - switch_pm_text: Option, - switch_pm_parameter: Option, -} - -#[async_trait::async_trait] -impl Request for AnswerInlineQuery { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "answerInlineQuery", &self).await - } -} - -impl AnswerInlineQuery { - pub(crate) fn new(bot: Bot, inline_query_id: I, results: R) -> Self - where - I: Into, - R: Into>, - { - let inline_query_id = inline_query_id.into(); - let results = results.into(); - Self { - bot, - inline_query_id, - results, - cache_time: None, - is_personal: None, - next_offset: None, - switch_pm_text: None, - switch_pm_parameter: None, - } - } - - /// Unique identifier for the answered query. - pub fn inline_query_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_query_id = val.into(); - self - } - - /// A JSON-serialized array of results for the inline query. - pub fn results(mut self, val: T) -> Self - where - T: Into>, - { - self.results = val.into(); - self - } - - /// The maximum amount of time in seconds that the result of the inline - /// query may be cached on the server. - /// - /// Defaults to 300. - pub fn cache_time(mut self, val: i32) -> Self { - self.cache_time = Some(val); - self - } - - /// Pass `true`, if results may be cached on the server side only for the - /// user that sent the query. - /// - /// By default, results may be returned to any user who sends the same - /// query. - #[allow(clippy::wrong_self_convention)] - pub fn is_personal(mut self, val: bool) -> Self { - self.is_personal = Some(val); - self - } - - /// Pass the offset that a client should send in the next query with the - /// same text to receive more results. - /// - /// Pass an empty string if there are no more results or if you don‘t - /// support pagination. Offset length can’t exceed 64 bytes. - pub fn next_offset(mut self, val: T) -> Self - where - T: Into, - { - self.next_offset = Some(val.into()); - self - } - - /// If passed, clients will display a button with specified text that - /// switches the user to a private chat with the bot and sends the bot a - /// start message with the parameter [`switch_pm_parameter`]. - /// - /// [`switch_pm_parameter`]: - /// crate::requests::AnswerInlineQuery::switch_pm_parameter - pub fn switch_pm_text(mut self, val: T) -> Self - where - T: Into, - { - self.switch_pm_text = Some(val.into()); - self - } - - /// [Deep-linking] parameter for the /start message sent to the bot when - /// user presses the switch button. 1-64 characters, only `A-Z`, `a-z`, - /// `0-9`, `_` and `-` are allowed. - /// - /// Example: An inline bot that sends YouTube videos can ask the user to - /// connect the bot to their YouTube account to adapt search results - /// accordingly. To do this, it displays a ‘Connect your YouTube account’ - /// button above the results, or even before showing any. The user presses - /// the button, switches to a private chat with the bot and, in doing so, - /// passes a start parameter that instructs the bot to return an oauth link. - /// Once done, the bot can offer a [`switch_inline`] button so that the user - /// can easily return to the chat where they wanted to use the bot's - /// inline capabilities. - /// - /// [Deep-linking]: https://core.telegram.org/bots#deep-linking - /// [`switch_inline`]: crate::types::InlineKeyboardMarkup - pub fn switch_pm_parameter(mut self, val: T) -> Self - where - T: Into, - { - self.switch_pm_parameter = Some(val.into()); - self - } -} diff --git a/src/requests/all/answer_pre_checkout_query.rs b/src/requests/all/answer_pre_checkout_query.rs deleted file mode 100644 index 2ac4df42..00000000 --- a/src/requests/all/answer_pre_checkout_query.rs +++ /dev/null @@ -1,82 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::True, - Bot, -}; - -/// 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. -/// -/// # Note -/// The Bot API must receive an answer within 10 seconds after the pre-checkout -/// query was sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#answerprecheckoutquery). -/// -/// [`Update`]: crate::types::Update -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct AnswerPreCheckoutQuery { - #[serde(skip_serializing)] - bot: Bot, - pre_checkout_query_id: String, - ok: bool, - error_message: Option, -} - -#[async_trait::async_trait] -impl Request for AnswerPreCheckoutQuery { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "answerPreCheckoutQuery", &self) - .await - } -} - -impl AnswerPreCheckoutQuery { - pub(crate) fn new

(bot: Bot, pre_checkout_query_id: P, ok: bool) -> Self - where - P: Into, - { - let pre_checkout_query_id = pre_checkout_query_id.into(); - Self { bot, pre_checkout_query_id, ok, error_message: None } - } - - /// Unique identifier for the query to be answered. - pub fn pre_checkout_query_id(mut self, val: T) -> Self - where - T: Into, - { - self.pre_checkout_query_id = val.into(); - self - } - - /// Specify `true` if everything is alright (goods are available, etc.) and - /// the bot is ready to proceed with the order. Use False if there are any - /// problems. - pub fn ok(mut self, val: bool) -> Self { - self.ok = val; - self - } - - /// Required if ok is `false`. Error message in human readable form that - /// explains the reason for failure to proceed with the checkout (e.g. - /// "Sorry, somebody just bought the last of our amazing black T-shirts - /// while you were busy filling out your payment details. Please choose a - /// different color or garment!"). - /// - /// Telegram will display this message to the user. - pub fn error_message(mut self, val: T) -> Self - where - T: Into, - { - self.error_message = Some(val.into()); - self - } -} diff --git a/src/requests/all/answer_shipping_query.rs b/src/requests/all/answer_shipping_query.rs deleted file mode 100644 index be4d6662..00000000 --- a/src/requests/all/answer_shipping_query.rs +++ /dev/null @@ -1,86 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ShippingOption, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#answershippingquery). -/// -/// [`Update`]: crate::types::Update -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct AnswerShippingQuery { - #[serde(skip_serializing)] - bot: Bot, - shipping_query_id: String, - ok: bool, - shipping_options: Option>, - error_message: Option, -} - -#[async_trait::async_trait] -impl Request for AnswerShippingQuery { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "answerShippingQuery", &self).await - } -} - -impl AnswerShippingQuery { - pub(crate) fn new(bot: Bot, shipping_query_id: S, ok: bool) -> Self - where - S: Into, - { - let shipping_query_id = shipping_query_id.into(); - Self { bot, shipping_query_id, ok, shipping_options: None, error_message: None } - } - - /// Unique identifier for the query to be answered. - pub fn shipping_query_id(mut self, val: T) -> Self - where - T: Into, - { - self.shipping_query_id = val.into(); - self - } - - /// Specify `true` if delivery to the specified address is possible and - /// `false` if there are any problems (for example, if delivery to the - /// specified address is not possible). - pub fn ok(mut self, val: bool) -> Self { - self.ok = val; - self - } - - /// Required if ok is `true`. A JSON-serialized array of available shipping - /// options. - pub fn shipping_options(mut self, val: T) -> Self - where - T: Into>, - { - self.shipping_options = Some(val.into()); - self - } - - /// Required if ok is `false`. Error message in human readable form that - /// explains why it is impossible to complete the order (e.g. "Sorry, - /// delivery to your desired address is unavailable'). - /// - /// Telegram will display this message to the user. - pub fn error_message(mut self, val: T) -> Self - where - T: Into, - { - self.error_message = Some(val.into()); - self - } -} diff --git a/src/requests/all/create_new_sticker_set.rs b/src/requests/all/create_new_sticker_set.rs deleted file mode 100644 index a49cb08b..00000000 --- a/src/requests/all/create_new_sticker_set.rs +++ /dev/null @@ -1,134 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{MaskPosition, StickerType, True}, - Bot, -}; - -/// Use this method to create new sticker set owned by a user. The bot will be -/// able to edit the created sticker set. -/// -/// [The official docs](https://core.telegram.org/bots/api#createnewstickerset). -#[derive(Debug, Clone)] -pub struct CreateNewStickerSet { - bot: Bot, - user_id: i32, - name: String, - title: String, - sticker_type: StickerType, - emojis: String, - contains_masks: Option, - mask_position: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for CreateNewStickerSet { - type Output = True; - - async fn send(&self) -> tokio::io::Result> { - let builder = FormBuilder::new() - .add_text("user_id", &self.user_id) - .add_text("name", &self.name) - .add_text("title", &self.title); - - let builder = match &self.sticker_type { - StickerType::Png(file) => builder.add_input_file("png_sticker", &file), - StickerType::Tgs(file) => builder.add_input_file("tgs_sticker", &file), - } - .await? - .add_text("emojis", &self.emojis) - .add_text("contains_masks", &self.contains_masks) - .add_text("mask_position", &self.mask_position); - - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "createNewStickerSet", - builder.build(), - ) - .await) - } -} - -impl CreateNewStickerSet { - pub(crate) fn new( - bot: Bot, - user_id: i32, - name: N, - title: T, - sticker_type: StickerType, - emojis: E, - ) -> Self - where - N: Into, - T: Into, - E: Into, - { - Self { - bot, - user_id, - name: name.into(), - title: title.into(), - sticker_type, - emojis: emojis.into(), - contains_masks: None, - mask_position: None, - } - } - - /// User identifier of created sticker set owner. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// Short name of sticker set, to be used in `t.me/addstickers/` URLs (e.g., - /// animals). Can contain only english letters, digits and underscores. - /// - /// Must begin with a letter, can't contain consecutive underscores and must - /// end in `_by_`. `` is case insensitive. - /// 1-64 characters. - pub fn name(mut self, val: T) -> Self - where - T: Into, - { - self.name = val.into(); - self - } - - /// Sticker set title, 1-64 characters. - pub fn title(mut self, val: T) -> Self - where - T: Into, - { - self.title = val.into(); - self - } - - pub fn sticker_type(mut self, val: StickerType) -> Self { - self.sticker_type = val; - self - } - - /// One or more emoji corresponding to the sticker. - pub fn emojis(mut self, val: T) -> Self - where - T: Into, - { - self.emojis = val.into(); - self - } - - /// Pass `true`, if a set of mask stickers should be created. - pub fn contains_masks(mut self, val: bool) -> Self { - self.contains_masks = Some(val); - self - } - - /// A JSON-serialized object for position where the mask should be placed on - /// faces. - pub fn mask_position(mut self, val: MaskPosition) -> Self { - self.mask_position = Some(val); - self - } -} diff --git a/src/requests/all/delete_chat_photo.rs b/src/requests/all/delete_chat_photo.rs deleted file mode 100644 index 01439bfa..00000000 --- a/src/requests/all/delete_chat_photo.rs +++ /dev/null @@ -1,50 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#deletechatphoto). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct DeleteChatPhoto { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for DeleteChatPhoto { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "deleteChatPhoto", &self).await - } -} - -impl DeleteChatPhoto { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/delete_chat_sticker_set.rs b/src/requests/all/delete_chat_sticker_set.rs deleted file mode 100644 index 9fe228c5..00000000 --- a/src/requests/all/delete_chat_sticker_set.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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 [`Bot::get_chat`] requests to check if the bot can use this -/// method. -/// -/// [The official docs](https://core.telegram.org/bots/api#deletechatstickerset). -/// -/// [`Bot::get_chat`]: crate::Bot::get_chat -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct DeleteChatStickerSet { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for DeleteChatStickerSet { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "deleteChatStickerSet", &self).await - } -} - -impl DeleteChatStickerSet { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format `@supergroupusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/delete_message.rs b/src/requests/all/delete_message.rs deleted file mode 100644 index 35ead60a..00000000 --- a/src/requests/all/delete_message.rs +++ /dev/null @@ -1,67 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// Use this method to delete a message, including service messages. -/// -/// The limitations are: -/// - A message can only be deleted if it was sent less than 48 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#deletemessage). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct DeleteMessage { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, -} - -#[async_trait::async_trait] -impl Request for DeleteMessage { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "deleteMessage", &self).await - } -} - -impl DeleteMessage { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to delete. - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } -} diff --git a/src/requests/all/delete_sticker_from_set.rs b/src/requests/all/delete_sticker_from_set.rs deleted file mode 100644 index 59269f7a..00000000 --- a/src/requests/all/delete_sticker_from_set.rs +++ /dev/null @@ -1,47 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::True, - Bot, -}; - -/// Use this method to delete a sticker from a set created by the bot. -/// -/// [The official docs](https://core.telegram.org/bots/api#deletestickerfromset). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct DeleteStickerFromSet { - #[serde(skip_serializing)] - bot: Bot, - sticker: String, -} - -#[async_trait::async_trait] -impl Request for DeleteStickerFromSet { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "deleteStickerFromSet", &self).await - } -} - -impl DeleteStickerFromSet { - pub(crate) fn new(bot: Bot, sticker: S) -> Self - where - S: Into, - { - let sticker = sticker.into(); - Self { bot, sticker } - } - - /// File identifier of the sticker. - pub fn sticker(mut self, val: T) -> Self - where - T: Into, - { - self.sticker = val.into(); - self - } -} diff --git a/src/requests/all/delete_webhook.rs b/src/requests/all/delete_webhook.rs deleted file mode 100644 index fd3bd3ba..00000000 --- a/src/requests/all/delete_webhook.rs +++ /dev/null @@ -1,37 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::True, - Bot, -}; - -/// Use this method to remove webhook integration if you decide to switch back -/// to [Bot::get_updates]. -/// -/// [The official docs](https://core.telegram.org/bots/api#deletewebhook). -/// -/// [Bot::get_updates]: crate::Bot::get_updates -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct DeleteWebhook { - #[serde(skip_serializing)] - bot: Bot, -} - -#[async_trait::async_trait] -impl Request for DeleteWebhook { - type Output = True; - - #[allow(clippy::trivially_copy_pass_by_ref)] - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "deleteWebhook", &self).await - } -} - -impl DeleteWebhook { - pub(crate) fn new(bot: Bot) -> Self { - Self { bot } - } -} diff --git a/src/requests/all/edit_inline_message_caption.rs b/src/requests/all/edit_inline_message_caption.rs deleted file mode 100644 index e777f17c..00000000 --- a/src/requests/all/edit_inline_message_caption.rs +++ /dev/null @@ -1,83 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, ParseMode, True}, - Bot, -}; - -/// Use this method to edit captions of messages sent via the bot. -/// -/// On success, [`True`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). -/// -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditInlineMessageCaption { - #[serde(skip_serializing)] - bot: Bot, - inline_message_id: String, - caption: Option, - parse_mode: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditInlineMessageCaption { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageCaption", &self).await - } -} - -impl EditInlineMessageCaption { - pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self - where - I: Into, - { - let inline_message_id = inline_message_id.into(); - Self { bot, inline_message_id, caption: None, parse_mode: None, reply_markup: None } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// New caption of the message. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_inline_message_live_location.rs b/src/requests/all/edit_inline_message_live_location.rs deleted file mode 100644 index 4b267427..00000000 --- a/src/requests/all/edit_inline_message_live_location.rs +++ /dev/null @@ -1,77 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, True}, - Bot, -}; - -/// Use this method to edit live location messages sent via the bot. -/// -/// A location can be edited until its live_period expires or editing is -/// explicitly disabled by a call to stopMessageLiveLocation. On success, -/// [`True`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). -/// -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditInlineMessageLiveLocation { - #[serde(skip_serializing)] - bot: Bot, - inline_message_id: String, - latitude: f32, - longitude: f32, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditInlineMessageLiveLocation { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageLiveLocation", &self) - .await - } -} - -impl EditInlineMessageLiveLocation { - pub(crate) fn new(bot: Bot, inline_message_id: I, latitude: f32, longitude: f32) -> Self - where - I: Into, - { - let inline_message_id = inline_message_id.into(); - Self { bot, inline_message_id, latitude, longitude, reply_markup: None } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// Latitude of new location. - pub fn latitude(mut self, val: f32) -> Self { - self.latitude = val; - self - } - - /// Longitude of new location. - pub fn longitude(mut self, val: f32) -> Self { - self.longitude = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_inline_message_media.rs b/src/requests/all/edit_inline_message_media.rs deleted file mode 100644 index 9a11f126..00000000 --- a/src/requests/all/edit_inline_message_media.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, Request, ResponseResult}, - types::{InlineKeyboardMarkup, InputMedia, True}, - Bot, -}; - -/// Use this method to edit animation, audio, document, photo, or video -/// messages sent via the bot. -/// -/// 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 -/// this method is used, new file can't be uploaded. Use previously -/// uploaded file via its `file_id` or specify a URL. On success, [`True`] is -/// returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). -/// -/// [`True`]: crate::types::True -#[derive(Debug, Clone)] -pub struct EditInlineMessageMedia { - bot: Bot, - inline_message_id: String, - media: InputMedia, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditInlineMessageMedia { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_multipart( - self.bot.client(), - self.bot.token(), - "editMessageMedia", - FormBuilder::new() - .add_text("media", &self.media) - .add_text("reply_markup", &self.reply_markup) - .add_text("inline_message_id", &self.inline_message_id) - .build(), - ) - .await - } -} - -impl EditInlineMessageMedia { - pub(crate) fn new(bot: Bot, inline_message_id: I, media: InputMedia) -> Self - where - I: Into, - { - let inline_message_id = inline_message_id.into(); - Self { bot, inline_message_id, media, reply_markup: None } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// A JSON-serialized object for a new media content of the message. - pub fn media(mut self, val: InputMedia) -> Self { - self.media = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_inline_message_reply_markup.rs b/src/requests/all/edit_inline_message_reply_markup.rs deleted file mode 100644 index cd96c686..00000000 --- a/src/requests/all/edit_inline_message_reply_markup.rs +++ /dev/null @@ -1,62 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, True}, - Bot, -}; - -/// Use this method to edit only the reply markup of messages sent via the bot. -/// -/// On success, [`True`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). -/// -/// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditInlineMessageReplyMarkup { - #[serde(skip_serializing)] - bot: Bot, - inline_message_id: String, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditInlineMessageReplyMarkup { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageReplyMarkup", &self) - .await - } -} - -impl EditInlineMessageReplyMarkup { - pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self - where - I: Into, - { - let inline_message_id = inline_message_id.into(); - Self { bot, inline_message_id, reply_markup: None } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_inline_message_text.rs b/src/requests/all/edit_inline_message_text.rs deleted file mode 100644 index 2b266314..00000000 --- a/src/requests/all/edit_inline_message_text.rs +++ /dev/null @@ -1,98 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, Message, ParseMode}, - Bot, -}; - -/// Use this method to edit text and game messages sent via the bot. -/// -/// On success, [`True`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagetext). -/// -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditInlineMessageText { - #[serde(skip_serializing)] - bot: Bot, - inline_message_id: String, - text: String, - parse_mode: Option, - disable_web_page_preview: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditInlineMessageText { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageText", &self).await - } -} - -impl EditInlineMessageText { - pub(crate) fn new(bot: Bot, inline_message_id: I, text: T) -> Self - where - I: Into, - T: Into, - { - let inline_message_id = inline_message_id.into(); - let text = text.into(); - Self { - bot, - inline_message_id, - text, - parse_mode: None, - disable_web_page_preview: None, - reply_markup: None, - } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// New text of the message. - pub fn text(mut self, val: T) -> Self - where - T: Into, - { - self.text = val.into(); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in your bot's message. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Disables link previews for links in this message. - pub fn disable_web_page_preview(mut self, val: bool) -> Self { - self.disable_web_page_preview = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_message_caption.rs b/src/requests/all/edit_message_caption.rs deleted file mode 100644 index 9294af93..00000000 --- a/src/requests/all/edit_message_caption.rs +++ /dev/null @@ -1,91 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Message, ParseMode}, - Bot, -}; - -/// Use this method to edit captions of messages sent by the bot. -/// -/// On success, the edited [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). -/// -/// [`Message`]: crate::types::Message -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditMessageCaption { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - caption: Option, - parse_mode: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditMessageCaption { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageCaption", &self).await - } -} - -impl EditMessageCaption { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, caption: None, parse_mode: None, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// New caption of the message. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_message_live_location.rs b/src/requests/all/edit_message_live_location.rs deleted file mode 100644 index c5afd295..00000000 --- a/src/requests/all/edit_message_live_location.rs +++ /dev/null @@ -1,91 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Message}, - Bot, -}; - -/// 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, the -/// edited [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagelivelocation). -/// -/// [`Message`]: crate::types::Message -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditMessageLiveLocation { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - latitude: f32, - longitude: f32, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditMessageLiveLocation { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageLiveLocation", &self) - .await - } -} - -impl EditMessageLiveLocation { - pub(crate) fn new( - bot: Bot, - chat_id: C, - message_id: i32, - latitude: f32, - longitude: f32, - ) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, latitude, longitude, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// Latitude of new location. - pub fn latitude(mut self, val: f32) -> Self { - self.latitude = val; - self - } - - /// Longitude of new location. - pub fn longitude(mut self, val: f32) -> Self { - self.longitude = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_message_media.rs b/src/requests/all/edit_message_media.rs deleted file mode 100644 index 7f15ed5f..00000000 --- a/src/requests/all/edit_message_media.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, InputMedia, Message}, - Bot, -}; - -/// 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. On -/// success, the edited [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagemedia). -/// -/// [`Message`]: crate::types::Message -#[derive(Debug, Clone)] -pub struct EditMessageMedia { - bot: Bot, - chat_id: ChatId, - message_id: i32, - media: InputMedia, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditMessageMedia { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_multipart( - self.bot.client(), - self.bot.token(), - "editMessageMedia", - FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_text("message_id", &self.message_id) - .add_text("media", &self.media) - .add_text("reply_markup", &self.reply_markup) - .build(), - ) - .await - } -} - -impl EditMessageMedia { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32, media: InputMedia) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, media, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// A JSON-serialized object for a new media content of the message. - pub fn media(mut self, val: InputMedia) -> Self { - self.media = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_message_reply_markup.rs b/src/requests/all/edit_message_reply_markup.rs deleted file mode 100644 index 66aab5bf..00000000 --- a/src/requests/all/edit_message_reply_markup.rs +++ /dev/null @@ -1,69 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Message}, - Bot, -}; - -/// Use this method to edit only the reply markup of messages. -/// -/// On success, the edited [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagereplymarkup). -/// -/// [`Message`]: crate::types::Message -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditMessageReplyMarkup { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditMessageReplyMarkup { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageReplyMarkup", &self) - .await - } -} - -impl EditMessageReplyMarkup { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/edit_message_text.rs b/src/requests/all/edit_message_text.rs deleted file mode 100644 index 12251313..00000000 --- a/src/requests/all/edit_message_text.rs +++ /dev/null @@ -1,107 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Message, ParseMode}, - Bot, -}; - -/// Use this method to edit text and game messages. -/// -/// On success, the edited [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#editmessagetext). -/// -/// [`Message`]: crate::types::Message -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct EditMessageText { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - text: String, - parse_mode: Option, - disable_web_page_preview: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for EditMessageText { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "editMessageText", &self).await - } -} - -impl EditMessageText { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32, text: T) -> Self - where - C: Into, - T: Into, - { - let chat_id = chat_id.into(); - let text = text.into(); - Self { - bot, - chat_id, - message_id, - text, - parse_mode: None, - disable_web_page_preview: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// New text of the message. - pub fn text(mut self, val: T) -> Self - where - T: Into, - { - self.text = val.into(); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in your bot's message. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Disables link previews for links in this message. - pub fn disable_web_page_preview(mut self, val: bool) -> Self { - self.disable_web_page_preview = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/export_chat_invite_link.rs b/src/requests/all/export_chat_invite_link.rs deleted file mode 100644 index 51a26437..00000000 --- a/src/requests/all/export_chat_invite_link.rs +++ /dev/null @@ -1,65 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::ChatId, - Bot, -}; - -/// 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. -/// -/// ## 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 -/// [`Bot::export_chat_invite_link`] – after this the link will become available -/// to the bot via the [`Bot::get_chat`] method. If your bot needs to generate a -/// new invite link replacing its previous one, use -/// [`Bot::export_chat_invite_link`] again. -/// -/// [The official docs](https://core.telegram.org/bots/api#exportchatinvitelink). -/// -/// [`Bot::export_chat_invite_link`]: crate::Bot::export_chat_invite_link -/// [`Bot::get_chat`]: crate::Bot::get_chat -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct ExportChatInviteLink { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for ExportChatInviteLink { - type Output = String; - - /// Returns the new invite link as `String` on success. - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "exportChatInviteLink", &self).await - } -} - -impl ExportChatInviteLink { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/forward_message.rs b/src/requests/all/forward_message.rs deleted file mode 100644 index feb9ec02..00000000 --- a/src/requests/all/forward_message.rs +++ /dev/null @@ -1,81 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message}, - Bot, -}; - -/// Use this method to forward messages of any kind. -/// -/// [`The official docs`](https://core.telegram.org/bots/api#forwardmessage). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct ForwardMessage { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - from_chat_id: ChatId, - disable_notification: Option, - message_id: i32, -} - -#[async_trait::async_trait] -impl Request for ForwardMessage { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "forwardMessage", &self).await - } -} - -impl ForwardMessage { - pub(crate) fn new(bot: Bot, chat_id: C, from_chat_id: F, message_id: i32) -> Self - where - C: Into, - F: Into, - { - let chat_id = chat_id.into(); - let from_chat_id = from_chat_id.into(); - Self { bot, chat_id, from_chat_id, message_id, disable_notification: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier for the chat where the original message was sent (or - /// channel username in the format `@channelusername`). - #[allow(clippy::wrong_self_convention)] - pub fn from_chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.from_chat_id = val.into(); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// Message identifier in the chat specified in [`from_chat_id`]. - /// - /// [`from_chat_id`]: ForwardMessage::from_chat_id - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } -} diff --git a/src/requests/all/get_chat.rs b/src/requests/all/get_chat.rs deleted file mode 100644 index 11406776..00000000 --- a/src/requests/all/get_chat.rs +++ /dev/null @@ -1,50 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{Chat, ChatId}, - Bot, -}; - -/// 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.). -/// -/// [The official docs](https://core.telegram.org/bots/api#getchat). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetChat { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for GetChat { - type Output = Chat; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getChat", &self).await - } -} - -impl GetChat { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/get_chat_administrators.rs b/src/requests/all/get_chat_administrators.rs deleted file mode 100644 index 06657ec5..00000000 --- a/src/requests/all/get_chat_administrators.rs +++ /dev/null @@ -1,53 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, ChatMember}, - Bot, -}; - -/// Use this method to get a list of administrators in a chat. -/// -/// If the chat is a group or a supergroup and no administrators were appointed, -/// only the creator will be returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#getchatadministrators). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetChatAdministrators { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for GetChatAdministrators { - type Output = Vec; - - /// On success, returns an array that contains information about all chat - /// administrators except other bots. - async fn send(&self) -> ResponseResult> { - net::request_json(self.bot.client(), self.bot.token(), "getChatAdministrators", &self).await - } -} - -impl GetChatAdministrators { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/get_chat_member.rs b/src/requests/all/get_chat_member.rs deleted file mode 100644 index 4ebe3f56..00000000 --- a/src/requests/all/get_chat_member.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, ChatMember}, - Bot, -}; - -/// Use this method to get information about a member of a chat. -/// -/// [The official docs](https://core.telegram.org/bots/api#getchatmember). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetChatMember { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, -} - -#[async_trait::async_trait] -impl Request for GetChatMember { - type Output = ChatMember; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getChatMember", &self).await - } -} - -impl GetChatMember { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, user_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } -} diff --git a/src/requests/all/get_chat_members_count.rs b/src/requests/all/get_chat_members_count.rs deleted file mode 100644 index 5c78596b..00000000 --- a/src/requests/all/get_chat_members_count.rs +++ /dev/null @@ -1,48 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::ChatId, - Bot, -}; - -/// Use this method to get the number of members in a chat. -/// -/// [The official docs](https://core.telegram.org/bots/api#getchatmemberscount). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetChatMembersCount { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for GetChatMembersCount { - type Output = i32; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getChatMembersCount", &self).await - } -} - -impl GetChatMembersCount { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/get_file.rs b/src/requests/all/get_file.rs deleted file mode 100644 index d2d0556c..00000000 --- a/src/requests/all/get_file.rs +++ /dev/null @@ -1,62 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::File, - Bot, -}; - -/// 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. -/// -/// The file can then be downloaded via the link -/// `https://api.telegram.org/file/bot/`, where `` -/// 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 [`GetFile`] again. -/// -/// **Note**: This function may not preserve the original file name and MIME -/// type. You should save the file's MIME type and name (if available) when the -/// [`File`] object is received. -/// -/// [The official docs](https://core.telegram.org/bots/api#getfile). -/// -/// [`File`]: crate::types::File -/// [`GetFile`]: self::GetFile -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetFile { - #[serde(skip_serializing)] - bot: Bot, - file_id: String, -} - -#[async_trait::async_trait] -impl Request for GetFile { - type Output = File; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getFile", &self).await - } -} - -impl GetFile { - pub(crate) fn new(bot: Bot, file_id: F) -> Self - where - F: Into, - { - Self { bot, file_id: file_id.into() } - } - - /// File identifier to get info about. - pub fn file_id(mut self, value: F) -> Self - where - F: Into, - { - self.file_id = value.into(); - self - } -} diff --git a/src/requests/all/get_game_high_scores.rs b/src/requests/all/get_game_high_scores.rs deleted file mode 100644 index 1a43d63e..00000000 --- a/src/requests/all/get_game_high_scores.rs +++ /dev/null @@ -1,63 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{GameHighScore, TargetMessage}, - Bot, -}; - -/// 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. -/// -/// ## Note -/// This method will currently return scores for the target user, plus two of -/// his closest neighbors on each side. Will also return the top three users if -/// the user and his neighbors are not among them. Please note that this -/// behavior is subject to change. -/// -/// [The official docs](https://core.telegram.org/bots/api#getgamehighscores) -#[derive(Debug, Clone, Serialize)] -pub struct GetGameHighScores { - #[serde(skip_serializing)] - bot: Bot, - #[serde(flatten)] - target: TargetMessage, - user_id: i32, -} - -#[async_trait::async_trait] -impl Request for GetGameHighScores { - type Output = Vec; - - async fn send(&self) -> ResponseResult> { - net::request_json(self.bot.client(), self.bot.token(), "getGameHighScores", &self).await - } -} - -impl GetGameHighScores { - pub(crate) fn new(bot: Bot, target: T, user_id: i32) -> Self - where - T: Into, - { - let target = target.into(); - Self { bot, target, user_id } - } - - /// Target message, either chat id and message id or inline message id. - pub fn target(mut self, val: T) -> Self - where - T: Into, - { - self.target = val.into(); - self - } - - /// Target user id. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } -} diff --git a/src/requests/all/get_me.rs b/src/requests/all/get_me.rs deleted file mode 100644 index 567b4375..00000000 --- a/src/requests/all/get_me.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::{ - net, - requests::{Request, ResponseResult}, - types::Me, - Bot, -}; -use serde::Serialize; - -/// A simple method for testing your bot's auth token. Requires no parameters. -/// -/// [The official docs](https://core.telegram.org/bots/api#getme). -#[derive(Debug, Clone, Serialize)] -pub struct GetMe { - #[serde(skip_serializing)] - bot: Bot, -} - -#[async_trait::async_trait] -impl Request for GetMe { - type Output = Me; - - /// Returns basic information about the bot. - #[allow(clippy::trivially_copy_pass_by_ref)] - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getMe", &self).await - } -} - -impl GetMe { - pub(crate) fn new(bot: Bot) -> Self { - Self { bot } - } -} diff --git a/src/requests/all/get_my_commands.rs b/src/requests/all/get_my_commands.rs deleted file mode 100644 index 586bfa28..00000000 --- a/src/requests/all/get_my_commands.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::BotCommand, - Bot, -}; - -/// Use this method to get the current list of the bot's commands. -/// -/// [The official docs](https://core.telegram.org/bots/api#getmycommands). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetMyCommands { - #[serde(skip_serializing)] - bot: Bot, -} - -#[async_trait::async_trait] -impl Request for GetMyCommands { - type Output = Vec; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getMyCommands", &self).await - } -} - -impl GetMyCommands { - pub(crate) fn new(bot: Bot) -> Self { - Self { bot } - } -} diff --git a/src/requests/all/get_sticker_set.rs b/src/requests/all/get_sticker_set.rs deleted file mode 100644 index a8a83bea..00000000 --- a/src/requests/all/get_sticker_set.rs +++ /dev/null @@ -1,47 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::StickerSet, - Bot, -}; - -/// Use this method to get a sticker set. -/// -/// [The official docs](https://core.telegram.org/bots/api#getstickerset). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetStickerSet { - #[serde(skip_serializing)] - bot: Bot, - name: String, -} - -#[async_trait::async_trait] -impl Request for GetStickerSet { - type Output = StickerSet; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getStickerSet", &self).await - } -} - -impl GetStickerSet { - pub(crate) fn new(bot: Bot, name: N) -> Self - where - N: Into, - { - let name = name.into(); - Self { bot, name } - } - - /// Name of the sticker set. - pub fn name(mut self, val: T) -> Self - where - T: Into, - { - self.name = val.into(); - self - } -} diff --git a/src/requests/all/get_updates.rs b/src/requests/all/get_updates.rs deleted file mode 100644 index 8bc2db59..00000000 --- a/src/requests/all/get_updates.rs +++ /dev/null @@ -1,122 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{AllowedUpdate, Update}, - Bot, RequestError, -}; -use serde_json::Value; - -/// Use this method to receive incoming updates using long polling ([wiki]). -/// -/// **Notes:** -/// 1. This method will not work if an outgoing webhook is set up. -/// 2. In order to avoid getting duplicate updates, -/// recalculate offset after each server response. -/// -/// [The official docs](https://core.telegram.org/bots/api#getupdates). -/// -/// [wiki]: https://en.wikipedia.org/wiki/Push_technology#Long_polling -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetUpdates { - #[serde(skip_serializing)] - bot: Bot, - pub(crate) offset: Option, - pub(crate) limit: Option, - pub(crate) timeout: Option, - pub(crate) allowed_updates: Option>, -} - -#[async_trait::async_trait] -impl Request for GetUpdates { - type Output = Vec>; - - /// Deserialize to `Vec>` instead of - /// `Vec`, because we want to parse the rest of updates even if our - /// library hasn't parsed one. - async fn send(&self) -> ResponseResult>> { - let value: Value = - net::request_json(self.bot.client(), self.bot.token(), "getUpdates", &self).await?; - - match value { - Value::Array(array) => Ok(array - .into_iter() - .map(|value| Update::try_parse(&value).map_err(|error| (value, error))) - .collect()), - _ => Err(RequestError::InvalidJson( - serde_json::from_value::>(value) - .expect_err("get_update must return Value::Array"), - )), - } - } -} - -impl GetUpdates { - pub(crate) fn new(bot: Bot) -> Self { - Self { bot, offset: None, limit: None, timeout: None, allowed_updates: None } - } - - /// Identifier of the first update to be returned. - /// - /// Must be greater by one than the highest among the identifiers of - /// previously received updates. By default, updates starting with the - /// earliest unconfirmed update are returned. An update is considered - /// confirmed as soon as [`GetUpdates`] is called with an [`offset`] - /// higher than its [`id`]. The negative offset can be specified to - /// retrieve updates starting from `-offset` update from the end of the - /// updates queue. All previous updates will forgotten. - /// - /// [`GetUpdates`]: self::GetUpdates - /// [`offset`]: self::GetUpdates::offset - /// [`id`]: crate::types::Update::id - pub fn offset(mut self, value: i32) -> Self { - self.offset = Some(value); - self - } - - /// Limits the number of updates to be retrieved. - /// - /// Values between `1`—`100` are accepted. Defaults to `100`. - pub fn limit(mut self, value: u8) -> Self { - self.limit = Some(value); - self - } - - /// Timeout in seconds for long polling. - /// - /// Defaults to `0`, i.e. usual short polling. Should be positive, short - /// polling should be used for testing purposes only. - pub fn timeout(mut self, value: u32) -> Self { - self.timeout = Some(value); - self - } - - /// List the types of updates you want your bot to receive. - /// - /// For example, specify [[`Message`], [`EditedChannelPost`], - /// [`CallbackQuery`]] to only receive updates of these types. - /// See [`AllowedUpdate`] for a complete list of available update types. - /// - /// Specify an empty list to receive all updates regardless of type - /// (default). If not specified, the previous setting will be used. - /// - /// **Note:** - /// This parameter doesn't affect updates created before the call to the - /// [`Bot::get_updates`], so unwanted updates may be received for a short - /// period of time. - /// - /// [`Message`]: self::AllowedUpdate::Message - /// [`EditedChannelPost`]: self::AllowedUpdate::EditedChannelPost - /// [`CallbackQuery`]: self::AllowedUpdate::CallbackQuery - /// [`AllowedUpdate`]: self::AllowedUpdate - /// [`Bot::get_updates`]: crate::Bot::get_updates - pub fn allowed_updates(mut self, value: T) -> Self - where - T: Into>, - { - self.allowed_updates = Some(value.into()); - self - } -} diff --git a/src/requests/all/get_user_profile_photos.rs b/src/requests/all/get_user_profile_photos.rs deleted file mode 100644 index 663a07a4..00000000 --- a/src/requests/all/get_user_profile_photos.rs +++ /dev/null @@ -1,58 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::UserProfilePhotos, - Bot, -}; - -/// Use this method to get a list of profile pictures for a user. -/// -/// [The official docs](https://core.telegram.org/bots/api#getuserprofilephotos). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct GetUserProfilePhotos { - #[serde(skip_serializing)] - bot: Bot, - user_id: i32, - offset: Option, - limit: Option, -} - -#[async_trait::async_trait] -impl Request for GetUserProfilePhotos { - type Output = UserProfilePhotos; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getUserProfilePhotos", &self).await - } -} - -impl GetUserProfilePhotos { - pub(crate) fn new(bot: Bot, user_id: i32) -> Self { - Self { bot, user_id, offset: None, limit: None } - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// Sequential number of the first photo to be returned. By default, all - /// photos are returned. - pub fn offset(mut self, val: i32) -> Self { - self.offset = Some(val); - self - } - - /// Limits the number of photos to be retrieved. Values between 1—100 are - /// accepted. - /// - /// Defaults to 100. - pub fn limit(mut self, val: i32) -> Self { - self.limit = Some(val); - self - } -} diff --git a/src/requests/all/get_webhook_info.rs b/src/requests/all/get_webhook_info.rs deleted file mode 100644 index 51424471..00000000 --- a/src/requests/all/get_webhook_info.rs +++ /dev/null @@ -1,38 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::WebhookInfo, - Bot, -}; - -/// Use this method to get current webhook status. -/// -/// If the bot is using [`Bot::get_updates`], will return an object with the url -/// field empty. -/// -/// [The official docs](https://core.telegram.org/bots/api#getwebhookinfo). -/// -/// [`Bot::get_updates`]: crate::Bot::get_updates -#[derive(Debug, Clone, Serialize)] -pub struct GetWebhookInfo { - #[serde(skip_serializing)] - bot: Bot, -} - -#[async_trait::async_trait] -impl Request for GetWebhookInfo { - type Output = WebhookInfo; - - #[allow(clippy::trivially_copy_pass_by_ref)] - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "getWebhookInfo", &self).await - } -} - -impl GetWebhookInfo { - pub(crate) fn new(bot: Bot) -> Self { - Self { bot } - } -} diff --git a/src/requests/all/kick_chat_member.rs b/src/requests/all/kick_chat_member.rs deleted file mode 100644 index 31953949..00000000 --- a/src/requests/all/kick_chat_member.rs +++ /dev/null @@ -1,72 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#kickchatmember). -/// -/// [unbanned]: crate::Bot::unban_chat_member -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct KickChatMember { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, - until_date: Option, -} - -#[async_trait::async_trait] -impl Request for KickChatMember { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "kickChatMember", &self).await - } -} - -impl KickChatMember { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, user_id, until_date: None } - } - - /// Unique identifier for the target group or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// Date when the user will be unbanned, unix time. - /// - /// If user is banned for more than 366 days or less than 30 seconds from - /// the current time they are considered to be banned forever. - pub fn until_date(mut self, val: i32) -> Self { - self.until_date = Some(val); - self - } -} diff --git a/src/requests/all/leave_chat.rs b/src/requests/all/leave_chat.rs deleted file mode 100644 index d0411efb..00000000 --- a/src/requests/all/leave_chat.rs +++ /dev/null @@ -1,48 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// Use this method for your bot to leave a group, supergroup or channel. -/// -/// [The official docs](https://core.telegram.org/bots/api#leavechat). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct LeaveChat { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for LeaveChat { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "leaveChat", &self).await - } -} - -impl LeaveChat { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup or channel (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/mod.rs b/src/requests/all/mod.rs deleted file mode 100644 index 3de4d87a..00000000 --- a/src/requests/all/mod.rs +++ /dev/null @@ -1,152 +0,0 @@ -mod add_sticker_to_set; -mod answer_callback_query; -mod answer_inline_query; -mod answer_pre_checkout_query; -mod answer_shipping_query; -mod create_new_sticker_set; -mod delete_chat_photo; -mod delete_chat_sticker_set; -mod delete_message; -mod delete_sticker_from_set; -mod delete_webhook; -mod edit_inline_message_caption; -mod edit_inline_message_live_location; -mod edit_inline_message_media; -mod edit_inline_message_reply_markup; -mod edit_inline_message_text; -mod edit_message_caption; -mod edit_message_live_location; -mod edit_message_media; -mod edit_message_reply_markup; -mod edit_message_text; -mod export_chat_invite_link; -mod forward_message; -mod get_chat; -mod get_chat_administrators; -mod get_chat_member; -mod get_chat_members_count; -mod get_file; -mod get_game_high_scores; -mod get_me; -mod get_my_commands; -mod get_sticker_set; -mod get_updates; -mod get_user_profile_photos; -mod get_webhook_info; -mod kick_chat_member; -mod leave_chat; -mod pin_chat_message; -mod promote_chat_member; -mod restrict_chat_member; -mod send_animation; -mod send_audio; -mod send_chat_action; -mod send_contact; -mod send_dice; -mod send_document; -mod send_game; -mod send_invoice; -mod send_location; -mod send_media_group; -mod send_message; -mod send_photo; -mod send_poll; -mod send_sticker; -mod send_venue; -mod send_video; -mod send_video_note; -mod send_voice; -mod set_chat_administrator_custom_title; -mod set_chat_description; -mod set_chat_permissions; -mod set_chat_photo; -mod set_chat_sticker_set; -mod set_chat_title; -mod set_game_score; -mod set_my_commands; -mod set_sticker_position_in_set; -mod set_sticker_set_thumb; -mod set_webhook; -mod stop_inline_message_live_location; -mod stop_message_live_location; -mod stop_poll; -mod unban_chat_member; -mod unpin_chat_message; -mod upload_sticker_file; - -pub use add_sticker_to_set::*; -pub use answer_callback_query::*; -pub use answer_inline_query::*; -pub use answer_pre_checkout_query::*; -pub use answer_shipping_query::*; -pub use create_new_sticker_set::*; -pub use delete_chat_photo::*; -pub use delete_chat_sticker_set::*; -pub use delete_message::*; -pub use delete_sticker_from_set::*; -pub use delete_webhook::*; -pub use edit_inline_message_caption::*; -pub use edit_inline_message_live_location::*; -pub use edit_inline_message_media::*; -pub use edit_inline_message_reply_markup::*; -pub use edit_inline_message_text::*; -pub use edit_message_caption::*; -pub use edit_message_live_location::*; -pub use edit_message_media::*; -pub use edit_message_reply_markup::*; -pub use edit_message_text::*; -pub use export_chat_invite_link::*; -pub use forward_message::*; -pub use get_chat::*; -pub use get_chat_administrators::*; -pub use get_chat_member::*; -pub use get_chat_members_count::*; -pub use get_file::*; -pub use get_game_high_scores::*; -pub use get_me::*; -pub use get_my_commands::*; -pub use get_sticker_set::*; -pub use get_updates::*; -pub use get_user_profile_photos::*; -pub use get_webhook_info::*; -pub use kick_chat_member::*; -pub use leave_chat::*; -pub use pin_chat_message::*; -pub use promote_chat_member::*; -pub use restrict_chat_member::*; -pub use send_animation::*; -pub use send_audio::*; -pub use send_chat_action::*; -pub use send_contact::*; -pub use send_dice::*; -pub use send_document::*; -pub use send_game::*; -pub use send_invoice::*; -pub use send_location::*; -pub use send_media_group::*; -pub use send_message::*; -pub use send_photo::*; -pub use send_poll::*; -pub use send_sticker::*; -pub use send_venue::*; -pub use send_video::*; -pub use send_video_note::*; -pub use send_voice::*; -pub use set_chat_administrator_custom_title::*; -pub use set_chat_description::*; -pub use set_chat_permissions::*; -pub use set_chat_photo::*; -pub use set_chat_sticker_set::*; -pub use set_chat_title::*; -pub use set_game_score::*; -pub use set_my_commands::*; -pub use set_sticker_position_in_set::*; -pub use set_sticker_set_thumb::*; -pub use set_webhook::*; -pub use std::pin::Pin; -pub use stop_inline_message_live_location::*; -pub use stop_message_live_location::*; -pub use stop_poll::*; -pub use unban_chat_member::*; -pub use unpin_chat_message::*; -pub use upload_sticker_file::*; diff --git a/src/requests/all/pin_chat_message.rs b/src/requests/all/pin_chat_message.rs deleted file mode 100644 index ae1f3227..00000000 --- a/src/requests/all/pin_chat_message.rs +++ /dev/null @@ -1,69 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#pinchatmessage). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct PinChatMessage { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - disable_notification: Option, -} - -#[async_trait::async_trait] -impl Request for PinChatMessage { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "pinChatMessage", &self).await - } -} - -impl PinChatMessage { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, disable_notification: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of a message to pin. - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// Pass `true`, if it is not necessary to send a notification to all chat - /// members about the new pinned message. - /// - /// Notifications are always disabled in channels. - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } -} diff --git a/src/requests/all/promote_chat_member.rs b/src/requests/all/promote_chat_member.rs deleted file mode 100644 index 468b3c48..00000000 --- a/src/requests/all/promote_chat_member.rs +++ /dev/null @@ -1,134 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#promotechatmember). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct PromoteChatMember { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, - can_change_info: Option, - can_post_messages: Option, - can_edit_messages: Option, - can_delete_messages: Option, - can_invite_users: Option, - can_restrict_members: Option, - can_pin_messages: Option, - can_promote_members: Option, -} - -#[async_trait::async_trait] -impl Request for PromoteChatMember { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "promoteChatMember", &self).await - } -} - -impl PromoteChatMember { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { - bot, - chat_id, - user_id, - can_change_info: None, - can_post_messages: None, - can_edit_messages: None, - can_delete_messages: None, - can_invite_users: None, - can_restrict_members: None, - can_pin_messages: None, - can_promote_members: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// Pass `true`, if the administrator can change chat title, photo and other - /// settings. - pub fn can_change_info(mut self, val: bool) -> Self { - self.can_change_info = Some(val); - self - } - - /// Pass `true`, if the administrator can create channel posts, channels - /// only. - pub fn can_post_messages(mut self, val: bool) -> Self { - self.can_post_messages = Some(val); - self - } - - /// Pass `true`, if the administrator can edit messages of other users and - /// can pin messages, channels only. - pub fn can_edit_messages(mut self, val: bool) -> Self { - self.can_edit_messages = Some(val); - self - } - - /// Pass `true`, if the administrator can delete messages of other users. - pub fn can_delete_messages(mut self, val: bool) -> Self { - self.can_delete_messages = Some(val); - self - } - - /// Pass `true`, if the administrator can invite new users to the chat. - pub fn can_invite_users(mut self, val: bool) -> Self { - self.can_invite_users = Some(val); - self - } - - /// Pass `true`, if the administrator can restrict, ban or unban chat - /// members. - pub fn can_restrict_members(mut self, val: bool) -> Self { - self.can_restrict_members = Some(val); - self - } - - /// Pass `true`, if the administrator can pin messages, supergroups only. - pub fn can_pin_messages(mut self, val: bool) -> Self { - self.can_pin_messages = Some(val); - self - } - - /// Pass `true`, if the administrator can add new administrators with a - /// subset of his own privileges or demote administrators that he has - /// promoted, directly or indirectly (promoted by administrators that were - /// appointed by him). - pub fn can_promote_members(mut self, val: bool) -> Self { - self.can_promote_members = Some(val); - self - } -} diff --git a/src/requests/all/restrict_chat_member.rs b/src/requests/all/restrict_chat_member.rs deleted file mode 100644 index 6b825b91..00000000 --- a/src/requests/all/restrict_chat_member.rs +++ /dev/null @@ -1,76 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, ChatPermissions, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#restrictchatmember). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct RestrictChatMember { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, - permissions: ChatPermissions, - until_date: Option, -} - -#[async_trait::async_trait] -impl Request for RestrictChatMember { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "restrictChatMember", &self).await - } -} - -impl RestrictChatMember { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32, permissions: ChatPermissions) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, user_id, permissions, until_date: None } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format `@supergroupusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// New user permissions. - pub fn permissions(mut self, val: ChatPermissions) -> Self { - self.permissions = val; - self - } - - /// Date when restrictions will be lifted for the user, unix time. - /// - /// If user is restricted for more than 366 days or less than 30 seconds - /// from the current time, they are considered to be restricted forever. - pub fn until_date(mut self, val: i32) -> Self { - self.until_date = Some(val); - self - } -} diff --git a/src/requests/all/send_animation.rs b/src/requests/all/send_animation.rs deleted file mode 100644 index df52f20c..00000000 --- a/src/requests/all/send_animation.rs +++ /dev/null @@ -1,193 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video -/// without sound). -/// -/// Bots can currently send animation files of up to 50 MB in size, this limit -/// may be changed in the future. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendanimation). -#[derive(Debug, Clone)] -pub struct SendAnimation { - bot: Bot, - pub chat_id: ChatId, - pub animation: InputFile, - pub duration: Option, - pub width: Option, - pub height: Option, - pub thumb: Option, - pub caption: Option, - pub parse_mode: Option, - pub disable_notification: Option, - pub reply_to_message_id: Option, - pub reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendAnimation { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - let mut builder = FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("animation", &self.animation) - .await? - .add_text("duration", &self.duration) - .add_text("width", &self.width) - .add_text("height", &self.height) - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup); - if let Some(thumb) = self.thumb.as_ref() { - builder = builder.add_input_file("thumb", thumb).await?; - } - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendAnimation", - builder.build(), - ) - .await) - } -} - -impl SendAnimation { - pub(crate) fn new(bot: Bot, chat_id: C, animation: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - animation, - duration: None, - width: None, - height: None, - thumb: None, - caption: None, - parse_mode: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, value: T) -> Self - where - T: Into, - { - self.chat_id = value.into(); - self - } - - /// Animation to send. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn animation(mut self, val: InputFile) -> Self { - self.animation = val; - self - } - - /// Duration of sent animation in seconds. - pub fn duration(mut self, value: u32) -> Self { - self.duration = Some(value); - self - } - - /// Animation width. - pub fn width(mut self, value: u32) -> Self { - self.width = Some(value); - self - } - - /// Animation height. - pub fn height(mut self, value: u32) -> Self { - self.height = Some(value); - self - } - - /// Thumbnail of the file sent; can be ignored if thumbnail generation for - /// the file is supported server-side. - /// - /// The thumbnail should be in JPEG format and less than 200kB in size. A - /// thumbnail‘s width and height should not exceed 320. Ignored if the - /// animation is not uploaded using [`InputFile::File`] or - /// [`InputFile::Memory`]. Thumbnails can’t be reused and can be only - /// uploaded as a new file. Pass [`InputFile::File`] to upload a file from - /// the file system or [`InputFile::Memory`] to upload a file from memory. - /// [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn thumb(mut self, value: InputFile) -> Self { - self.thumb = Some(value); - self - } - - /// Animation caption, `0`-`1024` characters. - pub fn caption(mut self, value: T) -> Self - where - T: Into, - { - self.caption = Some(value.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, value: ParseMode) -> Self { - self.parse_mode = Some(value); - self - } - - /// Sends the message silently. Users will receive a notification with no - /// sound. - pub fn disable_notification(mut self, value: bool) -> Self { - self.disable_notification = Some(value); - self - } - - /// If the message is a reply, [id] of the original message. - /// - /// [id]: crate::types::Message::id - pub fn reply_to_message_id(mut self, value: i32) -> Self { - self.reply_to_message_id = Some(value); - self - } - - /// Additional interface options. - pub fn reply_markup(mut self, value: T) -> Self - where - T: Into, - { - self.reply_markup = Some(value.into()); - self - } -} diff --git a/src/requests/all/send_audio.rs b/src/requests/all/send_audio.rs deleted file mode 100644 index 4d9d751a..00000000 --- a/src/requests/all/send_audio.rs +++ /dev/null @@ -1,206 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// 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. Bots can currently send audio -/// files of up to 50 MB in size, this limit may be changed in the future. -/// -/// For sending voice messages, use the [`Bot::send_voice`] method instead. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendaudio). -/// -/// [`Bot::send_voice`]: crate::Bot::send_voice -#[derive(Debug, Clone)] -pub struct SendAudio { - bot: Bot, - chat_id: ChatId, - audio: InputFile, - caption: Option, - parse_mode: Option, - duration: Option, - performer: Option, - title: Option, - thumb: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendAudio { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - let mut builder = FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("audio", &self.audio) - .await? - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("duration", &self.duration) - .add_text("performer", &self.performer) - .add_text("title", &self.title) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup); - if let Some(thumb) = self.thumb.as_ref() { - builder = builder.add_input_file("thumb", thumb).await?; - } - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendAudio", - builder.build(), - ) - .await) - } -} - -impl SendAudio { - pub(crate) fn new(bot: Bot, chat_id: C, audio: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - audio, - caption: None, - parse_mode: None, - duration: None, - performer: None, - title: None, - thumb: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Audio file to send. - /// - /// Pass [`InputFile::FileId`] to send an audio file that exists on the - /// Telegram servers (recommended), pass an [`InputFile::Url`] for Telegram - /// to get a file from the Internet (20MB max.), pass [`InputFile::File`] - /// to upload a file from the file system or [`InputFile::Memory`] to - /// upload a file from memory (50MB max. each). - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn audio(mut self, val: InputFile) -> Self { - self.audio = val; - self - } - - /// Audio caption, 0-1024 characters. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Duration of the audio in seconds. - pub fn duration(mut self, val: i32) -> Self { - self.duration = Some(val); - self - } - - /// Performer. - pub fn performer(mut self, val: T) -> Self - where - T: Into, - { - self.performer = Some(val.into()); - self - } - - /// Track name. - pub fn title(mut self, val: T) -> Self - where - T: Into, - { - self.title = Some(val.into()); - self - } - - /// Thumbnail of the file sent; can be ignored if thumbnail generation for - /// the file is supported server-side. - /// - /// The thumbnail should be in JPEG format and less than 200kB in size. A - /// thumbnail‘s width and height should not exceed 320. Ignored if the - /// audio file is not uploaded using [`InputFile::File`] or - /// [`InputFile::Memory`]. Thumbnails can’t be reused and can be only - /// uploaded as a new file. Pass [`InputFile::File`] to upload a file from - /// the file system or [`InputFile::Memory`] to upload a file from memory. - /// [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. A JSON-serialized object for an [inline - /// keyboard], [custom reply keyboard], instructions to remove reply - /// keyboard or to force a reply from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_chat_action.rs b/src/requests/all/send_chat_action.rs deleted file mode 100644 index 5fe853b2..00000000 --- a/src/requests/all/send_chat_action.rs +++ /dev/null @@ -1,105 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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). -/// -/// ## Note -/// Example: The [ImageBot] needs some time to process a request and upload the -/// image. Instead of sending a text message along the lines of “Retrieving -/// image, please wait…”, the bot may use [`Bot::send_chat_action`] with `action -/// = upload_photo`. The user will see a `sending photo` status for the bot. -/// -/// We only recommend using this method when a response from the bot will take a -/// **noticeable** amount of time to arrive. -/// -/// [ImageBot]: https://t.me/imagebot -/// [`Bot::send_chat_action`]: crate::Bot::send_chat_action -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendChatAction { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - action: SendChatActionKind, -} - -/// A type of action used in [`SendChatAction`]. -/// -/// [`SendChatAction`]: crate::requests::SendChatAction -#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum SendChatActionKind { - /// For [text messages](crate::Bot::send_message). - Typing, - - /// For [photos](crate::Bot::send_photo). - UploadPhoto, - - /// For [videos](crate::Bot::send_video). - RecordVideo, - - /// For [videos](crate::Bot::send_video). - UploadVideo, - - /// For [audio files](crate::Bot::send_audio). - RecordAudio, - - /// For [audio files](crate::Bot::send_audio). - UploadAudio, - - /// For [general files](crate::Bot::send_document). - UploadDocument, - - /// For [location data](crate::Bot::send_location). - FindLocation, - - /// For [video notes](crate::Bot::send_video_note). - RecordVideoNote, - - /// For [video notes](crate::Bot::send_video_note). - UploadVideoNote, -} - -#[async_trait::async_trait] -impl Request for SendChatAction { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendChatAction", &self).await - } -} - -impl SendChatAction { - pub(crate) fn new(bot: Bot, chat_id: C, action: SendChatActionKind) -> Self - where - C: Into, - { - Self { bot, chat_id: chat_id.into(), action } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Type of action to broadcast. - pub fn action(mut self, val: SendChatActionKind) -> Self { - self.action = val; - self - } -} diff --git a/src/requests/all/send_contact.rs b/src/requests/all/send_contact.rs deleted file mode 100644 index ef3ff034..00000000 --- a/src/requests/all/send_contact.rs +++ /dev/null @@ -1,129 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message, ReplyMarkup}, - Bot, -}; - -/// Use this method to send phone contacts. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendcontact). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendContact { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - phone_number: String, - first_name: String, - last_name: Option, - vcard: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendContact { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendContact", &self).await - } -} - -impl SendContact { - pub(crate) fn new(bot: Bot, chat_id: C, phone_number: P, first_name: F) -> Self - where - C: Into, - P: Into, - F: Into, - { - let chat_id = chat_id.into(); - let phone_number = phone_number.into(); - let first_name = first_name.into(); - Self { - bot, - chat_id, - phone_number, - first_name, - last_name: None, - vcard: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Contact's phone number. - pub fn phone_number(mut self, val: T) -> Self - where - T: Into, - { - self.phone_number = val.into(); - self - } - - /// Contact's first name. - pub fn first_name(mut self, val: T) -> Self - where - T: Into, - { - self.first_name = val.into(); - self - } - - /// Contact's last name. - pub fn last_name(mut self, val: T) -> Self - where - T: Into, - { - self.last_name = Some(val.into()); - self - } - - /// Additional data about the contact in the form of a [vCard], 0-2048 - /// bytes. - /// - /// [vCard]: https://en.wikipedia.org/wiki/VCard - pub fn vcard(mut self, val: T) -> Self - where - T: Into, - { - self.vcard = Some(val.into()); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_dice.rs b/src/requests/all/send_dice.rs deleted file mode 100644 index 663d7001..00000000 --- a/src/requests/all/send_dice.rs +++ /dev/null @@ -1,94 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, DiceEmoji, Message, ReplyMarkup}, - Bot, -}; - -/// Use this method to send an animated emoji that will display a random value. -/// -/// [The official docs](https://core.telegram.org/bots/api#senddice). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendDice { - #[serde(skip_serializing)] - bot: Bot, - - chat_id: ChatId, - #[serde(flatten)] - emoji: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendDice { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendDice", &self).await - } -} - -impl SendDice { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - emoji: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, value: T) -> Self - where - T: Into, - { - self.chat_id = value.into(); - self - } - - /// Emoji on which the dice throw animation is based. - pub fn emoji(mut self, val: DiceEmoji) -> Self { - self.emoji = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, value: bool) -> Self { - self.disable_notification = Some(value); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, value: i32) -> Self { - self.reply_to_message_id = Some(value); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_document.rs b/src/requests/all/send_document.rs deleted file mode 100644 index 3bed2c65..00000000 --- a/src/requests/all/send_document.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// Use this method to send general files. -/// -/// Bots can currently send files of any type of up to 50 MB in size, this limit -/// may be changed in the future. -/// -/// [The official docs](https://core.telegram.org/bots/api#senddocument). -#[derive(Debug, Clone)] -pub struct SendDocument { - bot: Bot, - chat_id: ChatId, - document: InputFile, - thumb: Option, - caption: Option, - parse_mode: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendDocument { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - let mut builder = FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("document", &self.document) - .await? - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup); - if let Some(thumb) = self.thumb.as_ref() { - builder = builder.add_input_file("thumb", thumb).await?; - } - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendDocument", - builder.build(), - ) - .await) - } -} - -impl SendDocument { - pub(crate) fn new(bot: Bot, chat_id: C, document: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - document, - thumb: None, - caption: None, - parse_mode: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// File to send. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn document(mut self, val: InputFile) -> Self { - self.document = val; - self - } - - /// Thumbnail of the file sent; can be ignored if thumbnail generation for - /// the file is supported server-side. - /// - /// The thumbnail should be in JPEG format and less than 200kB in size. A - /// thumbnail‘s width and height should not exceed 320. Ignored if the - /// document is not uploaded using [`InputFile::File`] or - /// [`InputFile::Memory`]. Thumbnails can’t be reused and can be only - /// uploaded as a new file. Pass [`InputFile::File`] to upload a file from - /// the file system or [`InputFile::Memory`] to upload a file from memory. - /// [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - /// Document caption (may also be used when resending documents by - /// `file_id`), 0-1024 characters. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_game.rs b/src/requests/all/send_game.rs deleted file mode 100644 index 03a0b0e2..00000000 --- a/src/requests/all/send_game.rs +++ /dev/null @@ -1,92 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, Message}, - Bot, -}; - -/// Use this method to send a game. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendgame). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendGame { - #[serde(skip_serializing)] - bot: Bot, - chat_id: i32, - game_short_name: String, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendGame { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendGame", &self).await - } -} - -impl SendGame { - pub(crate) fn new(bot: Bot, chat_id: i32, game_short_name: G) -> Self - where - G: Into, - { - let game_short_name = game_short_name.into(); - Self { - bot, - chat_id, - game_short_name, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat. - pub fn chat_id(mut self, val: i32) -> Self { - self.chat_id = val; - self - } - - /// Short name of the game, serves as the unique identifier for the game. - /// Set up your games via [@Botfather]. - /// - /// [@Botfather]: https://t.me/botfather - pub fn game_short_name(mut self, val: T) -> Self - where - T: Into, - { - self.game_short_name = val.into(); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. If empty, one `Play - /// game_title` button will be shown. If not empty, the first button must - /// launch the game. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_invoice.rs b/src/requests/all/send_invoice.rs deleted file mode 100644 index 8466cdba..00000000 --- a/src/requests/all/send_invoice.rs +++ /dev/null @@ -1,299 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, LabeledPrice, Message}, - Bot, -}; - -/// Use this method to send invoices. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendinvoice). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendInvoice { - #[serde(skip_serializing)] - bot: Bot, - chat_id: i32, - title: String, - description: String, - payload: String, - provider_token: String, - start_parameter: String, - currency: String, - prices: Vec, - provider_data: Option, - photo_url: Option, - photo_size: Option, - photo_width: Option, - photo_height: Option, - need_name: Option, - need_phone_number: Option, - need_email: Option, - need_shipping_address: Option, - send_phone_number_to_provider: Option, - send_email_to_provider: Option, - is_flexible: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendInvoice { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendInvoice", &self).await - } -} - -impl SendInvoice { - #[allow(clippy::too_many_arguments)] - pub(crate) fn new( - bot: Bot, - chat_id: i32, - title: T, - description: D, - payload: Pl, - provider_token: Pt, - start_parameter: S, - currency: C, - prices: Pr, - ) -> Self - where - T: Into, - D: Into, - Pl: Into, - Pt: Into, - S: Into, - C: Into, - Pr: Into>, - { - let title = title.into(); - let description = description.into(); - let payload = payload.into(); - let provider_token = provider_token.into(); - let start_parameter = start_parameter.into(); - let currency = currency.into(); - let prices = prices.into(); - Self { - bot, - chat_id, - title, - description, - payload, - provider_token, - start_parameter, - currency, - prices, - provider_data: None, - photo_url: None, - photo_size: None, - photo_width: None, - photo_height: None, - need_name: None, - need_phone_number: None, - need_email: None, - need_shipping_address: None, - send_phone_number_to_provider: None, - send_email_to_provider: None, - is_flexible: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target private chat. - pub fn chat_id(mut self, val: i32) -> Self { - self.chat_id = val; - self - } - - /// Product name, 1-32 characters. - pub fn title(mut self, val: T) -> Self - where - T: Into, - { - self.title = val.into(); - self - } - - /// Product description, 1-255 characters. - pub fn description(mut self, val: T) -> Self - where - T: Into, - { - self.description = val.into(); - self - } - - /// Bot-defined invoice payload, 1-128 bytes. This will not be displayed to - /// the user, use for your internal processes. - pub fn payload(mut self, val: T) -> Self - where - T: Into, - { - self.payload = val.into(); - self - } - - /// Payments provider token, obtained via [@Botfather]. - /// - /// [@Botfather]: https://t.me/botfather - pub fn provider_token(mut self, val: T) -> Self - where - T: Into, - { - self.provider_token = val.into(); - self - } - - /// Unique deep-linking parameter that can be used to generate this invoice - /// when used as a start parameter. - pub fn start_parameter(mut self, val: T) -> Self - where - T: Into, - { - self.start_parameter = val.into(); - self - } - - /// Three-letter ISO 4217 currency code, see [more on currencies]. - /// - /// [more on currencies]: https://core.telegram.org/bots/payments#supported-currencies - pub fn currency(mut self, val: T) -> Self - where - T: Into, - { - self.currency = val.into(); - self - } - - /// Price breakdown, a list of components (e.g. product price, tax, - /// discount, delivery cost, delivery tax, bonus, etc.). - pub fn prices(mut self, val: T) -> Self - where - T: Into>, - { - self.prices = val.into(); - self - } - - /// JSON-encoded data about the invoice, which will be shared with the - /// payment provider. - /// - /// A detailed description of required fields should be provided by the - /// payment provider. - pub fn provider_data(mut self, val: T) -> Self - where - T: Into, - { - self.provider_data = Some(val.into()); - self - } - - /// URL of the product photo for the invoice. - /// - /// Can be a photo of the goods or a marketing image for a service. People - /// like it better when they see what they are paying for. - pub fn photo_url(mut self, val: T) -> Self - where - T: Into, - { - self.photo_url = Some(val.into()); - self - } - - /// Photo size. - pub fn photo_size(mut self, val: i32) -> Self { - self.photo_size = Some(val); - self - } - - /// Photo width. - pub fn photo_width(mut self, val: i32) -> Self { - self.photo_width = Some(val); - self - } - - /// Photo height. - pub fn photo_height(mut self, val: i32) -> Self { - self.photo_height = Some(val); - self - } - - /// Pass `true`, if you require the user's full name to complete the order. - pub fn need_name(mut self, val: bool) -> Self { - self.need_name = Some(val); - self - } - - /// Pass `true`, if you require the user's phone number to complete the - /// order. - pub fn need_phone_number(mut self, val: bool) -> Self { - self.need_phone_number = Some(val); - self - } - - /// Pass `true`, if you require the user's email address to complete the - /// order. - pub fn need_email(mut self, val: bool) -> Self { - self.need_email = Some(val); - self - } - - /// Pass `true`, if you require the user's shipping address to complete the - /// order. - pub fn need_shipping_address(mut self, val: bool) -> Self { - self.need_shipping_address = Some(val); - self - } - - /// Pass `true`, if user's phone number should be sent to provider. - pub fn send_phone_number_to_provider(mut self, val: bool) -> Self { - self.send_phone_number_to_provider = Some(val); - self - } - - /// Pass `true`, if user's email address should be sent to provider. - pub fn send_email_to_provider(mut self, val: bool) -> Self { - self.send_email_to_provider = Some(val); - self - } - - /// Pass `true`, if the final price depends on the shipping method. - #[allow(clippy::wrong_self_convention)] - pub fn is_flexible(mut self, val: bool) -> Self { - self.is_flexible = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// If empty, one 'Pay `total price`' button will be shown. If not empty, - /// the first button must be a Pay button. - /// - /// [inlint keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_location.rs b/src/requests/all/send_location.rs deleted file mode 100644 index 20201ad1..00000000 --- a/src/requests/all/send_location.rs +++ /dev/null @@ -1,110 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message, ReplyMarkup}, - Bot, -}; - -/// Use this method to send point on the map. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendlocation). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendLocation { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - latitude: f32, - longitude: f32, - live_period: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendLocation { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendLocation", &self).await - } -} - -impl SendLocation { - pub(crate) fn new(bot: Bot, chat_id: C, latitude: f32, longitude: f32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { - bot, - chat_id, - latitude, - longitude, - live_period: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Latitude of the location. - pub fn latitude(mut self, val: f32) -> Self { - self.latitude = val; - self - } - - /// Longitude of the location. - pub fn longitude(mut self, val: f32) -> Self { - self.longitude = val; - self - } - - /// Period in seconds for which the location will be updated (see [Live - /// Locations], should be between 60 and 86400). - /// - /// [Live Locations]: https://telegram.org/blog/live-locations - pub fn live_period(mut self, val: i64) -> Self { - self.live_period = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// A JSON-serialized object for an [inline keyboard]. - /// - /// If empty, one 'Pay `total price`' button will be shown. If not empty, - /// the first button must be a Pay button. - /// - /// [inlint keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_media_group.rs b/src/requests/all/send_media_group.rs deleted file mode 100644 index 7484fc62..00000000 --- a/src/requests/all/send_media_group.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, Request, ResponseResult}, - types::{ChatId, InputMedia, Message}, - Bot, -}; - -/// Use this method to send a group of photos or videos as an album. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendmediagroup). -#[derive(Debug, Clone)] -pub struct SendMediaGroup { - bot: Bot, - chat_id: ChatId, - media: Vec, // TODO: InputMediaPhoto and InputMediaVideo - disable_notification: Option, - reply_to_message_id: Option, -} - -#[async_trait::async_trait] -impl Request for SendMediaGroup { - type Output = Vec; - - async fn send(&self) -> ResponseResult> { - net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendMediaGroup", - FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_text("media", &self.media) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .build(), - ) - .await - } -} - -impl SendMediaGroup { - pub(crate) fn new(bot: Bot, chat_id: C, media: M) -> Self - where - C: Into, - M: Into>, - { - let chat_id = chat_id.into(); - let media = media.into(); - Self { bot, chat_id, media, disable_notification: None, reply_to_message_id: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// A JSON-serialized array describing photos and videos to be sent, must - /// include 2–10 items. - pub fn media(mut self, val: T) -> Self - where - T: Into>, - { - self.media = val.into(); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the messages are a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } -} diff --git a/src/requests/all/send_message.rs b/src/requests/all/send_message.rs deleted file mode 100644 index 29525cb9..00000000 --- a/src/requests/all/send_message.rs +++ /dev/null @@ -1,121 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// Use this method to send text messages. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendmessage). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendMessage { - #[serde(skip_serializing)] - bot: Bot, - pub chat_id: ChatId, - pub text: String, - pub parse_mode: Option, - pub disable_web_page_preview: Option, - pub disable_notification: Option, - pub reply_to_message_id: Option, - pub reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendMessage { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendMessage", &self).await - } -} - -impl SendMessage { - pub(crate) fn new(bot: Bot, chat_id: C, text: T) -> Self - where - C: Into, - T: Into, - { - Self { - bot, - chat_id: chat_id.into(), - text: text.into(), - parse_mode: None, - disable_web_page_preview: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, value: T) -> Self - where - T: Into, - { - self.chat_id = value.into(); - self - } - - /// Text of the message to be sent. - pub fn text(mut self, value: T) -> Self - where - T: Into, - { - self.text = value.into(); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, value: ParseMode) -> Self { - self.parse_mode = Some(value); - self - } - - /// Disables link previews for links in this message. - pub fn disable_web_page_preview(mut self, value: bool) -> Self { - self.disable_web_page_preview = Some(value); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, value: bool) -> Self { - self.disable_notification = Some(value); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, value: i32) -> Self { - self.reply_to_message_id = Some(value); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, value: T) -> Self - where - T: Into, - { - self.reply_markup = Some(value.into()); - self - } -} diff --git a/src/requests/all/send_photo.rs b/src/requests/all/send_photo.rs deleted file mode 100644 index c66e6f02..00000000 --- a/src/requests/all/send_photo.rs +++ /dev/null @@ -1,140 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// Use this method to send photos. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendphoto). -#[derive(Debug, Clone)] -pub struct SendPhoto { - bot: Bot, - chat_id: ChatId, - photo: InputFile, - caption: Option, - parse_mode: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendPhoto { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendPhoto", - FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("photo", &self.photo) - .await? - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup) - .build(), - ) - .await) - } -} - -impl SendPhoto { - pub(crate) fn new(bot: Bot, chat_id: C, photo: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - photo, - caption: None, - parse_mode: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Photo to send. - /// - /// Pass [`InputFile::FileId`] to send a photo that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// photo from the Internet (5MB max.), pass [`InputFile::File`] to upload - /// a picture from the file system or [`InputFile::Memory`] to upload a - /// photo from memory (10MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn photo(mut self, val: InputFile) -> Self { - self.photo = val; - self - } - - ///Photo caption (may also be used when resending photos by file_id), - /// 0-1024 characters. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. A JSON-serialized object for an [inline - /// keyboard], [custom reply keyboard], instructions to remove reply - /// keyboard or to force a reply from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_poll.rs b/src/requests/all/send_poll.rs deleted file mode 100644 index 3dd412a1..00000000 --- a/src/requests/all/send_poll.rs +++ /dev/null @@ -1,217 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message, ParseMode, PollType, ReplyMarkup}, - Bot, -}; - -/// Use this method to send a native poll. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendpoll). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendPoll { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - question: String, - options: Vec, - is_anonymous: Option, - poll_type: Option, - allows_multiple_answers: Option, - correct_option_id: Option, - explanation: Option, - explanation_parse_mode: Option, - open_period: Option, - close_date: Option, - is_closed: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendPoll { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendPoll", &self).await - } -} - -impl SendPoll { - pub(crate) fn new(bot: Bot, chat_id: C, question: Q, options: O) -> Self - where - C: Into, - Q: Into, - O: Into>, - { - let chat_id = chat_id.into(); - let question = question.into(); - let options = options.into(); - Self { - bot, - chat_id, - question, - options, - is_anonymous: None, - poll_type: None, - allows_multiple_answers: None, - correct_option_id: None, - explanation: None, - explanation_parse_mode: None, - is_closed: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - close_date: None, - open_period: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - /// - /// A native poll can't be sent to a private chat. - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Poll question, 1-255 characters. - pub fn question(mut self, val: T) -> Self - where - T: Into, - { - self.question = val.into(); - self - } - - /// List of answer options, 2-10 strings 1-100 characters each. - pub fn options(mut self, val: T) -> Self - where - T: Into>, - { - self.options = val.into(); - self - } - - /// `true`, if the poll needs to be anonymous, defaults to `true`. - #[allow(clippy::wrong_self_convention)] - pub fn is_anonymous(mut self, val: T) -> Self - where - T: Into, - { - self.is_anonymous = Some(val.into()); - self - } - - /// Poll type, `quiz` or `regular`, defaults to `regular`. - pub fn poll_type(mut self, val: PollType) -> Self { - self.poll_type = Some(val); - self - } - - /// `true`, if the poll allows multiple answers, ignored for polls in quiz - /// mode. - /// - /// Defaults to `false`. - pub fn allows_multiple_answers(mut self, val: T) -> Self - where - T: Into, - { - self.allows_multiple_answers = Some(val.into()); - self - } - - /// 0-based identifier of the correct answer option, required for polls in - /// quiz mode. - pub fn correct_option_id(mut self, val: T) -> Self - where - T: Into, - { - self.correct_option_id = Some(val.into()); - self - } - - /// Text that is shown when a user chooses an incorrect answer or taps on - /// the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line - /// feeds after entities parsing. - pub fn explanation(mut self, val: T) -> Self - where - T: Into, - { - self.explanation = Some(val.into()); - self - } - - /// Mode for parsing entities in the explanation. See [formatting options] - /// for more details. - /// - /// [formatting options]: https://core.telegram.org/bots/api#formatting-options - pub fn explanation_parse_mode(mut self, val: ParseMode) -> Self { - self.explanation_parse_mode = Some(val); - self - } - - /// Amount of time in seconds the poll will be active after creation, 5-600. - /// Can't be used together with `close_date`. - pub fn open_period(mut self, val: i32) -> Self { - self.open_period = Some(val); - self - } - - /// Point in time (Unix timestamp) when the poll will be automatically - /// closed. Must be at least 5 and no more than 600 seconds in the future. - /// Can't be used together with `open_period`. - pub fn close_date(mut self, val: i32) -> Self { - self.close_date = Some(val); - self - } - - /// Pass `true`, if the poll needs to be immediately closed. - /// - /// This can be useful for poll preview. - #[allow(clippy::wrong_self_convention)] - pub fn is_closed(mut self, val: T) -> Self - where - T: Into, - { - self.is_closed = Some(val.into()); - self - } - - /// Sends the message [silently]. - /// - /// Users will receive a notification with no sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_sticker.rs b/src/requests/all/send_sticker.rs deleted file mode 100644 index 9c683a30..00000000 --- a/src/requests/all/send_sticker.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ReplyMarkup}, - Bot, -}; - -/// Use this method to send static .WEBP or [animated] .TGS stickers. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendsticker). -/// -/// [animated]: https://telegram.org/blog/animated-stickers -#[derive(Debug, Clone)] -pub struct SendSticker { - bot: Bot, - chat_id: ChatId, - sticker: InputFile, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendSticker { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendSticker", - FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("sticker", &self.sticker) - .await? - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup) - .build(), - ) - .await) - } -} - -impl SendSticker { - pub(crate) fn new(bot: Bot, chat_id: C, sticker: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - sticker, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Sticker to send. - /// - /// Pass [`InputFile::FileId`] to send a sticker that exists on the - /// Telegram servers (recommended), pass an [`InputFile::Url`] for Telegram - /// to get a sticker (.WEBP file) from the Internet, pass - /// [`InputFile::File`] to upload a sticker from the file system or - /// [`InputFile::Memory`] to upload a sticker from memory - /// [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn sticker(mut self, val: InputFile) -> Self { - self.sticker = val; - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_venue.rs b/src/requests/all/send_venue.rs deleted file mode 100644 index 513ece7d..00000000 --- a/src/requests/all/send_venue.rs +++ /dev/null @@ -1,159 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, Message, ReplyMarkup}, - Bot, -}; - -/// Use this method to send information about a venue. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendvenue). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SendVenue { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - latitude: f32, - longitude: f32, - title: String, - address: String, - foursquare_id: Option, - foursquare_type: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for SendVenue { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendVenue", &self).await - } -} - -impl SendVenue { - pub(crate) fn new( - bot: Bot, - chat_id: C, - latitude: f32, - longitude: f32, - title: T, - address: A, - ) -> Self - where - C: Into, - T: Into, - A: Into, - { - let chat_id = chat_id.into(); - let title = title.into(); - let address = address.into(); - Self { - bot, - chat_id, - latitude, - longitude, - title, - address, - foursquare_id: None, - foursquare_type: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Latitude of the venue. - pub fn latitude(mut self, val: f32) -> Self { - self.latitude = val; - self - } - - /// Longitude of the venue. - pub fn longitude(mut self, val: f32) -> Self { - self.longitude = val; - self - } - - /// Name of the venue. - pub fn title(mut self, val: T) -> Self - where - T: Into, - { - self.title = val.into(); - self - } - - /// Address of the venue. - pub fn address(mut self, val: T) -> Self - where - T: Into, - { - self.address = val.into(); - self - } - - /// Foursquare identifier of the venue. - pub fn foursquare_id(mut self, val: T) -> Self - where - T: Into, - { - self.foursquare_id = Some(val.into()); - self - } - - /// Foursquare type of the venue, if known. - /// - /// For example, `arts_entertainment/default`, `arts_entertainment/aquarium` - /// or `food/icecream`. - pub fn foursquare_type(mut self, val: T) -> Self - where - T: Into, - { - self.foursquare_type = Some(val.into()); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_video.rs b/src/requests/all/send_video.rs deleted file mode 100644 index 395bf875..00000000 --- a/src/requests/all/send_video.rs +++ /dev/null @@ -1,207 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// Use this method to send video files, Telegram clients support mp4 videos -/// (other formats may be sent as Document). -/// -/// Bots can currently send video files of up to 50 MB in size, this -/// limit may be changed in the future. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendvideo). -#[derive(Debug, Clone)] -pub struct SendVideo { - bot: Bot, - chat_id: ChatId, - video: InputFile, - duration: Option, - width: Option, - height: Option, - thumb: Option, - caption: Option, - parse_mode: Option, - supports_streaming: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendVideo { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - let mut builder = FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("video", &self.video) - .await? - .add_text("duration", &self.duration) - .add_text("width", &self.width) - .add_text("height", &self.height) - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("supports_streaming", &self.supports_streaming) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup); - if let Some(thumb) = self.thumb.as_ref() { - builder = builder.add_input_file("thumb", thumb).await?; - } - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendVideo", - builder.build(), - ) - .await) - } -} - -impl SendVideo { - pub(crate) fn new(bot: Bot, chat_id: C, video: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - video, - duration: None, - width: None, - height: None, - thumb: None, - caption: None, - parse_mode: None, - supports_streaming: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Video to send. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn video(mut self, val: InputFile) -> Self { - self.video = val; - self - } - - /// Duration of sent video in seconds. - pub fn duration(mut self, val: i32) -> Self { - self.duration = Some(val); - self - } - - /// Video width. - pub fn width(mut self, val: i32) -> Self { - self.width = Some(val); - self - } - - /// Video height. - pub fn height(mut self, val: i32) -> Self { - self.height = Some(val); - self - } - - /// Thumbnail of the file sent; can be ignored if thumbnail generation for - /// the file is supported server-side. - /// - /// The thumbnail should be in JPEG format and less than 200kB in size. A - /// thumbnail‘s width and height should not exceed 320. Ignored if the - /// video file is not uploaded using [`InputFile::File`] or - /// [`InputFile::Memory`]. Thumbnails can’t be reused and can be only - /// uploaded as a new file. Pass [`InputFile::File`] to upload a file from - /// the file system or [`InputFile::Memory`] to upload a file from memory. - /// [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - /// Video caption (may also be used when resending videos by file_id), - /// 0-1024 characters. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Pass `true`, if the uploaded video is suitable for streaming. - pub fn supports_streaming(mut self, val: bool) -> Self { - self.supports_streaming = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_video_note.rs b/src/requests/all/send_video_note.rs deleted file mode 100644 index 81638f68..00000000 --- a/src/requests/all/send_video_note.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ReplyMarkup}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendvideonote). -/// -/// [v.4.0]: https://telegram.org/blog/video-messages-and-telescope -#[derive(Debug, Clone)] -pub struct SendVideoNote { - bot: Bot, - chat_id: ChatId, - video_note: InputFile, - duration: Option, - length: Option, - thumb: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendVideoNote { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - let mut builder = FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("video_note", &self.video_note) - .await? - .add_text("duration", &self.duration) - .add_text("length", &self.length) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup); - if let Some(thumb) = self.thumb.as_ref() { - builder = builder.add_input_file("thumb", thumb).await?; - } - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendVideoNote", - builder.build(), - ) - .await) - } -} - -impl SendVideoNote { - pub(crate) fn new(bot: Bot, chat_id: C, video_note: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - video_note, - duration: None, - length: None, - thumb: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Video note to send. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn video_note(mut self, val: InputFile) -> Self { - self.video_note = val; - self - } - - /// Duration of sent video in seconds. - pub fn duration(mut self, val: i32) -> Self { - self.duration = Some(val); - self - } - - /// Video width and height, i.e. diameter of the video message. - pub fn length(mut self, val: i32) -> Self { - self.length = Some(val); - self - } - - /// Thumbnail of the file sent; can be ignored if thumbnail generation for - /// the file is supported server-side. - /// - /// The thumbnail should be in JPEG format and less than 200kB in size. A - /// thumbnail‘s width and height should not exceed 320. Ignored if the - /// video note is not uploaded using [`InputFile::File`] or - /// [`InputFile::Memory`]. Thumbnails can’t be reused and can be only - /// uploaded as a new file. Pass [`InputFile::File`] to upload a file from - /// the file system or [`InputFile::Memory`] to upload a file from memory. - /// [More info on Sending Files »]. - /// - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/send_voice.rs b/src/requests/all/send_voice.rs deleted file mode 100644 index 29b7f6c1..00000000 --- a/src/requests/all/send_voice.rs +++ /dev/null @@ -1,159 +0,0 @@ -use crate::{ - net, - requests::{form_builder::FormBuilder, RequestWithFile, ResponseResult}, - types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup}, - Bot, -}; - -/// 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`]). Bots can currently -/// send voice messages of up to 50 MB in size, this limit may be changed in the -/// future. -/// -/// [The official docs](https://core.telegram.org/bots/api#sendvoice). -/// -/// [`Audio`]: crate::types::Audio -/// [`Document`]: crate::types::Document -#[derive(Debug, Clone)] -pub struct SendVoice { - bot: Bot, - chat_id: ChatId, - voice: InputFile, - caption: Option, - parse_mode: Option, - duration: Option, - disable_notification: Option, - reply_to_message_id: Option, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl RequestWithFile for SendVoice { - type Output = Message; - - async fn send(&self) -> tokio::io::Result> { - Ok(net::request_multipart( - self.bot.client(), - self.bot.token(), - "sendVoice", - FormBuilder::new() - .add_text("chat_id", &self.chat_id) - .add_input_file("voice", &self.voice) - .await? - .add_text("caption", &self.caption) - .add_text("parse_mode", &self.parse_mode) - .add_text("duration", &self.duration) - .add_text("disable_notification", &self.disable_notification) - .add_text("reply_to_message_id", &self.reply_to_message_id) - .add_text("reply_markup", &self.reply_markup) - .build(), - ) - .await) - } -} - -impl SendVoice { - pub(crate) fn new(bot: Bot, chat_id: C, voice: InputFile) -> Self - where - C: Into, - { - Self { - bot, - chat_id: chat_id.into(), - voice, - caption: None, - parse_mode: None, - duration: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Audio file to send. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn voice(mut self, val: InputFile) -> Self { - self.voice = val; - self - } - - /// Voice message caption, 0-1024 characters. - pub fn caption(mut self, val: T) -> Self - where - T: Into, - { - self.caption = Some(val.into()); - self - } - - /// Send [Markdown] or [HTML], if you want Telegram apps to show - /// [bold, italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: crate::types::ParseMode::Markdown - /// [HTML]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: - /// crate::types::ParseMode - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - /// Duration of the voice message in seconds. - pub fn duration(mut self, val: i32) -> Self { - self.duration = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - /// If the message is a reply, ID of the original message. - pub fn reply_to_message_id(mut self, val: i32) -> Self { - self.reply_to_message_id = Some(val); - self - } - - /// Additional interface options. - /// - /// A JSON-serialized object for an [inline keyboard], [custom reply - /// keyboard], instructions to remove reply keyboard or to force a reply - /// from the user. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - /// [custom reply keyboard]: https://core.telegram.org/bots#keyboards - pub fn reply_markup(mut self, val: ReplyMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/set_chat_administrator_custom_title.rs b/src/requests/all/set_chat_administrator_custom_title.rs deleted file mode 100644 index a3211811..00000000 --- a/src/requests/all/set_chat_administrator_custom_title.rs +++ /dev/null @@ -1,75 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// Use this method to set a custom title for an administrator in a supergroup -/// promoted by the bot. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchatadministratorcustomtitle). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatAdministratorCustomTitle { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, - custom_title: String, -} - -#[async_trait::async_trait] -impl Request for SetChatAdministratorCustomTitle { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json( - self.bot.client(), - self.bot.token(), - "setChatAdministratorCustomTitle", - &self, - ) - .await - } -} - -impl SetChatAdministratorCustomTitle { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32, custom_title: CT) -> Self - where - C: Into, - CT: Into, - { - let chat_id = chat_id.into(); - let custom_title = custom_title.into(); - Self { bot, chat_id, user_id, custom_title } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// New custom title for the administrator; 0-16 characters, emoji are not - /// allowed. - pub fn custom_title(mut self, val: T) -> Self - where - T: Into, - { - self.custom_title = val.into(); - self - } -} diff --git a/src/requests/all/set_chat_description.rs b/src/requests/all/set_chat_description.rs deleted file mode 100644 index 092c495b..00000000 --- a/src/requests/all/set_chat_description.rs +++ /dev/null @@ -1,62 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchatdescription). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatDescription { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - description: Option, -} - -#[async_trait::async_trait] -impl Request for SetChatDescription { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setChatDescription", &self).await - } -} - -impl SetChatDescription { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, description: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// New chat description, 0-255 characters. - pub fn description(mut self, val: T) -> Self - where - T: Into, - { - self.description = Some(val.into()); - self - } -} diff --git a/src/requests/all/set_chat_permissions.rs b/src/requests/all/set_chat_permissions.rs deleted file mode 100644 index aaa1881b..00000000 --- a/src/requests/all/set_chat_permissions.rs +++ /dev/null @@ -1,58 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, ChatPermissions, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchatpermissions). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatPermissions { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - permissions: ChatPermissions, -} - -#[async_trait::async_trait] -impl Request for SetChatPermissions { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "sendChatPermissions", &self).await - } -} - -impl SetChatPermissions { - pub(crate) fn new(bot: Bot, chat_id: C, permissions: ChatPermissions) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, permissions } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format `@supergroupusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// New default chat permissions. - pub fn permissions(mut self, val: ChatPermissions) -> Self { - self.permissions = val; - self - } -} diff --git a/src/requests/all/set_chat_photo.rs b/src/requests/all/set_chat_photo.rs deleted file mode 100644 index dcc5febc..00000000 --- a/src/requests/all/set_chat_photo.rs +++ /dev/null @@ -1,58 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InputFile, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchatphoto). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatPhoto { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - photo: InputFile, -} - -#[async_trait::async_trait] -impl Request for SetChatPhoto { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setChatPhoto", &self).await - } -} - -impl SetChatPhoto { - pub(crate) fn new(bot: Bot, chat_id: C, photo: InputFile) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, photo } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// New chat photo, uploaded using `multipart/form-data`. - pub fn photo(mut self, val: InputFile) -> Self { - self.photo = val; - self - } -} diff --git a/src/requests/all/set_chat_sticker_set.rs b/src/requests/all/set_chat_sticker_set.rs deleted file mode 100644 index 010a10f5..00000000 --- a/src/requests/all/set_chat_sticker_set.rs +++ /dev/null @@ -1,64 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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 getChat requests to check if the bot can use this method. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchatstickerset). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatStickerSet { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - sticker_set_name: String, -} - -#[async_trait::async_trait] -impl Request for SetChatStickerSet { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setChatStickerSet", &self).await - } -} - -impl SetChatStickerSet { - pub(crate) fn new(bot: Bot, chat_id: C, sticker_set_name: S) -> Self - where - C: Into, - S: Into, - { - let chat_id = chat_id.into(); - let sticker_set_name = sticker_set_name.into(); - Self { bot, chat_id, sticker_set_name } - } - - /// Unique identifier for the target chat or username of the target - /// supergroup (in the format `@supergroupusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Name of the sticker set to be set as the group sticker set. - pub fn sticker_set_name(mut self, val: T) -> Self - where - T: Into, - { - self.sticker_set_name = val.into(); - self - } -} diff --git a/src/requests/all/set_chat_title.rs b/src/requests/all/set_chat_title.rs deleted file mode 100644 index 7d6ae6d1..00000000 --- a/src/requests/all/set_chat_title.rs +++ /dev/null @@ -1,63 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#setchattitle). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetChatTitle { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - title: String, -} - -#[async_trait::async_trait] -impl Request for SetChatTitle { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setChatTitle", &self).await - } -} - -impl SetChatTitle { - pub(crate) fn new(bot: Bot, chat_id: C, title: T) -> Self - where - C: Into, - T: Into, - { - let chat_id = chat_id.into(); - let title = title.into(); - Self { bot, chat_id, title } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// New chat title, 1-255 characters. - pub fn title(mut self, val: T) -> Self - where - T: Into, - { - self.title = val.into(); - self - } -} diff --git a/src/requests/all/set_game_score.rs b/src/requests/all/set_game_score.rs deleted file mode 100644 index 8e429e3a..00000000 --- a/src/requests/all/set_game_score.rs +++ /dev/null @@ -1,89 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{Message, TargetMessage}, - Bot, -}; - -/// 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`. -/// -/// [The official docs](https://core.telegram.org/bots/api#setgamescore). -/// -/// [`Message`]: crate::types::Message -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetGameScore { - #[serde(skip_serializing)] - bot: Bot, - #[serde(flatten)] - target: TargetMessage, - user_id: i32, - score: i32, - force: Option, - disable_edit_message: Option, -} - -#[async_trait::async_trait] -impl Request for SetGameScore { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setGameScore", &self).await - } -} - -impl SetGameScore { - pub(crate) fn new(bot: Bot, target: T, user_id: i32, score: i32) -> Self - where - T: Into, - { - let target = target.into(); - Self { bot, target, user_id, score, force: None, disable_edit_message: None } - } - - /// Target message, either chat id and message id or inline message id. - pub fn target(mut self, val: T) -> Self - where - T: Into, - { - self.target = val.into(); - self - } - - /// User identifier. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// New score, must be non-negative. - pub fn score(mut self, val: i32) -> Self { - self.score = val; - self - } - - /// Pass `true`, if the high score is allowed to decrease. - /// - /// This can be useful when fixing mistakes or banning cheaters. - pub fn force(mut self, val: bool) -> Self { - self.force = Some(val); - self - } - - /// Sends the message [silently]. Users will receive a notification with no - /// sound. - /// - /// [silently]: https://telegram.org/blog/channels-2-0#silent-messages - pub fn disable_edit_message(mut self, val: bool) -> Self { - self.disable_edit_message = Some(val); - self - } -} diff --git a/src/requests/all/set_my_commands.rs b/src/requests/all/set_my_commands.rs deleted file mode 100644 index 831f9705..00000000 --- a/src/requests/all/set_my_commands.rs +++ /dev/null @@ -1,50 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{BotCommand, True}, - Bot, -}; - -/// Use this method to change the list of the bot's commands. -/// -/// [The official docs](https://core.telegram.org/bots/api#setmycommands). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetMyCommands { - #[serde(skip_serializing)] - bot: Bot, - - commands: Vec, -} - -#[async_trait::async_trait] -impl Request for SetMyCommands { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setMyCommands", &self).await - } -} - -impl SetMyCommands { - pub(crate) fn new(bot: Bot, commands: C) -> Self - where - C: Into>, - { - Self { bot, commands: commands.into() } - } - - /// A JSON-serialized list of bot commands to be set as the list of the - /// bot's commands. - /// - /// At most 100 commands can be specified. - pub fn commands(mut self, commands: C) -> Self - where - C: Into>, - { - self.commands = commands.into(); - self - } -} diff --git a/src/requests/all/set_sticker_position_in_set.rs b/src/requests/all/set_sticker_position_in_set.rs deleted file mode 100644 index 4ed78551..00000000 --- a/src/requests/all/set_sticker_position_in_set.rs +++ /dev/null @@ -1,56 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::True, - Bot, -}; - -/// Use this method to move a sticker in a set created by the bot to a specific -/// position. -/// -/// [The official docs](https://core.telegram.org/bots/api#setstickerpositioninset). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetStickerPositionInSet { - #[serde(skip_serializing)] - bot: Bot, - sticker: String, - position: i32, -} - -#[async_trait::async_trait] -impl Request for SetStickerPositionInSet { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setStickerPositionInSet", &self) - .await - } -} - -impl SetStickerPositionInSet { - pub(crate) fn new(bot: Bot, sticker: S, position: i32) -> Self - where - S: Into, - { - let sticker = sticker.into(); - Self { bot, sticker, position } - } - - /// File identifier of the sticker. - pub fn sticker(mut self, val: T) -> Self - where - T: Into, - { - self.sticker = val.into(); - self - } - - /// New sticker position in the set, zero-based. - pub fn position(mut self, val: i32) -> Self { - self.position = val; - self - } -} diff --git a/src/requests/all/set_sticker_set_thumb.rs b/src/requests/all/set_sticker_set_thumb.rs deleted file mode 100644 index ecf153f4..00000000 --- a/src/requests/all/set_sticker_set_thumb.rs +++ /dev/null @@ -1,74 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InputFile, True}, - Bot, -}; - -/// Use this method to set the thumbnail of a sticker set. Animated thumbnails -/// can be set for animated sticker sets only. -/// -/// [The official docs](https://core.telegram.org/bots/api#setstickersetthumb). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetStickerSetThumb { - #[serde(skip_serializing)] - bot: Bot, - name: String, - user_id: i32, - thumb: Option, -} - -#[async_trait::async_trait] -impl Request for SetStickerSetThumb { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setStickerSetThumb", &self).await - } -} - -impl SetStickerSetThumb { - pub(crate) fn new(bot: Bot, name: S, user_id: i32) -> Self - where - S: Into, - { - Self { bot, name: name.into(), user_id, thumb: None } - } - - /// Sticker set name. - pub fn name(mut self, val: T) -> Self - where - T: Into, - { - self.name = val.into(); - self - } - - /// User identifier of the sticker set owner. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// A PNG image with the thumbnail, must be up to 128 kilobytes in size and - /// have width and height exactly 100px, or a TGS animation with the - /// thumbnail up to 32 kilobytes in size; see https://core.telegram.org/animated_stickers#technical-requirements - /// for animated sticker technical requirements. - /// - /// Pass [`InputFile::FileId`] to send a file that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// file from the Internet (20MB max.), pass [`InputFile::File`] to upload - /// a file from the file system or [`InputFile::Memory`] to upload a file - /// from memory (50MB max. each). [More info on Sending Files »]. Animated - /// sticker set thumbnail can't be uploaded via HTTP URL. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url]: crate::types::InputFile::Url - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } -} diff --git a/src/requests/all/set_webhook.rs b/src/requests/all/set_webhook.rs deleted file mode 100644 index c2aff792..00000000 --- a/src/requests/all/set_webhook.rs +++ /dev/null @@ -1,114 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{AllowedUpdate, InputFile, True}, - Bot, -}; - -/// 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. -/// -/// If you'd like to make sure that the Webhook request comes from Telegram, -/// we recommend using a secret path in the URL, e.g. -/// `https://www.example.com/`. Since nobody else knows your bot‘s -/// token, you can be pretty sure it’s us. -/// -/// [The official docs](https://core.telegram.org/bots/api#setwebhook). -/// -/// [`Update`]: crate::types::Update -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct SetWebhook { - #[serde(skip_serializing)] - bot: Bot, - url: String, - certificate: Option, - max_connections: Option, - allowed_updates: Option>, -} - -#[async_trait::async_trait] -impl Request for SetWebhook { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "setWebhook", &self).await - } -} - -impl SetWebhook { - pub(crate) fn new(bot: Bot, url: U) -> Self - where - U: Into, - { - let url = url.into(); - Self { bot, url, certificate: None, max_connections: None, allowed_updates: None } - } - - /// HTTPS url to send updates to. - /// - /// Use an empty string to remove webhook integration. - pub fn url(mut self, val: T) -> Self - where - T: Into, - { - self.url = val.into(); - self - } - - /// Upload your public key certificate so that the root certificate in use - /// can be checked. - /// - /// See our [self-signed guide] for details. - /// - /// [self-signed guide]: https://core.telegram.org/bots/self-signed - pub fn certificate(mut self, val: InputFile) -> Self { - self.certificate = Some(val); - self - } - - /// Maximum allowed number of simultaneous HTTPS connections to the webhook - /// for update delivery, 1-100. - /// - /// Defaults to 40. Use lower values to limit the load on your bot‘s server, - /// and higher values to increase your bot’s throughput. - pub fn max_connections(mut self, val: i32) -> Self { - self.max_connections = Some(val); - self - } - - /// List the types of updates you want your bot to receive. - /// - /// For example, specify [`AllowedUpdate::Message`], - /// [`AllowedUpdate::EditedChannelPost`], [`AllowedUpdate::CallbackQuery`] - /// to only receive updates of these types. Specify an empty list to receive - /// all updates regardless of type (default). If not specified, the - /// previous setting will be used. See [`AllowedUpdate`] for a complete list - /// of available update types. - /// - /// Please note that this parameter doesn't affect updates created before - /// the call to the [`Bot::set_webhook`], so unwanted updates may be - /// received for a short period of time. - /// - /// [`Bot::set_webhook`]: crate::Bot::set_webhook - /// [`AllowedUpdate::Message`]: crate::types::AllowedUpdate::Message - /// [`AllowedUpdate::EditedChannelPost`]: - /// crate::types::AllowedUpdate::EditedChannelPost - /// [`AllowedUpdate::CallbackQuery`]: - /// crate::types::AllowedUpdate::CallbackQuery - /// [`AllowedUpdate`]: crate::types::AllowedUpdate - pub fn allowed_updates(mut self, val: T) -> Self - where - T: Into>, - { - self.allowed_updates = Some(val.into()); - self - } -} diff --git a/src/requests/all/stop_inline_message_live_location.rs b/src/requests/all/stop_inline_message_live_location.rs deleted file mode 100644 index 40fb5604..00000000 --- a/src/requests/all/stop_inline_message_live_location.rs +++ /dev/null @@ -1,62 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{InlineKeyboardMarkup, Message}, - Bot, -}; - -/// Use this method to stop updating a live location message (sent via the bot) -/// before `live_period` expires. -/// -/// On success, [`True`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). -/// -/// [`True`]: crate::types::True -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct StopInlineMessageLiveLocation { - #[serde(skip_serializing)] - bot: Bot, - inline_message_id: String, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for StopInlineMessageLiveLocation { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "stopMessageLiveLocation", &self) - .await - } -} - -impl StopInlineMessageLiveLocation { - pub(crate) fn new(bot: Bot, inline_message_id: I) -> Self - where - I: Into, - { - let inline_message_id = inline_message_id.into(); - Self { bot, inline_message_id, reply_markup: None } - } - - /// Identifier of the inline message. - pub fn inline_message_id(mut self, val: T) -> Self - where - T: Into, - { - self.inline_message_id = val.into(); - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/stop_message_live_location.rs b/src/requests/all/stop_message_live_location.rs deleted file mode 100644 index 892492ea..00000000 --- a/src/requests/all/stop_message_live_location.rs +++ /dev/null @@ -1,70 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Message}, - Bot, -}; - -/// Use this method to stop updating a live location message before -/// `live_period` expires. -/// -/// On success, the sent [`Message`] is returned. -/// -/// [The official docs](https://core.telegram.org/bots/api#stopmessagelivelocation). -/// -/// [`Message`]: crate::types::Message -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct StopMessageLiveLocation { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for StopMessageLiveLocation { - type Output = Message; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "stopMessageLiveLocation", &self) - .await - } -} - -impl StopMessageLiveLocation { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`) - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the message to edit - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/stop_poll.rs b/src/requests/all/stop_poll.rs deleted file mode 100644 index 946b4760..00000000 --- a/src/requests/all/stop_poll.rs +++ /dev/null @@ -1,66 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, InlineKeyboardMarkup, Poll}, - Bot, -}; - -/// Use this method to stop a poll which was sent by the bot. -/// -/// [The official docs](https://core.telegram.org/bots/api#stoppoll). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct StopPoll { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - message_id: i32, - reply_markup: Option, -} - -#[async_trait::async_trait] -impl Request for StopPoll { - type Output = Poll; - - /// On success, the stopped [`Poll`] with the final results is returned. - /// - /// [`Poll`]: crate::types::Poll - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "stopPoll", &self).await - } -} -impl StopPoll { - pub(crate) fn new(bot: Bot, chat_id: C, message_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, message_id, reply_markup: None } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Identifier of the original message with the poll. - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - /// A JSON-serialized object for a new [inline keyboard]. - /// - /// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/requests/all/unban_chat_member.rs b/src/requests/all/unban_chat_member.rs deleted file mode 100644 index 5aee625c..00000000 --- a/src/requests/all/unban_chat_member.rs +++ /dev/null @@ -1,58 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#unbanchatmember). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct UnbanChatMember { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, - user_id: i32, -} - -#[async_trait::async_trait] -impl Request for UnbanChatMember { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "unbanChatMember", &self).await - } -} - -impl UnbanChatMember { - pub(crate) fn new(bot: Bot, chat_id: C, user_id: i32) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id, user_id } - } - - /// Unique identifier for the target group or username of the target - /// supergroup or channel (in the format `@username`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } - - /// Unique identifier of the target user. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } -} diff --git a/src/requests/all/unpin_chat_message.rs b/src/requests/all/unpin_chat_message.rs deleted file mode 100644 index 15e76a99..00000000 --- a/src/requests/all/unpin_chat_message.rs +++ /dev/null @@ -1,52 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{ChatId, True}, - Bot, -}; - -/// Use this method to unpin 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. -/// -/// [The official docs](https://core.telegram.org/bots/api#unpinchatmessage). -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct UnpinChatMessage { - #[serde(skip_serializing)] - bot: Bot, - chat_id: ChatId, -} - -#[async_trait::async_trait] -impl Request for UnpinChatMessage { - type Output = True; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "unpinChatMessage", &self).await - } -} - -impl UnpinChatMessage { - pub(crate) fn new(bot: Bot, chat_id: C) -> Self - where - C: Into, - { - let chat_id = chat_id.into(); - Self { bot, chat_id } - } - - /// Unique identifier for the target chat or username of the target channel - /// (in the format `@channelusername`). - pub fn chat_id(mut self, val: T) -> Self - where - T: Into, - { - self.chat_id = val.into(); - self - } -} diff --git a/src/requests/all/upload_sticker_file.rs b/src/requests/all/upload_sticker_file.rs deleted file mode 100644 index b09b143f..00000000 --- a/src/requests/all/upload_sticker_file.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::Serialize; - -use crate::{ - net, - requests::{Request, ResponseResult}, - types::{File, InputFile}, - Bot, -}; - -/// Use this method to upload a .png file with a sticker for later use in -/// [`Bot::create_new_sticker_set`] and [`Bot::add_sticker_to_set`] methods (can -/// be used multiple times). -/// -/// [The official docs](https://core.telegram.org/bots/api#uploadstickerfile). -/// -/// [`Bot::create_new_sticker_set`]: crate::Bot::create_new_sticker_set -/// [`Bot::add_sticker_to_set`]: crate::Bot::add_sticker_to_set -#[serde_with_macros::skip_serializing_none] -#[derive(Debug, Clone, Serialize)] -pub struct UploadStickerFile { - #[serde(skip_serializing)] - bot: Bot, - user_id: i32, - png_sticker: InputFile, -} -#[async_trait::async_trait] -impl Request for UploadStickerFile { - type Output = File; - - async fn send(&self) -> ResponseResult { - net::request_json(self.bot.client(), self.bot.token(), "uploadStickerFile", &self).await - } -} - -impl UploadStickerFile { - pub(crate) fn new(bot: Bot, user_id: i32, png_sticker: InputFile) -> Self { - Self { bot, user_id, png_sticker } - } - - /// User identifier of sticker file owner. - pub fn user_id(mut self, val: i32) -> Self { - self.user_id = val; - self - } - - /// **Png** image with the sticker, must be up to 512 kilobytes in size, - /// dimensions must not exceed 512px, and either width or height must be - /// exactly 512px. [More info on Sending Files »]. - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - pub fn png_sticker(mut self, val: InputFile) -> Self { - self.png_sticker = val; - self - } -} diff --git a/src/requests/form_builder.rs b/src/requests/form_builder.rs deleted file mode 100644 index 3c7f70b9..00000000 --- a/src/requests/form_builder.rs +++ /dev/null @@ -1,156 +0,0 @@ -use std::{borrow::Cow, path::PathBuf}; - -use reqwest::multipart::Form; - -use crate::{ - requests::utils::{file_from_memory_to_part, file_to_part}, - types::{ - ChatId, InlineKeyboardMarkup, InputFile, InputMedia, MaskPosition, ParseMode, ReplyMarkup, - }, -}; - -/// This is a convenient struct that builds `reqwest::multipart::Form` -/// from scratch. -pub(crate) struct FormBuilder { - form: Form, -} - -impl FormBuilder { - pub(crate) fn new() -> Self { - Self { form: Form::new() } - } - - pub fn add_text<'a, T, N>(self, name: N, value: &T) -> Self - where - N: Into>, - T: IntoFormText, - { - match value.into_form_text() { - Some(val) => Self { form: self.form.text(name.into().into_owned(), val) }, - None => self, - } - } - - pub async fn add_input_file<'a, N>(self, name: N, value: &InputFile) -> tokio::io::Result - where - N: Into>, - { - Ok(match value { - InputFile::File(path) => self.add_file(name, path.clone()).await?, - InputFile::Memory { file_name, data } => { - self.add_file_from_memory(name, file_name.clone(), data.clone()) - } - InputFile::Url(url) => self.add_text(name, url), - InputFile::FileId(file_id) => self.add_text(name, file_id), - }) - } - - // used in SendMediaGroup - pub async fn add_file<'a, N>(self, name: N, path_to_file: PathBuf) -> tokio::io::Result - where - N: Into>, - { - Ok(Self { - form: self.form.part(name.into().into_owned(), file_to_part(path_to_file).await?), - }) - } - - fn add_file_from_memory<'a, N>( - self, - name: N, - file_name: String, - data: Cow<'static, [u8]>, - ) -> Self - where - N: Into>, - { - Self { - form: self - .form - .part(name.into().into_owned(), file_from_memory_to_part(data, file_name)), - } - } - - pub fn build(self) -> Form { - self.form - } -} - -pub(crate) trait IntoFormText { - fn into_form_text(&self) -> Option; -} - -macro_rules! impl_for_struct { - ($($name:ty),*) => { - $( - impl IntoFormText for $name { - fn into_form_text(&self) -> Option { - let json = serde_json::to_string(self) - .expect("serde_json::to_string failed"); - Some(json) - } - } - )* - }; -} - -impl_for_struct!(bool, i32, i64, u32, ReplyMarkup, InlineKeyboardMarkup, MaskPosition); - -impl IntoFormText for Option -where - T: IntoFormText, -{ - fn into_form_text(&self) -> Option { - self.as_ref().and_then(IntoFormText::into_form_text) - } -} - -// TODO: fix InputMedia implementation of IntoFormValue (for now it doesn't -// encode files :|) -impl IntoFormText for Vec { - fn into_form_text(&self) -> Option { - let json = serde_json::to_string(self).expect("serde_json::to_string failed"); - Some(json) - } -} - -impl IntoFormText for InputMedia { - fn into_form_text(&self) -> Option { - let json = serde_json::to_string(self).expect("serde_json::to_string failed"); - Some(json) - } -} - -impl IntoFormText for str { - fn into_form_text(&self) -> Option { - Some(self.to_owned()) - } -} - -impl IntoFormText for ParseMode { - fn into_form_text(&self) -> Option { - let string = match self { - ParseMode::MarkdownV2 => String::from("MarkdownV2"), - ParseMode::HTML => String::from("HTML"), - #[allow(deprecated)] - ParseMode::Markdown => String::from("Markdown"), - }; - Some(string) - } -} - -impl IntoFormText for ChatId { - fn into_form_text(&self) -> Option { - let string = match self { - ChatId::Id(id) => id.to_string(), - ChatId::ChannelUsername(username) => username.clone(), - }; - Some(string) - } -} - -impl IntoFormText for String { - fn into_form_text(&self) -> Option { - Some(self.clone()) - } -} diff --git a/src/requests/mod.rs b/src/requests/mod.rs deleted file mode 100644 index bb104ddf..00000000 --- a/src/requests/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! API requests. - -mod all; -mod form_builder; -mod utils; - -pub use all::*; - -/// A type that is returned after making a request to Telegram. -pub type ResponseResult = Result; - -/// A shortcut for `ResponseResult::Ok(val)`. -pub fn respond(val: T) -> ResponseResult { - ResponseResult::Ok(val) -} - -/// Designates an API request. -#[async_trait::async_trait] -pub trait Request { - /// A data structure returned if success. - type Output; - - /// Asynchronously sends this request to Telegram and returns the result. - async fn send(&self) -> ResponseResult; -} - -/// Designates an API request with possibly sending file. -#[async_trait::async_trait] -pub trait RequestWithFile { - /// A data structure returned if success. - type Output; - - /// Asynchronously sends this request to Telegram and returns the result. - /// Returns `tokio::io::Result::Err` when trying to send file which does not - /// exists. - async fn send(&self) -> tokio::io::Result>; -} diff --git a/src/requests/utils.rs b/src/requests/utils.rs deleted file mode 100644 index f10c9dc5..00000000 --- a/src/requests/utils.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::{borrow::Cow, path::PathBuf}; - -use bytes::{Bytes, BytesMut}; -use reqwest::{multipart::Part, Body}; -use tokio_util::codec::{Decoder, FramedRead}; - -struct FileDecoder; - -impl Decoder for FileDecoder { - type Item = Bytes; - type Error = std::io::Error; - - fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { - if src.is_empty() { - return Ok(None); - } - Ok(Some(src.split().freeze())) - } -} - -pub async fn file_to_part(path_to_file: PathBuf) -> std::io::Result { - let file_name = path_to_file.file_name().unwrap().to_string_lossy().into_owned(); - - let file = FramedRead::new(tokio::fs::File::open(path_to_file).await?, FileDecoder); - - Ok(Part::stream(Body::wrap_stream(file)).file_name(file_name)) -} - -pub fn file_from_memory_to_part(data: Cow<'static, [u8]>, name: String) -> Part { - Part::bytes(data).file_name(name) -} diff --git a/src/types/allowed_update.rs b/src/types/allowed_update.rs deleted file mode 100644 index f3b920ac..00000000 --- a/src/types/allowed_update.rs +++ /dev/null @@ -1,14 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum AllowedUpdate { - Message, - EditedMessage, - ChannelPost, - EditedChannelPost, - InlineQuery, - ChosenInlineResult, - CallbackQuery, -} diff --git a/src/types/animation.rs b/src/types/animation.rs deleted file mode 100644 index dc52901c..00000000 --- a/src/types/animation.rs +++ /dev/null @@ -1,165 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{MimeWrapper, PhotoSize}; - -/// This object represents an animation file (GIF or H.264/MPEG-4 AVC video -/// without sound). -/// -/// [The official docs](https://core.telegram.org/bots/api#animation). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Animation { - /// An identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// A video width as defined by a sender. - pub width: u32, - - /// A video height as defined by a sender. - pub height: u32, - - /// A duration of the video in seconds as defined by a sender. - pub duration: u32, - - /// An animation thumbnail as defined by a sender. - pub thumb: Option, - - /// An original animation filename as defined by a sender. - pub file_name: Option, - - /// A MIME type of the file as defined by a sender. - pub mime_type: Option, - - /// A size of a file. - pub file_size: Option, -} - -impl Animation { - pub fn new( - file_id: S1, - file_unique_id: S2, - width: u32, - height: u32, - duration: u32, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - width, - height, - duration, - thumb: None, - file_name: None, - mime_type: None, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn width(mut self, val: u32) -> Self { - self.width = val; - self - } - - pub fn height(mut self, val: u32) -> Self { - self.height = val; - self - } - - pub fn duration(mut self, val: u32) -> Self { - self.duration = val; - self - } - - pub fn thumb(mut self, val: PhotoSize) -> Self { - self.thumb = Some(val); - self - } - - pub fn file_name(mut self, val: S) -> Self - where - S: Into, - { - self.file_name = Some(val.into()); - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = Some(val); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn deserialize() { - let json = r#"{ - "file_id":"id", - "file_unique_id":"", - "width":320, - "height":320, - "duration":59, - "thumb":{ - "file_id":"id", - "file_unique_id":"", - "width":320, - "height":320, - "file_size":3452 - }, - "file_name":"some", - "mime_type":"video/gif", - "file_size":6500}"#; - let expected = Animation { - file_id: "id".to_string(), - file_unique_id: "".to_string(), - width: 320, - height: 320, - duration: 59, - thumb: Some(PhotoSize { - file_id: "id".to_string(), - file_unique_id: "".to_string(), - width: 320, - height: 320, - file_size: Some(3452), - }), - file_name: Some("some".to_string()), - mime_type: Some(MimeWrapper("video/gif".parse().unwrap())), - file_size: Some(6500), - }; - let actual = serde_json::from_str::(json).unwrap(); - assert_eq!(actual, expected) - } -} diff --git a/src/types/audio.rs b/src/types/audio.rs deleted file mode 100644 index d5599c20..00000000 --- a/src/types/audio.rs +++ /dev/null @@ -1,152 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{MimeWrapper, PhotoSize}; - -/// This object represents an audio file to be treated as music by the Telegram -/// clients. -/// -/// [The official docs](https://core.telegram.org/bots/api#audio). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Audio { - /// An identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// A duration of the audio in seconds as defined by a sender. - pub duration: u32, - - /// A performer of the audio as defined by a sender or by audio tags. - pub performer: Option, - - /// A title of the audio as defined by sender or by audio tags. - pub title: Option, - - /// A MIME type of the file as defined by a sender. - pub mime_type: Option, - - /// A size of a file. - pub file_size: Option, - - /// A thumbnail of the album cover to which the music file belongs. - pub thumb: Option, -} - -impl Audio { - pub fn new(file_id: S1, file_unique_id: S2, duration: u32) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - duration, - performer: None, - title: None, - mime_type: None, - file_size: None, - thumb: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn duration(mut self, val: u32) -> Self { - self.duration = val; - self - } - - pub fn performer(mut self, val: S) -> Self - where - S: Into, - { - self.performer = Some(val.into()); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = Some(val); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } - - pub fn thumb(mut self, val: PhotoSize) -> Self { - self.thumb = Some(val); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn deserialize() { - let json = r#"{ - "file_id":"id", - "file_unique_id":"", - "duration":60, - "performer":"Performer", - "title":"Title", - "mime_type":"application/zip", - "file_size":123456, - "thumb":{ - "file_id":"id", - "file_unique_id":"", - "width":320, - "height":320, - "file_size":3452 - } - }"#; - let expected = Audio { - file_id: "id".to_string(), - file_unique_id: "".to_string(), - duration: 60, - performer: Some("Performer".to_string()), - title: Some("Title".to_string()), - mime_type: Some(serde_json::from_str("\"application/zip\"").unwrap()), - file_size: Some(123_456), - thumb: Some(PhotoSize { - file_id: "id".to_string(), - file_unique_id: "".to_string(), - width: 320, - height: 320, - file_size: Some(3452), - }), - }; - let actual = serde_json::from_str::

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementDriverLicense { - /// Base64-encoded encrypted Telegram Passport element data provided - /// by the user, available for `personal_details`, `passport`, - /// `driver_license`, `identity_card`, `internal_passport` and - /// `address` types. Can be decrypted and verified using the - /// accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub data: String, - - /// Encrypted file with the front side of the document, provided by the - /// user. Available for `passport`, `driver_license`, `identity_card` - /// and `internal_passport`. The file can be decrypted and verified - /// using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub front_side: PassportFile, - - /// Encrypted file with the reverse side of the document, provided by - /// the user. Available for `driver_license` and `identity_card`. The - /// file can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub reverse_side: PassportFile, - - /// Encrypted file with the selfie of the user holding a document, - /// provided by the user; available for `passport`, `driver_license`, - /// `identity_card` and `internal_passport`. The file can be decrypted - /// and verified using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub selfie: PassportFile, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementDriverLicense { - pub fn new( - data: S, - front_side: PassportFile, - reverse_side: PassportFile, - selfie: PassportFile, - ) -> Self - where - S: Into, - { - Self { data: data.into(), front_side, reverse_side, selfie, translation: None } - } - - pub fn data(mut self, val: S) -> Self - where - S: Into, - { - self.data = val.into(); - self - } - - pub fn front_side(mut self, val: PassportFile) -> Self { - self.front_side = val; - self - } - - pub fn reverse_side(mut self, val: PassportFile) -> Self { - self.reverse_side = val; - self - } - - pub fn selfie(mut self, val: PassportFile) -> Self { - self.selfie = val; - self - } - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementIdentityCard { - /// Base64-encoded encrypted Telegram Passport element data provided - /// by the user, available for `personal_details`, `passport`, - /// `driver_license`, `identity_card`, `internal_passport` and - /// `address` types. Can be decrypted and verified using the - /// accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub data: String, - - /// Encrypted file with the front side of the document, provided by the - /// user. Available for `passport`, `driver_license`, `identity_card` - /// and `internal_passport`. The file can be decrypted and verified - /// using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub front_side: PassportFile, - - /// Encrypted file with the reverse side of the document, provided by - /// the user. Available for `driver_license` and `identity_card`. The - /// file can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub reverse_side: PassportFile, - - /// Encrypted file with the selfie of the user holding a document, - /// provided by the user; available for `passport`, `driver_license`, - /// `identity_card` and `internal_passport`. The file can be decrypted - /// and verified using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub selfie: PassportFile, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementIdentityCard { - pub fn new( - data: S, - front_side: PassportFile, - reverse_side: PassportFile, - selfie: PassportFile, - ) -> Self - where - S: Into, - { - Self { data: data.into(), front_side, reverse_side, selfie, translation: None } - } - - pub fn data(mut self, val: S) -> Self - where - S: Into, - { - self.data = val.into(); - self - } - - pub fn front_side(mut self, val: PassportFile) -> Self { - self.front_side = val; - self - } - - pub fn reverse_side(mut self, val: PassportFile) -> Self { - self.reverse_side = val; - self - } - - pub fn selfie(mut self, val: PassportFile) -> Self { - self.selfie = val; - self - } - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementInternalPassport { - /// Base64-encoded encrypted Telegram Passport element data provided - /// by the user, available for `personal_details`, `passport`, - /// `driver_license`, `identity_card`, `internal_passport` and - /// `address` types. Can be decrypted and verified using the - /// accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub data: String, - - /// Encrypted file with the front side of the document, provided by the - /// user. Available for `passport`, `driver_license`, `identity_card` - /// and `internal_passport`. The file can be decrypted and verified - /// using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub front_side: PassportFile, - - /// Encrypted file with the selfie of the user holding a document, - /// provided by the user; available for `passport`, `driver_license`, - /// `identity_card` and `internal_passport`. The file can be decrypted - /// and verified using the accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub selfie: PassportFile, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementInternalPassport { - pub fn new(data: S, front_side: PassportFile, selfie: PassportFile) -> Self - where - S: Into, - { - Self { data: data.into(), front_side, selfie, translation: None } - } - - pub fn data(mut self, val: S) -> Self - where - S: Into, - { - self.data = val.into(); - self - } - - pub fn front_side(mut self, val: PassportFile) -> Self { - self.front_side = val; - self - } - - pub fn selfie(mut self, val: PassportFile) -> Self { - self.selfie = val; - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementAddress { - /// Base64-encoded encrypted Telegram Passport element data provided - /// by the user, available for `personal_details`, `passport`, - /// `driver_license`, `identity_card`, `internal_passport` and - /// `address` types. Can be decrypted and verified using the - /// accompanying [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub data: String, -} - -impl EncryptedPassportElementAddress { - pub fn new(data: S) -> Self - where - S: Into, - { - Self { data: data.into() } - } - - pub fn data(mut self, val: S) -> Self - where - S: Into, - { - self.data = val.into(); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementUtilityBill { - /// Array of encrypted files with documents provided by the user, - /// available for `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub files: Vec, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementUtilityBill { - pub fn new(files: F) -> Self - where - F: Into>, - { - Self { files: files.into(), translation: None } - } - - pub fn files

(mut self, val: P) -> Self - where - P: Into>, - { - self.files = val.into(); - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementBankStatement { - /// Array of encrypted files with documents provided by the user, - /// available for `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub files: Vec, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementBankStatement { - pub fn new(files: F) -> Self - where - F: Into>, - { - Self { files: files.into(), translation: None } - } - - pub fn files

(mut self, val: P) -> Self - where - P: Into>, - { - self.files = val.into(); - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementRentalAgreement { - /// Array of encrypted files with documents provided by the user, - /// available for `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub files: Vec, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementRentalAgreement { - pub fn new(files: F) -> Self - where - F: Into>, - { - Self { files: files.into(), translation: None } - } - - pub fn files

(mut self, val: P) -> Self - where - P: Into>, - { - self.files = val.into(); - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementPassportRegistration { - /// Array of encrypted files with documents provided by the user, - /// available for `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub files: Vec, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementPassportRegistration { - pub fn new(files: F) -> Self - where - F: Into>, - { - Self { files: files.into(), translation: None } - } - - pub fn files

(mut self, val: P) -> Self - where - P: Into>, - { - self.files = val.into(); - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementTemporaryRegistration { - /// Array of encrypted files with documents provided by the user, - /// available for `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub files: Vec, - - /// Array of encrypted files with translated versions of documents - /// provided by the user. Available if requested for `passport`, - /// `driver_license`, `identity_card`, `internal_passport`, - /// `utility_bill`, `bank_statement`, `rental_agreement`, - /// `passport_registration` and `temporary_registration` types. Files - /// can be decrypted and verified using the accompanying - /// [`EncryptedCredentials`]. - /// - /// [`EncryptedCredentials`]: - /// crate::types::EncryptedCredentials - pub translation: Option>, -} - -impl EncryptedPassportElementTemporaryRegistration { - pub fn new(files: F) -> Self - where - F: Into>, - { - Self { files: files.into(), translation: None } - } - - pub fn files

(mut self, val: P) -> Self - where - P: Into>, - { - self.files = val.into(); - self - } - - pub fn translation

(mut self, val: P) -> Self - where - P: Into>, - { - self.translation = Some(val.into()); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementPhoneNumber { - /// User's verified phone number, available only for `phone_number` - /// type. - pub phone_number: String, -} - -impl EncryptedPassportElementPhoneNumber { - pub fn new(phone_number: S) -> Self - where - S: Into, - { - Self { phone_number: phone_number.into() } - } - - pub fn phone_number(mut self, val: S) -> Self - where - S: Into, - { - self.phone_number = val.into(); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct EncryptedPassportElementEmail { - /// User's verified email address, available only for `email` type. - pub email: String, -} - -impl EncryptedPassportElementEmail { - pub fn new(email: S) -> Self - where - S: Into, - { - Self { email: email.into() } - } - - pub fn email(mut self, val: S) -> Self - where - S: Into, - { - self.email = val.into(); - self - } -} diff --git a/src/types/file.rs b/src/types/file.rs deleted file mode 100644 index 721f61c0..00000000 --- a/src/types/file.rs +++ /dev/null @@ -1,75 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a file ready to be downloaded. -/// -/// The file can be downloaded via the link `https://api.telegram.org/file/bot/`. -/// 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 [`Bot::get_file`]. -/// -/// [The official docs](https://core.telegram.org/bots/api#file). -/// -/// [`Bot::get_file`]: crate::Bot::get_file -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct File { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// File size, if known. - pub file_size: u32, - - // TODO: chacge "Use ..." to use bot.download... - /// File path. Use `https://api.telegram.org/file/bot/` - /// to get the file. - pub file_path: String, -} - -impl File { - pub fn new(file_id: S1, file_unique_id: S2, file_size: u32, file_path: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - file_size, - file_path: file_path.into(), - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = val; - self - } - - pub fn file_path(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } -} diff --git a/src/types/force_reply.rs b/src/types/force_reply.rs deleted file mode 100644 index a6a74408..00000000 --- a/src/types/force_reply.rs +++ /dev/null @@ -1,41 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::True; - -/// Upon receiving a message with this object, Telegram clients will display a -/// reply interface to the user (act as if the user has selected the bot‘s -/// message and tapped ’Reply'). -/// -/// This can be extremely useful if you want to create user-friendly -/// step-by-step interfaces without having to sacrifice [privacy mode]. -/// -/// [The official docs](https://core.telegram.org/bots/api#forcereply). -/// -/// [privacy mode]: https://core.telegram.org/bots#privacy-mode -#[serde_with_macros::skip_serializing_none] -#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ForceReply { - /// Shows reply interface to the user, as if they manually selected the - /// bot‘s message and tapped ’Reply'. - pub force_reply: True, - - /// Use this parameter if you want to force reply from specific users only. - /// Targets: 1) users that are `@mentioned` in the text of the - /// [`Message`] object; 2) if the bot's message is a reply - /// (has reply_to_message_id), sender of the original message. - /// - /// [`Message`]: crate::types::Message - pub selective: Option, -} - -impl ForceReply { - pub fn new() -> Self { - Self::default() - } - - pub fn selective(mut self, val: bool) -> Self { - self.selective = Some(val); - self - } -} diff --git a/src/types/game.rs b/src/types/game.rs deleted file mode 100644 index 52fe01b8..00000000 --- a/src/types/game.rs +++ /dev/null @@ -1,106 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{Animation, MessageEntity, PhotoSize}; - -/// This object represents a game. -/// -/// Use [@Botfather] to create and edit games, their short names will act as -/// unique identifiers. -/// -/// [@Botfather]: https://t.me/botfather -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Game { - /// Title of the game. - pub title: String, - - /// Description of the game. - pub description: String, - - /// Photo that will be displayed in the game message in chats. - pub photo: Vec, - - /// Brief description of the game or high scores included in the game - /// message. Can be automatically edited to include current high scores - /// for the game when the bot calls [`Bot::set_game_score`], or manually - /// edited using [`Bot::edit_message_text`]. 0-4096 characters. - /// - /// [`Bot::set_game_score`]: crate::Bot::set_game_score - /// - /// [`Bot::edit_message_text`]: crate::Bot::edit_message_text - pub text: Option, - - /// Special entities that appear in text, such as usernames, URLs, bot - /// commands, etc. - pub text_entities: Option>, - - /// Animation that will be displayed in the game message in chats. Upload - /// via [@Botfather]. - /// - /// [@Botfather]: https://t.me/botfather - pub animation: Option, -} - -impl Game { - pub fn new(title: S1, description: S2, photo: P) -> Self - where - S1: Into, - S2: Into, - P: Into>, - { - Self { - title: title.into(), - description: description.into(), - photo: photo.into(), - text: None, - text_entities: None, - animation: None, - } - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = val.into(); - self - } - - pub fn photo

(mut self, val: P) -> Self - where - P: Into>, - { - self.photo = val.into(); - self - } - - pub fn text(mut self, val: S) -> Self - where - S: Into, - { - self.text = Some(val.into()); - self - } - - pub fn text_entities(mut self, val: T) -> Self - where - T: Into>, - { - self.text_entities = Some(val.into()); - self - } - - pub fn animation(mut self, val: Animation) -> Self { - self.animation = Some(val); - self - } -} diff --git a/src/types/game_high_score.rs b/src/types/game_high_score.rs deleted file mode 100644 index f713b18e..00000000 --- a/src/types/game_high_score.rs +++ /dev/null @@ -1,40 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::user::User; - -/// This object represents one row of the high scores table for a game. -/// -/// [The official docs](https://core.telegram.org/bots/api#gamehighscore). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct GameHighScore { - /// Position in high score table for the game. - pub position: u32, - - /// User. - pub user: User, - - /// Score. - pub score: u32, -} - -impl GameHighScore { - pub fn new(position: u32, user: User, score: u32) -> Self { - Self { position, user, score } - } - - pub fn position(mut self, val: u32) -> Self { - self.position = val; - self - } - - pub fn user(mut self, val: User) -> Self { - self.user = val; - self - } - - pub fn score(mut self, val: u32) -> Self { - self.score = val; - self - } -} diff --git a/src/types/inline_keyboard_button.rs b/src/types/inline_keyboard_button.rs deleted file mode 100644 index 12497463..00000000 --- a/src/types/inline_keyboard_button.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::types::{CallbackGame, LoginUrl}; -use serde::{Deserialize, Serialize}; - -/// This object represents one button of an inline keyboard. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinekeyboardbutton). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineKeyboardButton { - /// Label text on the button. - pub text: String, - - #[serde(flatten)] - pub kind: InlineKeyboardButtonKind, -} - -impl InlineKeyboardButton { - pub fn new(text: S, kind: InlineKeyboardButtonKind) -> Self - where - S: Into, - { - Self { text: text.into(), kind } - } - - pub fn text(mut self, val: S) -> Self - where - S: Into, - { - self.text = val.into(); - self - } - - pub fn kind(mut self, val: InlineKeyboardButtonKind) -> Self { - self.kind = val; - self - } -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum InlineKeyboardButtonKind { - /// HTTP or tg:// url to be opened when button is pressed. - Url(String), - - /// An HTTP URL used to automatically authorize the user. Can be used as a - /// replacement for the [Telegram Login Widget](). - /// - /// [Telegram Login Widget]: https://core.telegram.org/widgets/login - LoginUrl(LoginUrl), - - /// Data to be sent in a [`CallbackQuery`] to the bot when button is - /// pressed, 1-64 bytes. - /// - /// [`CallbackQuery`]: crate::types::CallbackQuery - CallbackData(String), - - /// If set, pressing the button will prompt the user to select one of their - /// chats, open that chat and insert the bot‘s username and the specified - /// inline query in the input field. Can be empty, in which case just the - /// bot’s username will be inserted. - /// - /// Note: This offers an easy way for users to start using your bot in - /// [inline mode] when they are currently in a private chat with it. - /// Especially useful when combined with [switch_pm…] actions – in this - /// case the user will be automatically returned to the chat they - /// switched from, skipping the chat selection screen. - /// - /// [inline mode]: https://core.telegram.org/bots/inline - /// [switch_pm…]: https://core.telegram.org/bots/api#answerinlinequery - SwitchInlineQuery(String), - - /// If set, pressing the button will insert the bot‘s username and the - /// specified inline query in the current chat's input field. - /// Can be empty, in which case only the bot’s username will be - /// inserted. - /// - ///This offers a quick way for the user to open your bot in inline mode in - /// the same chat – good for selecting something from multiple options. - SwitchInlineQueryCurrentChat(String), - - /// Description of the game that will be launched when the user presses the - /// button. - /// - /// ## Note - /// This type of button **must** always be the first button in the first - /// row. - CallbackGame(CallbackGame), - - /// Specify True, to send a [Pay button]. - /// - /// ## Note - /// This type of button **must** always be the first button in the first - /// row. - /// - /// [Pay button]: https://core.telegram.org/bots/api#payments - Pay(bool), -} - -/// Build buttons. -/// -/// # Examples -/// ``` -/// use teloxide::types::InlineKeyboardButton; -/// -/// let url_button = InlineKeyboardButton::url("Text".to_string(), "http://url.com".to_string()); -/// ``` -impl InlineKeyboardButton { - pub fn url(text: String, url: String) -> InlineKeyboardButton { - InlineKeyboardButton { text, kind: InlineKeyboardButtonKind::Url(url) } - } - - pub fn callback(text: String, callback_data: String) -> InlineKeyboardButton { - InlineKeyboardButton { text, kind: InlineKeyboardButtonKind::CallbackData(callback_data) } - } - - pub fn switch_inline_query(text: String, switch_inline_query: String) -> InlineKeyboardButton { - InlineKeyboardButton { - text, - kind: InlineKeyboardButtonKind::SwitchInlineQuery(switch_inline_query), - } - } - - pub fn switch_inline_query_current_chat( - text: String, - switch_inline_query_current_chat: String, - ) -> InlineKeyboardButton { - InlineKeyboardButton { - text, - kind: InlineKeyboardButtonKind::SwitchInlineQueryCurrentChat( - switch_inline_query_current_chat, - ), - } - } -} diff --git a/src/types/inline_keyboard_markup.rs b/src/types/inline_keyboard_markup.rs deleted file mode 100644 index b6884a96..00000000 --- a/src/types/inline_keyboard_markup.rs +++ /dev/null @@ -1,109 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::InlineKeyboardButton; - -/// This object represents an [inline keyboard] that appears right next to the -/// message it belongs to. -/// -/// *Note*: This will only work in Telegram versions released after 9 April, -/// 2016. Older clients will display unsupported message. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinekeyboardmarkup). -/// -/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, Default)] -#[non_exhaustive] -pub struct InlineKeyboardMarkup { - /// Array of button rows, each represented by an array of - /// [`InlineKeyboardButton`] objects. - /// - /// [`InlineKeyboardButton`]: crate::types::InlineKeyboardButton - pub inline_keyboard: Vec>, -} - -/// Build `InlineKeyboardMarkup`. -/// -/// # Examples -/// ``` -/// use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup}; -/// -/// let url_button = InlineKeyboardButton::url("text".to_string(), "http://url.com".to_string()); -/// let keyboard = InlineKeyboardMarkup::default().append_row(vec![url_button]); -/// ``` -impl InlineKeyboardMarkup { - pub fn new(inline_keyboard: I1) -> Self - where - I1: Into>, - I2: Into>, - { - Self { inline_keyboard: inline_keyboard.into().into_iter().map(Into::into).collect() } - } - - pub fn inline_keyboard(mut self, val: I1) -> Self - where - I1: Into>, - I2: Into>, - { - self.inline_keyboard = val.into().into_iter().map(Into::into).collect(); - self - } - - pub fn append_row(mut self, buttons: Vec) -> Self { - self.inline_keyboard.push(buttons); - self - } - - pub fn append_to_row(mut self, button: InlineKeyboardButton, index: usize) -> Self { - match self.inline_keyboard.get_mut(index) { - Some(buttons) => buttons.push(button), - None => self.inline_keyboard.push(vec![button]), - }; - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn append_row() { - let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string()); - let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string()); - - let markup = - InlineKeyboardMarkup::default().append_row(vec![button1.clone(), button2.clone()]); - - let expected = InlineKeyboardMarkup { inline_keyboard: vec![vec![button1, button2]] }; - - assert_eq!(markup, expected); - } - - #[test] - fn append_to_row_existent_row() { - let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string()); - let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string()); - - let markup = InlineKeyboardMarkup::default() - .append_row(vec![button1.clone()]) - .append_to_row(button2.clone(), 0); - - let expected = InlineKeyboardMarkup { inline_keyboard: vec![vec![button1, button2]] }; - - assert_eq!(markup, expected); - } - - #[test] - fn append_to_row_nonexistent_row() { - let button1 = InlineKeyboardButton::url("text 1".to_string(), "url 1".to_string()); - let button2 = InlineKeyboardButton::url("text 2".to_string(), "url 2".to_string()); - - let markup = InlineKeyboardMarkup::default() - .append_row(vec![button1.clone()]) - .append_to_row(button2.clone(), 1); - - let expected = InlineKeyboardMarkup { inline_keyboard: vec![vec![button1], vec![button2]] }; - - assert_eq!(markup, expected); - } -} diff --git a/src/types/inline_query.rs b/src/types/inline_query.rs deleted file mode 100644 index a1c15fc8..00000000 --- a/src/types/inline_query.rs +++ /dev/null @@ -1,74 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{Location, User}; - -/// This object represents an incoming inline query. -/// -/// When the user sends an empty query, your bot could return some default or -/// trending results. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequery). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQuery { - /// Unique identifier for this query. - pub id: String, - - /// Sender. - pub from: User, - - /// Sender location, only for bots that request user location. - pub location: Option, - - /// Text of the query (up to 512 characters). - pub query: String, - - /// Offset of the results to be returned, can be controlled by the bot. - pub offset: String, -} - -impl InlineQuery { - pub fn new(id: S1, from: User, query: S2, offset: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { id: id.into(), from, location: None, query: query.into(), offset: offset.into() } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn from(mut self, val: User) -> Self { - self.from = val; - self - } - - pub fn location(mut self, val: Location) -> Self { - self.location = Some(val); - self - } - - pub fn query(mut self, val: S) -> Self - where - S: Into, - { - self.query = val.into(); - self - } - - pub fn offset(mut self, val: S) -> Self - where - S: Into, - { - self.offset = val.into(); - self - } -} diff --git a/src/types/inline_query_result.rs b/src/types/inline_query_result.rs deleted file mode 100644 index cb9976de..00000000 --- a/src/types/inline_query_result.rs +++ /dev/null @@ -1,102 +0,0 @@ -#![allow(clippy::large_enum_variant)] - -use derive_more::From; -use serde::{Deserialize, Serialize}; - -use crate::types::{ - InlineQueryResultArticle, InlineQueryResultAudio, InlineQueryResultCachedAudio, - InlineQueryResultCachedDocument, InlineQueryResultCachedGif, InlineQueryResultCachedMpeg4Gif, - InlineQueryResultCachedPhoto, InlineQueryResultCachedSticker, InlineQueryResultCachedVideo, - InlineQueryResultCachedVoice, InlineQueryResultContact, InlineQueryResultDocument, - InlineQueryResultGame, InlineQueryResultGif, InlineQueryResultLocation, - InlineQueryResultMpeg4Gif, InlineQueryResultPhoto, InlineQueryResultVenue, - InlineQueryResultVideo, InlineQueryResultVoice, -}; - -/// This object represents one result of an inline query. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresult). -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, From)] -#[serde(tag = "type")] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum InlineQueryResult { - #[serde(rename = "audio")] - CachedAudio(InlineQueryResultCachedAudio), - #[serde(rename = "document")] - CachedDocument(InlineQueryResultCachedDocument), - #[serde(rename = "gif")] - CachedGif(InlineQueryResultCachedGif), - #[serde(rename = "mpeg4_gif")] - CachedMpeg4Gif(InlineQueryResultCachedMpeg4Gif), - #[serde(rename = "photo")] - CachedPhoto(InlineQueryResultCachedPhoto), - #[serde(rename = "sticker")] - CachedSticker(InlineQueryResultCachedSticker), - #[serde(rename = "video")] - CachedVideo(InlineQueryResultCachedVideo), - #[serde(rename = "voice")] - CachedVoice(InlineQueryResultCachedVoice), - - Article(InlineQueryResultArticle), - Audio(InlineQueryResultAudio), - Contact(InlineQueryResultContact), - Game(InlineQueryResultGame), - Document(InlineQueryResultDocument), - Gif(InlineQueryResultGif), - Location(InlineQueryResultLocation), - #[serde(rename = "mpeg4_gif")] - Mpeg4Gif(InlineQueryResultMpeg4Gif), - Photo(InlineQueryResultPhoto), - Venue(InlineQueryResultVenue), - Video(InlineQueryResultVideo), - Voice(InlineQueryResultVoice), -} - -#[cfg(test)] -mod tests { - use crate::types::{ - inline_keyboard_markup::InlineKeyboardMarkup, parse_mode::ParseMode, InlineQueryResult, - InlineQueryResultCachedAudio, InputMessageContent, InputMessageContentText, - }; - - #[test] - fn cached_audio_min_serialize() { - let structure = InlineQueryResult::CachedAudio(InlineQueryResultCachedAudio { - id: String::from("id"), - audio_file_id: String::from("audio_file_id"), - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - }); - - let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id"}"#; - let actual_json = serde_json::to_string(&structure).unwrap(); - - assert_eq!(expected_json, actual_json); - } - - #[test] - fn cached_audio_full_serialize() { - let structure = InlineQueryResult::CachedAudio(InlineQueryResultCachedAudio { - id: String::from("id"), - audio_file_id: String::from("audio_file_id"), - caption: Some(String::from("caption")), - parse_mode: Some(ParseMode::HTML), - reply_markup: Some(InlineKeyboardMarkup::default()), - input_message_content: Some(InputMessageContent::Text(InputMessageContentText { - message_text: String::from("message_text"), - parse_mode: Some(ParseMode::MarkdownV2), - disable_web_page_preview: Some(true), - })), - }); - - let expected_json = r#"{"type":"audio","id":"id","audio_file_id":"audio_file_id","caption":"caption","parse_mode":"HTML","reply_markup":{"inline_keyboard":[]},"input_message_content":{"message_text":"message_text","parse_mode":"MarkdownV2","disable_web_page_preview":true}}"#; - let actual_json = serde_json::to_string(&structure).unwrap(); - - assert_eq!(expected_json, actual_json); - } - - // TODO: Add more tests -} diff --git a/src/types/inline_query_result_article.rs b/src/types/inline_query_result_article.rs deleted file mode 100644 index 2f9bd689..00000000 --- a/src/types/inline_query_result_article.rs +++ /dev/null @@ -1,128 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent}; - -/// Represents a link to an article or web page. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultarticle). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultArticle { - /// Unique identifier for this result, 1-64 Bytes. - pub id: String, - - /// Title of the result. - pub title: String, - - /// Content of the message to be sent. - pub input_message_content: InputMessageContent, - - /// Inline keyboard attached to the message. - pub reply_markup: Option, - - /// URL of the result. - pub url: Option, - - /// Pass `true`, if you don't want the URL to be shown in the - /// message. - pub hide_url: Option, - - /// Short description of the result. - pub description: Option, - - /// Url of the thumbnail for the result. - pub thumb_url: Option, - - /// Thumbnail width. - pub thumb_width: Option, - - /// Thumbnail height. - pub thumb_height: Option, -} - -impl InlineQueryResultArticle { - pub fn new(id: S1, title: S2, input_message_content: InputMessageContent) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - title: title.into(), - input_message_content, - reply_markup: None, - url: None, - hide_url: None, - description: None, - thumb_url: None, - thumb_width: None, - thumb_height: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = val; - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn url(mut self, val: S) -> Self - where - S: Into, - { - self.url = Some(val.into()); - self - } - - pub fn hide_url(mut self, val: bool) -> Self { - self.hide_url = Some(val); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = Some(val.into()); - self - } - - pub fn thumb_width(mut self, val: i32) -> Self { - self.thumb_width = Some(val); - self - } - - pub fn thumb_height(mut self, val: i32) -> Self { - self.thumb_height = Some(val); - self - } -} diff --git a/src/types/inline_query_result_audio.rs b/src/types/inline_query_result_audio.rs deleted file mode 100644 index 648c1bee..00000000 --- a/src/types/inline_query_result_audio.rs +++ /dev/null @@ -1,133 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to an MP3 audio file. By default, this audio file will be -/// sent by the user. -/// -/// Alternatively, you can use `input_message_content` to send a message with -/// the specified content instead of the audio. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultaudio). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultAudio { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL for the audio file. - pub audio_url: String, - - /// Title. - pub title: String, - - /// Caption, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Performer. - pub performer: Option, - - /// Audio duration in seconds. - pub audio_duration: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the audio. - pub input_message_content: Option, -} - -impl InlineQueryResultAudio { - pub fn new(id: S1, audio_url: S2, title: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - audio_url: audio_url.into(), - title: title.into(), - caption: None, - parse_mode: None, - performer: None, - audio_duration: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn audio_url(mut self, val: S) -> Self - where - S: Into, - { - self.audio_url = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn performer(mut self, val: S) -> Self - where - S: Into, - { - self.performer = Some(val.into()); - self - } - - pub fn audio_duration(mut self, val: S) -> Self - where - S: Into, - { - self.audio_duration = Some(val.into()); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_audio.rs b/src/types/inline_query_result_cached_audio.rs deleted file mode 100644 index 5efec634..00000000 --- a/src/types/inline_query_result_cached_audio.rs +++ /dev/null @@ -1,96 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to an MP3 audio file stored on the Telegram servers. -/// -/// By default, this audio file will be sent by the user. Alternatively, you can -/// use `input_message_content` to send a message with the specified content -/// instead of the audio. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedaudio). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedAudio { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier for the audio file. - pub audio_file_id: String, - - /// Caption, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the audio. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedAudio { - pub fn new(id: S1, audio_file_id: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - audio_file_id: audio_file_id.into(), - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn audio_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.audio_file_id = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_document.rs b/src/types/inline_query_result_cached_document.rs deleted file mode 100644 index 882c5858..00000000 --- a/src/types/inline_query_result_cached_document.rs +++ /dev/null @@ -1,121 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a file stored on the Telegram servers. -/// -/// By default, this file will be sent by the user with an optional caption. -/// Alternatively, you can use `input_message_content` to send a message with -/// the specified content instead of the file. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcacheddocument). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedDocument { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// Title for the result. - pub title: String, - - /// A valid file identifier for the file. - pub document_file_id: String, - - /// Short description of the result. - pub description: Option, - - /// Caption of the document to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the file. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedDocument { - pub fn new(id: S1, title: S2, document_file_id: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - title: title.into(), - document_file_id: document_file_id.into(), - description: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn document_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.document_file_id = val.into(); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_gif.rs b/src/types/inline_query_result_cached_gif.rs deleted file mode 100644 index 79fb44db..00000000 --- a/src/types/inline_query_result_cached_gif.rs +++ /dev/null @@ -1,109 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to an animated GIF file stored on the Telegram servers. -/// -/// By default, this animated GIF file will be sent by the user with an optional -/// caption. Alternatively, you can use `input_message_content` to send a -/// message with specified content instead of the animation. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedgif). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedGif { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier for the GIF file. - pub gif_file_id: String, - - /// Title for the result. - pub title: Option, - - /// Caption of the GIF file to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [`ParseMode::Markdown`] or [`ParseMode::HTML`], if you want - /// Telegram apps to show [bold, italic, fixed-width text or inline - /// URLs] in the media caption. - /// - /// [`ParseMode::Markdown`]: crate::types::ParseMode::Markdown - /// [`ParseMode::HTML`]: crate::types::ParseMode::HTML - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the GIF animation. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedGif { - pub fn new(id: S1, gif_file_id: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - gif_file_id: gif_file_id.into(), - title: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn gif_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.gif_file_id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_mpeg4_gif.rs b/src/types/inline_query_result_cached_mpeg4_gif.rs deleted file mode 100644 index 8f97667d..00000000 --- a/src/types/inline_query_result_cached_mpeg4_gif.rs +++ /dev/null @@ -1,101 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a video animation (H.264/MPEG-4 AVC video without -/// sound) stored on the Telegram servers. -/// -/// By default, this animated MPEG-4 file will be sent by the user with an -/// optional caption. Alternatively, you can use `input_message_content` to send -/// a message with the specified content instead of the animation. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedMpeg4Gif { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier for the MP4 file. - pub mpeg4_file_id: String, - - /// Title for the result. - pub title: Option, - - /// Caption of the MPEG-4 file to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the video animation. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedMpeg4Gif { - pub fn new(id: S1, mpeg4_file_id: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - mpeg4_file_id: mpeg4_file_id.into(), - title: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_photo.rs b/src/types/inline_query_result_cached_photo.rs deleted file mode 100644 index ac9d28e8..00000000 --- a/src/types/inline_query_result_cached_photo.rs +++ /dev/null @@ -1,120 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a photo stored on the Telegram servers. -/// -/// By default, this photo will be sent by the user with an optional caption. -/// Alternatively, you can use `input_message_content` to send a message with -/// the specified content instead of the photo. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedphoto). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedPhoto { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier of the photo. - pub photo_file_id: String, - - /// Title for the result. - pub title: Option, - - /// Short description of the result. - pub description: Option, - - /// Caption of the photo to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the photo. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedPhoto { - pub fn new(id: S1, photo_file_id: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - photo_file_id: photo_file_id.into(), - title: None, - description: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn photo_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.photo_file_id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_sticker.rs b/src/types/inline_query_result_cached_sticker.rs deleted file mode 100644 index 0c4e9b88..00000000 --- a/src/types/inline_query_result_cached_sticker.rs +++ /dev/null @@ -1,70 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent}; - -/// Represents a link to a sticker stored on the Telegram servers. -/// -/// By default, this sticker will be sent by the user. Alternatively, you can -/// use `input_message_content` to send a message with the specified content -/// instead of the sticker. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedsticker). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedSticker { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier of the sticker. - pub sticker_file_id: String, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the sticker. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedSticker { - pub fn new(id: S1, sticker_file_id: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - sticker_file_id: sticker_file_id.into(), - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn sticker_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.sticker_file_id = val.into(); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_video.rs b/src/types/inline_query_result_cached_video.rs deleted file mode 100644 index 645892b0..00000000 --- a/src/types/inline_query_result_cached_video.rs +++ /dev/null @@ -1,121 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a video file stored on the Telegram servers. -/// -/// By default, this video file will be sent by the user with an optional -/// caption. Alternatively, you can use `input_message_content` to send a -/// message with the specified content instead of the video. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedvideo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedVideo { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier for the video file. - pub video_file_id: String, - - /// Title for each result. - pub title: String, - - /// Short description of the result. - pub description: Option, - - /// Caption of the video to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the video. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedVideo { - pub fn new(id: S1, video_file_id: S2, title: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - video_file_id: video_file_id.into(), - title: title.into(), - description: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn video_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.video_file_id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_cached_voice.rs b/src/types/inline_query_result_cached_voice.rs deleted file mode 100644 index 1f50672c..00000000 --- a/src/types/inline_query_result_cached_voice.rs +++ /dev/null @@ -1,109 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a voice message stored on the Telegram servers. -/// -/// By default, this voice message will be sent by the user. Alternatively, you -/// can use `input_message_content` to send a message with the specified content -/// instead of the voice message. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedvideo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultCachedVoice { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid file identifier for the voice message. - pub voice_file_id: String, - - /// Voice message title. - pub title: String, - - /// Caption, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the voice message. - pub input_message_content: Option, -} - -impl InlineQueryResultCachedVoice { - pub fn new(id: S1, voice_file_id: S2, title: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - voice_file_id: voice_file_id.into(), - title: title.into(), - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn voice_file_id(mut self, val: S) -> Self - where - S: Into, - { - self.voice_file_id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_contact.rs b/src/types/inline_query_result_contact.rs deleted file mode 100644 index 0b4ae0d8..00000000 --- a/src/types/inline_query_result_contact.rs +++ /dev/null @@ -1,140 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent}; - -/// Represents a contact with a phone number. -/// -/// By default, this contact will be sent by the user. Alternatively, you can -/// use `input_message_content` to send a message with the specified content -/// instead of the contact. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultcachedvideo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultContact { - /// Unique identifier for this result, 1-64 Bytes. - pub id: String, - - /// Contact's phone number. - pub phone_number: String, - - /// Contact's first name. - pub first_name: String, - - /// Contact's last name. - pub last_name: Option, - - /// Additional data about the contact in the form of a [vCard], 0-2048 - /// bytes. - /// - /// [VCard]: https://en.wikipedia.org/wiki/VCard - pub vcard: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the contact. - pub input_message_content: Option, - - /// Url of the thumbnail for the result. - pub thumb_url: Option, - - /// Thumbnail width. - pub thumb_width: Option, - - /// Thumbnail height. - pub thumb_height: Option, -} - -impl InlineQueryResultContact { - pub fn new(id: S1, phone_number: S2, first_name: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - phone_number: phone_number.into(), - first_name: first_name.into(), - last_name: None, - vcard: None, - reply_markup: None, - input_message_content: None, - thumb_url: None, - thumb_width: None, - thumb_height: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn phone_number(mut self, val: S) -> Self - where - S: Into, - { - self.phone_number = val.into(); - self - } - - pub fn first_name(mut self, val: S) -> Self - where - S: Into, - { - self.first_name = val.into(); - self - } - - pub fn last_name(mut self, val: S) -> Self - where - S: Into, - { - self.last_name = Some(val.into()); - self - } - - pub fn vcard(mut self, val: S) -> Self - where - S: Into, - { - self.vcard = Some(val.into()); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = Some(val.into()); - self - } - - pub fn thumb_width(mut self, val: i32) -> Self { - self.thumb_width = Some(val); - self - } - - pub fn thumb_height(mut self, val: i32) -> Self { - self.thumb_height = Some(val); - self - } -} diff --git a/src/types/inline_query_result_document.rs b/src/types/inline_query_result_document.rs deleted file mode 100644 index ea66f561..00000000 --- a/src/types/inline_query_result_document.rs +++ /dev/null @@ -1,138 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, MimeWrapper, ParseMode}; - -/// Represents a link to a file. -/// -/// By default, this file will be sent by the user with an optional caption. -/// Alternatively, you can use `input_message_content` to send a message with -/// the specified content instead of the file. Currently, only **.PDF** and -/// **.ZIP** files can be sent using this method. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultdocument). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultDocument { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// Title for the result. - pub title: String, - - /// Caption of the document to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// A valid URL for the file. - pub document_url: String, - - /// Mime type of the content of the file, either `application/pdf` or - /// `application/zip`. - pub mime_type: MimeWrapper, - - /// Short description of the result. - pub description: Option, - - /// Inline keyboard attached to the message. - pub reply_markup: Option, - - /// Content of the message to be sent instead of the file. - pub input_message_content: Option, - - /// URL of the thumbnail (jpeg only) for the file. - pub thumb_url: Option, - - /// Thumbnail width. - pub thumb_width: Option, - - /// Thumbnail height. - pub thumb_height: Option, -} - -impl InlineQueryResultDocument { - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn document_url(mut self, val: S) -> Self - where - S: Into, - { - self.document_url = val.into(); - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = val; - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = Some(val.into()); - self - } - - pub fn thumb_width(mut self, val: i32) -> Self { - self.thumb_width = Some(val); - self - } - - pub fn thumb_height(mut self, val: i32) -> Self { - self.thumb_height = Some(val); - self - } -} diff --git a/src/types/inline_query_result_game.rs b/src/types/inline_query_result_game.rs deleted file mode 100644 index c795547c..00000000 --- a/src/types/inline_query_result_game.rs +++ /dev/null @@ -1,55 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::InlineKeyboardMarkup; - -/// Represents a [game]. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultgame). -/// -/// [game]: https://core.telegram.org/bots/api#games -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultGame { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// Short name of the game. - pub game_short_name: String, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, -} - -impl InlineQueryResultGame { - pub fn new(id: S1, game_short_name: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { id: id.into(), game_short_name: game_short_name.into(), reply_markup: None } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn game_short_name(mut self, val: S) -> Self - where - S: Into, - { - self.game_short_name = val.into(); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/types/inline_query_result_gif.rs b/src/types/inline_query_result_gif.rs deleted file mode 100644 index 71145de3..00000000 --- a/src/types/inline_query_result_gif.rs +++ /dev/null @@ -1,148 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to an animated GIF file. -/// -/// By default, this animated GIF file will be sent by the user with optional -/// caption. Alternatively, you can use `input_message_content` to send a -/// message with the specified content instead of the animation. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultgif). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultGif { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL for the GIF file. File size must not exceed 1MB. - pub gif_url: String, - - /// Width of the GIF. - pub gif_width: Option, - - /// Height of the GIFv. - pub gif_height: Option, - - /// Duration of the GIF. - pub gif_duration: Option, - - /// URL of the static thumbnail for the result (jpeg or gif). - pub thumb_url: String, - - /// Title for the result. - pub title: Option, - - /// Caption of the GIF file to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the GIF animation. - pub input_message_content: Option, -} - -impl InlineQueryResultGif { - pub fn new(id: S1, gif_url: S2, thumb_url: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - gif_url: gif_url.into(), - gif_width: None, - gif_height: None, - gif_duration: None, - thumb_url: thumb_url.into(), - title: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn gif_url(mut self, val: S) -> Self - where - S: Into, - { - self.gif_url = val.into(); - self - } - - pub fn gif_width(mut self, val: i32) -> Self { - self.gif_width = Some(val); - self - } - - pub fn gif_height(mut self, val: i32) -> Self { - self.gif_height = Some(val); - self - } - - pub fn gif_duration(mut self, val: i32) -> Self { - self.gif_duration = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_location.rs b/src/types/inline_query_result_location.rs deleted file mode 100644 index 1d6d9270..00000000 --- a/src/types/inline_query_result_location.rs +++ /dev/null @@ -1,128 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent}; - -/// Represents a location on a map. -/// -/// By default, the location will be sent by the user. Alternatively, you can -/// use `input_message_content` to send a message with the specified content -/// instead of the location. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultlocation). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultLocation { - /// Unique identifier for this result, 1-64 Bytes. - pub id: String, - - /// Location latitude in degrees. - pub latitude: f64, - - /// Location longitude in degrees. - pub longitude: f64, - - /// Location title. - pub title: String, - - /// Period in seconds for which the location can be updated, should be - /// between 60 and 86400. - pub live_period: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the location. - pub input_message_content: Option, - - /// Url of the thumbnail for the result. - pub thumb_url: Option, - - /// Thumbnail width. - pub thumb_width: Option, - - /// Thumbnail height. - pub thumb_height: Option, -} - -impl InlineQueryResultLocation { - pub fn new(id: S1, title: S2, latitude: f64, longitude: f64) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - title: title.into(), - latitude, - longitude, - live_period: None, - reply_markup: None, - input_message_content: None, - thumb_url: None, - thumb_width: None, - thumb_height: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn latitude(mut self, val: f64) -> Self { - self.latitude = val; - self - } - - pub fn longitude(mut self, val: f64) -> Self { - self.longitude = val; - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn live_period(mut self, val: i32) -> Self { - self.live_period = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = Some(val.into()); - self - } - - pub fn thumb_width(mut self, val: i32) -> Self { - self.thumb_width = Some(val); - self - } - - pub fn thumb_height(mut self, val: i32) -> Self { - self.thumb_height = Some(val); - self - } -} diff --git a/src/types/inline_query_result_mpeg4_gif.rs b/src/types/inline_query_result_mpeg4_gif.rs deleted file mode 100644 index 6c01ceb7..00000000 --- a/src/types/inline_query_result_mpeg4_gif.rs +++ /dev/null @@ -1,149 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a video animation (H.264/MPEG-4 AVC video without -/// sound). -/// -/// By default, this animated MPEG-4 file will be sent by the user with optional -/// caption. Alternatively, you can use `input_message_content` to send -/// a message with the specified content instead of the animation. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultMpeg4Gif { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL for the MP4 file. File size must not exceed 1MB. - pub mpeg4_url: String, - - /// Video width. - pub mpeg4_width: Option, - - /// Video height. - pub mpeg4_height: Option, - - /// Video duration. - pub mpeg4_duration: Option, - - /// URL of the static thumbnail (jpeg or gif) for the result. - pub thumb_url: String, - - /// Title for the result. - pub title: Option, - - /// Caption of the MPEG-4 file to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the video animation. - pub input_message_content: Option, -} - -impl InlineQueryResultMpeg4Gif { - pub fn new(id: S1, mpeg4_url: S2, thumb_url: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - mpeg4_url: mpeg4_url.into(), - thumb_url: thumb_url.into(), - mpeg4_width: None, - mpeg4_height: None, - mpeg4_duration: None, - title: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn mpeg4_url(mut self, val: S) -> Self - where - S: Into, - { - self.mpeg4_url = val.into(); - self - } - - pub fn mpeg4_width(mut self, val: i32) -> Self { - self.mpeg4_width = Some(val); - self - } - - pub fn mpeg4_height(mut self, val: i32) -> Self { - self.mpeg4_height = Some(val); - self - } - - pub fn mpeg4_duration(mut self, val: i32) -> Self { - self.mpeg4_duration = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_photo.rs b/src/types/inline_query_result_photo.rs deleted file mode 100644 index e1d32dc9..00000000 --- a/src/types/inline_query_result_photo.rs +++ /dev/null @@ -1,152 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a photo. -/// -/// By default, this photo will be sent by the user with optional caption. -/// Alternatively, you can use `input_message_content` to send a message with -/// the specified content instead of the photo. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultphoto). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultPhoto { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL of the photo. Photo must be in **jpeg** format. Photo size - /// must not exceed 5MB. - pub photo_url: String, - - /// URL of the thumbnail for the photo. - pub thumb_url: String, - - /// Width of the photo. - pub photo_width: Option, - - /// Height of the photo. - pub photo_height: Option, - - /// Title for the result. - pub title: Option, - - /// Short description of the result. - pub description: Option, - - /// Caption of the photo to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the photo. - pub input_message_content: Option, -} - -impl InlineQueryResultPhoto { - pub fn new(id: S1, photo_url: S2, thumb_url: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - photo_url: photo_url.into(), - thumb_url: thumb_url.into(), - photo_width: None, - photo_height: None, - title: None, - description: None, - caption: None, - parse_mode: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn photo_url(mut self, val: S) -> Self - where - S: Into, - { - self.photo_url = val.into(); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = val.into(); - self - } - - pub fn photo_width(mut self, val: i32) -> Self { - self.photo_width = Some(val); - self - } - - pub fn photo_height(mut self, val: i32) -> Self { - self.photo_height = Some(val); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_venue.rs b/src/types/inline_query_result_venue.rs deleted file mode 100644 index c7e67443..00000000 --- a/src/types/inline_query_result_venue.rs +++ /dev/null @@ -1,157 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent}; - -/// Represents a venue. -/// -/// By default, the venue will be sent by the user. Alternatively, you can use -/// `input_message_content` to send a message with the specified content instead -/// of the venue. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultvenue). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultVenue { - /// Unique identifier for this result, 1-64 Bytes. - pub id: String, - - /// Latitude of the venue location in degrees. - pub latitude: f64, - - /// Longitude of the venue location in degrees. - pub longitude: f64, - - /// Title of the venue. - pub title: String, - - /// Address of the venue. - pub address: String, - - /// Foursquare identifier of the venue if known. - pub foursquare_id: Option, - - /// Foursquare type of the venue, if known. (For example, - /// `arts_entertainment/default`, `arts_entertainment/aquarium` or - /// `food/icecream`.) - pub foursquare_type: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the venue. - pub input_message_content: Option, - - /// Url of the thumbnail for the result. - pub thumb_url: Option, - - /// Thumbnail width. - pub thumb_width: Option, - - /// Thumbnail height. - pub thumb_height: Option, -} - -impl InlineQueryResultVenue { - pub fn new(id: S1, latitude: f64, longitude: f64, title: S2, address: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - latitude, - longitude, - title: title.into(), - address: address.into(), - foursquare_id: None, - foursquare_type: None, - reply_markup: None, - input_message_content: None, - thumb_url: None, - thumb_width: None, - thumb_height: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn latitude(mut self, val: f64) -> Self { - self.latitude = val; - self - } - - pub fn longitude(mut self, val: f64) -> Self { - self.longitude = val; - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn address(mut self, val: S) -> Self - where - S: Into, - { - self.address = val.into(); - self - } - - pub fn foursquare_id(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_id = Some(val.into()); - self - } - - pub fn foursquare_type(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_type = Some(val.into()); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = Some(val.into()); - self - } - - pub fn thumb_width(mut self, val: i32) -> Self { - self.thumb_width = Some(val); - self - } - - pub fn thumb_height(mut self, val: i32) -> Self { - self.thumb_height = Some(val); - self - } -} diff --git a/src/types/inline_query_result_video.rs b/src/types/inline_query_result_video.rs deleted file mode 100644 index d51258fc..00000000 --- a/src/types/inline_query_result_video.rs +++ /dev/null @@ -1,182 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, MimeWrapper, ParseMode}; - -/// Represents a link to a page containing an embedded video player or a video -/// file. -/// -/// By default, this video file will be sent by the user with an optional -/// caption. Alternatively, you can use `input_messaage_content` to send a -/// message with the specified content instead of the video. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultvideo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultVideo { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL for the embedded video player or video file. - pub video_url: String, - - /// Mime type of the content of video url, `text/html` or `video/mp4`. - pub mime_type: MimeWrapper, - - /// URL of the thumbnail (jpeg only) for the video. - pub thumb_url: String, - - /// Title for the result. - pub title: String, - - /// Caption of the video to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Video width. - pub video_width: Option, - - /// Video height. - pub video_height: Option, - - /// Video duration in seconds. - pub video_duration: Option, - - /// Short description of the result. - pub description: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the video. This field is - /// **required** if [`InlineQueryResultVideo`] is used to send an HTML-page - /// as a result (e.g., a YouTube video). - /// - /// [`InlineQueryResultVideo`]: - /// crate::types::InlineQueryResultVideo - pub input_message_content: Option, -} - -impl InlineQueryResultVideo { - pub fn new( - id: S1, - video_url: S2, - mime_type: MimeWrapper, - thumb_url: S3, - title: S4, - ) -> Self - where - S1: Into, - S2: Into, - S3: Into, - S4: Into, - { - Self { - id: id.into(), - video_url: video_url.into(), - mime_type, - thumb_url: thumb_url.into(), - title: title.into(), - caption: None, - parse_mode: None, - video_width: None, - video_height: None, - video_duration: None, - description: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn video_url(mut self, val: S) -> Self - where - S: Into, - { - self.video_url = val.into(); - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = val; - self - } - - pub fn thumb_url(mut self, val: S) -> Self - where - S: Into, - { - self.thumb_url = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn video_width(mut self, val: i32) -> Self { - self.video_width = Some(val); - self - } - - pub fn video_height(mut self, val: i32) -> Self { - self.video_height = Some(val); - self - } - - pub fn video_duration(mut self, val: i32) -> Self { - self.video_duration = Some(val); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = Some(val.into()); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/inline_query_result_voice.rs b/src/types/inline_query_result_voice.rs deleted file mode 100644 index db812b7e..00000000 --- a/src/types/inline_query_result_voice.rs +++ /dev/null @@ -1,119 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; - -/// Represents a link to a voice recording in an .ogg container encoded with -/// OPUS. -/// -/// By default, this voice recording will be sent by the user. Alternatively, -/// you can use `input_message_content` to send a message with the specified -/// content instead of the the voice message. -/// -/// [The official docs](https://core.telegram.org/bots/api#inlinequeryresultvoice). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InlineQueryResultVoice { - /// Unique identifier for this result, 1-64 bytes. - pub id: String, - - /// A valid URL for the voice recording. - pub voice_url: String, - - /// Recording title. - pub title: String, - - /// Caption, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Recording duration in seconds. - pub voice_duration: Option, - - /// [Inline keyboard] attached to the message. - /// - /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating - pub reply_markup: Option, - - /// Content of the message to be sent instead of the voice recording. - pub input_message_content: Option, -} - -impl InlineQueryResultVoice { - pub fn new(id: S1, voice_url: S2, title: S3) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - id: id.into(), - voice_url: voice_url.into(), - title: title.into(), - caption: None, - parse_mode: None, - voice_duration: None, - reply_markup: None, - input_message_content: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn voice_url(mut self, val: S) -> Self - where - S: Into, - { - self.voice_url = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn voice_duration(mut self, value: i32) -> Self { - self.voice_duration = Some(value); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } - - pub fn input_message_content(mut self, val: InputMessageContent) -> Self { - self.input_message_content = Some(val); - self - } -} diff --git a/src/types/input_file.rs b/src/types/input_file.rs deleted file mode 100644 index 55e15e14..00000000 --- a/src/types/input_file.rs +++ /dev/null @@ -1,101 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use std::{borrow::Cow, path::PathBuf}; - -/// This object represents the contents of a file to be uploaded. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputfile). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize)] -#[non_exhaustive] -pub enum InputFile { - File(PathBuf), - Memory { file_name: String, data: Cow<'static, [u8]> }, - Url(String), - FileId(String), -} - -impl InputFile { - pub fn file

(path: P) -> Self - where - P: Into, - { - Self::File(path.into()) - } - - pub fn memory(file_name: S, data: D) -> Self - where - S: Into, - D: Into>, - { - Self::Memory { file_name: file_name.into(), data: data.into() } - } - - pub fn url(url: T) -> Self - where - T: Into, - { - Self::Url(url.into()) - } - - pub fn file_id(file_id: T) -> Self - where - T: Into, - { - Self::FileId(file_id.into()) - } - - pub fn as_file(&self) -> Option<&PathBuf> { - match self { - Self::File(path) => Some(path), - _ => None, - } - } - - pub fn as_url(&self) -> Option<&String> { - match self { - Self::Url(url) => Some(url), - _ => None, - } - } - - pub fn as_file_id(&self) -> Option<&String> { - match self { - Self::FileId(id) => Some(id), - _ => None, - } - } -} - -impl From for Option { - fn from(file: InputFile) -> Self { - match file { - InputFile::File(path) => Some(path), - _ => None, - } - } -} - -impl Serialize for InputFile { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - InputFile::File(path) => { - // NOTE: file should be actually attached with - // multipart/form-data - serializer.serialize_str( - // TODO: remove unwrap (?) - &format!("attach://{}", path.file_name().unwrap().to_string_lossy()), - ) - } - InputFile::Memory { data, .. } => { - // NOTE: file should be actually attached with - // multipart/form-data - serializer.serialize_str(&format!("attach://{}", String::from_utf8_lossy(data))) - } - InputFile::Url(url) => serializer.serialize_str(url), - InputFile::FileId(id) => serializer.serialize_str(id), - } - } -} diff --git a/src/types/input_media.rs b/src/types/input_media.rs deleted file mode 100644 index a37ebda4..00000000 --- a/src/types/input_media.rs +++ /dev/null @@ -1,511 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{InputFile, ParseMode}; - -/// This object represents the content of a media message to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmedia). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(tag = "type")] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum InputMedia { - Photo(InputMediaPhoto), - Video(InputMediaVideo), - Animation(InputMediaAnimation), - Audio(InputMediaAudio), - Document(InputMediaDocument), -} - -/// Represents a photo to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmediaphoto). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMediaPhoto { - /// File to send. - pub media: InputFile, - - /// Caption of the photo to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, -} - -impl InputMediaPhoto { - pub fn new(media: InputFile) -> Self { - Self { media, caption: None, parse_mode: None } - } - - pub fn media(mut self, val: InputFile) -> Self { - self.media = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } -} - -/// Represents a video to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmediavideo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMediaVideo { - // File to send. - pub media: InputFile, - - /// Thumbnail of the file sent; can be ignored if thumbnail generation - /// for the file is supported server-side. The thumbnail should be in - /// JPEG format and less than 200 kB in size. A thumbnail‘s width and - /// height should not exceed 320. Ignored if the file is not uploaded - /// using multipart/form-data. - pub thumb: Option, - - /// Caption of the video to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Video width. - pub width: Option, - - /// Video height. - pub height: Option, - - /// Video duration. - pub duration: Option, - - /// Pass `true`, if the uploaded video is suitable for streaming. - pub supports_streaming: Option, -} - -impl InputMediaVideo { - pub fn new(media: InputFile) -> Self { - Self { - media, - thumb: None, - caption: None, - parse_mode: None, - width: None, - height: None, - duration: None, - supports_streaming: None, - } - } - - pub fn media(mut self, val: InputFile) -> Self { - self.media = val; - self - } - - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn width(mut self, val: u16) -> Self { - self.width = Some(val); - self - } - - pub fn height(mut self, val: u16) -> Self { - self.height = Some(val); - self - } - - pub fn duration(mut self, val: u16) -> Self { - self.duration = Some(val); - self - } - - pub fn supports_streaming(mut self, val: bool) -> Self { - self.supports_streaming = Some(val); - self - } -} - -/// Represents an animation file (GIF or H.264/MPEG-4 AVC video without -/// sound) to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmediaanimation). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMediaAnimation { - /// File to send. - pub media: InputFile, - - /// Thumbnail of the file sent; can be ignored if thumbnail generation - /// for the file is supported server-side. The thumbnail should be in - /// JPEG format and less than 200 kB in size. A thumbnail‘s width and - /// height should not exceed 320. Ignored if the file is not uploaded - /// using multipart/form-data. - pub thumb: Option, - - /// Caption of the animation to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Animation width. - pub width: Option, - - /// Animation height. - pub height: Option, - - /// Animation duration. - pub duration: Option, -} - -impl InputMediaAnimation { - pub fn new(media: InputFile) -> Self { - Self { - media, - thumb: None, - caption: None, - parse_mode: None, - width: None, - height: None, - duration: None, - } - } - - pub fn media(mut self, val: InputFile) -> Self { - self.media = val; - self - } - - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn width(mut self, val: u16) -> Self { - self.width = Some(val); - self - } - - pub fn height(mut self, val: u16) -> Self { - self.height = Some(val); - self - } - - pub fn duration(mut self, val: u16) -> Self { - self.duration = Some(val); - self - } -} - -/// Represents an audio file to be treated as music to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmediaaudio). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMediaAudio { - /// File to send. - pub media: InputFile, - - /// Thumbnail of the file sent; can be ignored if thumbnail generation - /// for the file is supported server-side. The thumbnail should be in - /// JPEG format and less than 200 kB in size. A thumbnail‘s width and - /// height should not exceed 320. Ignored if the file is not uploaded - /// using multipart/form-data. - pub thumb: Option, - - /// Caption of the audio to be sent, 0-1024 characters. - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Duration of the audio in seconds. - pub duration: Option, - - /// Performer of the audio. - pub performer: Option, - - /// Title of the audio. - pub title: Option, -} - -impl InputMediaAudio { - pub fn new(media: InputFile) -> Self { - Self { - media, - thumb: None, - caption: None, - parse_mode: None, - performer: None, - title: None, - duration: None, - } - } - - pub fn media(mut self, val: InputFile) -> Self { - self.media = val; - self - } - - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn duration(mut self, val: u16) -> Self { - self.duration = Some(val); - self - } - - pub fn performer(mut self, val: S) -> Self - where - S: Into, - { - self.performer = Some(val.into()); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = Some(val.into()); - self - } -} - -/// Represents a general file to be sent. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmediadocument). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMediaDocument { - /// File to send. - pub media: InputFile, - - /// Thumbnail of the file sent; can be ignored if thumbnail generation - /// for the file is supported server-side. The thumbnail should be in - /// JPEG format and less than 200 kB in size. A thumbnail‘s width and - /// height should not exceed 320. Ignored if the file is not uploaded - /// using multipart/form-data. - pub thumb: Option, - - /// Caption of the document to be sent, 0-1024 charactersю - pub caption: Option, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, -} - -impl InputMediaDocument { - pub fn new(media: InputFile) -> Self { - Self { media, thumb: None, caption: None, parse_mode: None } - } - - pub fn thumb(mut self, val: InputFile) -> Self { - self.thumb = Some(val); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } -} - -impl InputMedia { - pub fn media(&self) -> &InputFile { - match self { - InputMedia::Photo(InputMediaPhoto { media, .. }) - | InputMedia::Document(InputMediaDocument { media, .. }) - | InputMedia::Audio(InputMediaAudio { media, .. }) - | InputMedia::Animation(InputMediaAnimation { media, .. }) - | InputMedia::Video(InputMediaVideo { media, .. }) => media, - } - } -} - -impl From for InputFile { - fn from(media: InputMedia) -> InputFile { - match media { - InputMedia::Photo(InputMediaPhoto { media, .. }) - | InputMedia::Document(InputMediaDocument { media, .. }) - | InputMedia::Audio(InputMediaAudio { media, .. }) - | InputMedia::Animation(InputMediaAnimation { media, .. }) - | InputMedia::Video(InputMediaVideo { media, .. }) => media, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn photo_serialize() { - let expected_json = r#"{"type":"photo","media":"123456"}"#; - let photo = InputMedia::Photo(InputMediaPhoto { - media: InputFile::FileId(String::from("123456")), - caption: None, - parse_mode: None, - }); - - let actual_json = serde_json::to_string(&photo).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn video_serialize() { - let expected_json = r#"{"type":"video","media":"123456"}"#; - let video = InputMedia::Video(InputMediaVideo { - media: InputFile::FileId(String::from("123456")), - thumb: None, - caption: None, - parse_mode: None, - width: None, - height: None, - duration: None, - supports_streaming: None, - }); - - let actual_json = serde_json::to_string(&video).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn animation_serialize() { - let expected_json = r#"{"type":"animation","media":"123456"}"#; - let video = InputMedia::Animation(InputMediaAnimation { - media: InputFile::FileId(String::from("123456")), - thumb: None, - caption: None, - parse_mode: None, - width: None, - height: None, - duration: None, - }); - - let actual_json = serde_json::to_string(&video).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn audio_serialize() { - let expected_json = r#"{"type":"audio","media":"123456"}"#; - let video = InputMedia::Audio(InputMediaAudio { - media: InputFile::FileId(String::from("123456")), - thumb: None, - caption: None, - parse_mode: None, - duration: None, - performer: None, - title: None, - }); - - let actual_json = serde_json::to_string(&video).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn document_serialize() { - let expected_json = r#"{"type":"document","media":"123456"}"#; - let video = InputMedia::Document(InputMediaDocument { - media: InputFile::FileId(String::from("123456")), - thumb: None, - caption: None, - parse_mode: None, - }); - - let actual_json = serde_json::to_string(&video).unwrap(); - assert_eq!(expected_json, actual_json); - } -} diff --git a/src/types/input_message_content.rs b/src/types/input_message_content.rs deleted file mode 100644 index caf57650..00000000 --- a/src/types/input_message_content.rs +++ /dev/null @@ -1,318 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::ParseMode; - -/// This object represents the content of a message to be sent as a result of an -/// inline query. -/// -/// [The official docs](https://core.telegram.org/bots/api#inputmessagecontent). -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[non_exhaustive] -pub enum InputMessageContent { - Text(InputMessageContentText), - Location(InputMessageContentLocation), - Venue(InputMessageContentVenue), - Contact(InputMessageContentContact), -} -/// Represents the content of a text message to be sent as the result of an -/// inline query. -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMessageContentText { - /// Text of the message to be sent, 1-4096 characters. - pub message_text: String, - - /// Send [Markdown] or [HTML], if you want Telegram apps to show [bold, - /// italic, fixed-width text or inline URLs] in the media caption. - /// - /// [Markdown]: https://core.telegram.org/bots/api#markdown-style - /// [HTML]: https://core.telegram.org/bots/api#html-style - /// [bold, italic, fixed-width text or inline URLs]: https://core.telegram.org/bots/api#formatting-options - pub parse_mode: Option, - - /// Disables link previews for links in the sent message. - pub disable_web_page_preview: Option, -} - -impl InputMessageContentText { - pub fn new(message_text: S) -> Self - where - S: Into, - { - Self { message_text: message_text.into(), parse_mode: None, disable_web_page_preview: None } - } - - pub fn message_text(mut self, val: S) -> Self - where - S: Into, - { - self.message_text = val.into(); - self - } - - pub fn parse_mode(mut self, val: ParseMode) -> Self { - self.parse_mode = Some(val); - self - } - - pub fn disable_web_page_preview(mut self, val: bool) -> Self { - self.disable_web_page_preview = Some(val); - self - } -} - -/// Represents the content of a location message to be sent as the result of an -/// inline query. -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMessageContentLocation { - /// Latitude of the location in degrees. - pub latitude: f64, - - /// Longitude of the location in degrees. - pub longitude: f64, - - /// Period in seconds for which the location can be updated, should be - /// between 60 and 86400. - pub live_period: Option, -} - -impl InputMessageContentLocation { - pub fn new(latitude: f64, longitude: f64) -> Self { - Self { latitude, longitude, live_period: None } - } - - pub fn latitude(mut self, val: f64) -> Self { - self.latitude = val; - self - } - - pub fn longitude(mut self, val: f64) -> Self { - self.longitude = val; - self - } - - pub fn live_period(mut self, val: u32) -> Self { - self.live_period = Some(val); - self - } -} - -/// Represents the content of a venue message to be sent as the result of -/// an inline query. -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMessageContentVenue { - /// Latitude of the venue in degrees. - pub latitude: f64, - - /// Longitude of the venue in degrees. - pub longitude: f64, - - /// Name of the venue. - pub title: String, - - /// Address of the venue. - pub address: String, - - /// Foursquare identifier of the venue, if known. - pub foursquare_id: Option, - - /// Foursquare type of the venue, if known. (For example, - /// `arts_entertainment/default`, `arts_entertainment/aquarium` - /// or `food/icecream`.) - pub foursquare_type: Option, -} - -impl InputMessageContentVenue { - pub fn new(latitude: f64, longitude: f64, title: S1, address: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - latitude, - longitude, - title: title.into(), - address: address.into(), - foursquare_id: None, - foursquare_type: None, - } - } - - pub fn latitude(mut self, val: f64) -> Self { - self.latitude = val; - self - } - - pub fn longitude(mut self, val: f64) -> Self { - self.longitude = val; - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn address(mut self, val: S) -> Self - where - S: Into, - { - self.address = val.into(); - self - } - - pub fn foursquare_id(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_id = Some(val.into()); - self - } - - pub fn foursquare_type(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_type = Some(val.into()); - self - } -} - -/// Represents the content of a contact message to be sent as the result of -/// an inline query. -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct InputMessageContentContact { - /// Contact's phone number. - pub phone_number: String, - - /// Contact's first name. - pub first_name: String, - - /// Contact's last name. - pub last_name: Option, - - /// Additional data about the contact in the form of a [vCard], 0-2048 - /// bytes. - /// - /// [vCard]: https://en.wikipedia.org/wiki/VCard - pub vcard: Option, -} - -impl InputMessageContentContact { - pub fn new(phone_number: S1, first_name: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - phone_number: phone_number.into(), - first_name: first_name.into(), - last_name: None, - vcard: None, - } - } - - pub fn phone_number(mut self, val: S) -> Self - where - S: Into, - { - self.phone_number = val.into(); - self - } - - pub fn first_name(mut self, val: S) -> Self - where - S: Into, - { - self.first_name = val.into(); - self - } - - pub fn last_name(mut self, val: S) -> Self - where - S: Into, - { - self.last_name = Some(val.into()); - self - } - - pub fn vcard(mut self, val: S) -> Self - where - S: Into, - { - self.vcard = Some(val.into()); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn text_serialize() { - let expected_json = r#"{"message_text":"text"}"#; - let text_content = InputMessageContent::Text(InputMessageContentText { - message_text: String::from("text"), - parse_mode: None, - disable_web_page_preview: None, - }); - - let actual_json = serde_json::to_string(&text_content).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn location_serialize() { - let expected_json = r#"{"latitude":59.08,"longitude":38.4326}"#; - let location_content = InputMessageContent::Location(InputMessageContentLocation { - latitude: 59.08, - longitude: 38.4326, - live_period: None, - }); - - let actual_json = serde_json::to_string(&location_content).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn venue_serialize() { - let expected_json = r#"{"latitude":59.08,"longitude":38.4326,"title":"some title","address":"some address"}"#; - let venue_content = InputMessageContent::Venue(InputMessageContentVenue { - latitude: 59.08, - longitude: 38.4326, - title: String::from("some title"), - address: String::from("some address"), - foursquare_id: None, - foursquare_type: None, - }); - - let actual_json = serde_json::to_string(&venue_content).unwrap(); - assert_eq!(expected_json, actual_json); - } - - #[test] - fn contact_serialize() { - let expected_json = r#"{"phone_number":"+3800000000","first_name":"jhon"}"#; - let contact_content = InputMessageContent::Contact(InputMessageContentContact { - phone_number: String::from("+3800000000"), - first_name: String::from("jhon"), - last_name: None, - vcard: None, - }); - - let actual_json = serde_json::to_string(&contact_content).unwrap(); - assert_eq!(expected_json, actual_json); - } -} diff --git a/src/types/invoice.rs b/src/types/invoice.rs deleted file mode 100644 index 979881e1..00000000 --- a/src/types/invoice.rs +++ /dev/null @@ -1,91 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object contains basic information about an invoice. -/// -/// [The official docs](https://core.telegram.org/bots/api#invoice). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Invoice { - /// Product name. - pub title: String, - - /// Product description. - pub description: String, - - /// Unique bot deep-linking parameter that can be used to generate this - /// invoice. - pub start_parameter: String, - - /// Three-letter ISO 4217 currency code. - pub currency: String, - - /// Total price in the smallest units of the currency (integer, **not** - /// float/double). For example, for a price of `US$ 1.45` pass `amount = - /// 145`. See the exp parameter in [`currencies.json`], it shows the number - /// of digits past the decimal point for each currency (2 for the - /// majority of currencies). - /// - /// [`currencies.json`]: https://core.telegram.org/bots/payments/currencies.json - pub total_amount: i32, -} - -impl Invoice { - pub fn new( - title: S1, - description: S2, - start_parameter: S3, - currency: S4, - total_amount: i32, - ) -> Self - where - S1: Into, - S2: Into, - S3: Into, - S4: Into, - { - Self { - title: title.into(), - description: description.into(), - start_parameter: start_parameter.into(), - currency: currency.into(), - total_amount, - } - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = val.into(); - self - } - - pub fn start_parameter(mut self, val: S) -> Self - where - S: Into, - { - self.start_parameter = val.into(); - self - } - - pub fn currency(mut self, val: S) -> Self - where - S: Into, - { - self.currency = val.into(); - self - } - - pub fn total_amount(mut self, val: i32) -> Self { - self.total_amount = val; - self - } -} diff --git a/src/types/keyboard_button.rs b/src/types/keyboard_button.rs deleted file mode 100644 index fc37134a..00000000 --- a/src/types/keyboard_button.rs +++ /dev/null @@ -1,156 +0,0 @@ -use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; - -use crate::types::{KeyboardButtonPollType, True}; - -/// This object represents one button of the reply keyboard. -/// -/// For filter text buttons String can be used instead of this object to specify -/// text of the button. -/// -/// [The official docs](https://core.telegram.org/bots/api#keyboardbutton). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct KeyboardButton { - /// Text of the button. If none of the optional fields are used, it will - /// be sent as a message when the button is pressed. - pub text: String, - - /// Request something from user. - /// - If `Some(Contact)`, the user's phone number will be sent as a contact - /// when the button is pressed. Available in private chats only - /// - If `Some(Location)`, the user's current location will be sent when the - /// button is pressed. Available in private chats only - #[serde(flatten)] - pub request: Option, -} - -impl KeyboardButton { - pub fn new(text: T) -> Self - where - T: Into, - { - Self { text: text.into(), request: None } - } - - pub fn request(mut self, val: T) -> Self - where - T: Into>, - { - self.request = val.into(); - self - } -} - -// Serialize + Deserialize are implemented by hand -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum ButtonRequest { - Location, - Contact, - KeyboardButtonPollType(KeyboardButtonPollType), -} - -/// Helper struct for (de)serializing [`ButtonRequest`](ButtonRequest) -#[serde_with_macros::skip_serializing_none] -#[derive(Serialize, Deserialize)] -#[non_exhaustive] -struct RawRequest { - /// If `true`, the user's phone number will be sent as a contact - /// when the button is pressed. Available in private chats only. - #[serde(rename = "request_contact")] - contact: Option, - - /// If `true`, the user's current location will be sent when the - /// button is pressed. Available in private chats only. - #[serde(rename = "request_location")] - location: Option, - - /// If specified, the user will be asked to create a poll and - /// send it to the bot when the button is pressed. Available in private - /// chats only. - #[serde(rename = "request_poll")] - poll: Option, -} - -impl<'de> Deserialize<'de> for ButtonRequest { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let raw = RawRequest::deserialize(deserializer)?; - match raw { - RawRequest { contact: Some(_), location: Some(_), poll: Some(_) } => { - Err(D::Error::custom( - "`request_contact` and `request_location` fields are mutually exclusive, but \ - both were provided", - )) - } - RawRequest { contact: Some(_), .. } => Ok(Self::Contact), - RawRequest { location: Some(_), .. } => Ok(Self::Location), - RawRequest { poll: Some(poll_type), .. } => Ok(Self::KeyboardButtonPollType(poll_type)), - _ => Err(D::Error::custom( - "Either one of `request_contact` and `request_location` fields is required", - )), - } - } -} - -impl Serialize for ButtonRequest { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match self { - Self::Contact => { - RawRequest { contact: Some(True), location: None, poll: None }.serialize(serializer) - } - Self::Location => { - RawRequest { contact: None, location: Some(True), poll: None }.serialize(serializer) - } - Self::KeyboardButtonPollType(poll_type) => { - RawRequest { contact: None, location: None, poll: Some(poll_type.clone()) } - .serialize(serializer) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn serialize_no_request() { - let button = KeyboardButton { text: String::from(""), request: None }; - let expected = r#"{"text":""}"#; - let actual = serde_json::to_string(&button).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn serialize_request_contact() { - let button = - KeyboardButton { text: String::from(""), request: Some(ButtonRequest::Contact) }; - let expected = r#"{"text":"","request_contact":true}"#; - let actual = serde_json::to_string(&button).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn deserialize_no_request() { - let json = r#"{"text":""}"#; - let expected = KeyboardButton { text: String::from(""), request: None }; - let actual = serde_json::from_str(json).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn deserialize_request_contact() { - let json = r#"{"text":"","request_contact":true}"#; - let expected = - KeyboardButton { text: String::from(""), request: Some(ButtonRequest::Contact) }; - let actual = serde_json::from_str(json).unwrap(); - assert_eq!(expected, actual); - } -} diff --git a/src/types/keyboard_button_poll_type.rs b/src/types/keyboard_button_poll_type.rs deleted file mode 100644 index 6b24d540..00000000 --- a/src/types/keyboard_button_poll_type.rs +++ /dev/null @@ -1,24 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct KeyboardButtonPollType { - poll_type: String, -} - -impl KeyboardButtonPollType { - pub fn new(poll_type: S) -> Self - where - S: Into, - { - Self { poll_type: poll_type.into() } - } - - pub fn poll_type(mut self, val: S) -> Self - where - S: Into, - { - self.poll_type = val.into(); - self - } -} diff --git a/src/types/label_price.rs b/src/types/label_price.rs deleted file mode 100644 index 4c6841a9..00000000 --- a/src/types/label_price.rs +++ /dev/null @@ -1,56 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a portion of the price for goods or services. -/// -/// [The official docs](https://core.telegram.org/bots/api#labeledprice). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct LabeledPrice { - /// Portion label. - pub label: String, - - /// Price of the product in the smallest units of the [currency] (integer, - /// **not** float/double). For example, for a price of `US$ 1.45` pass - /// `amount = 145`. See the exp parameter in [`currencies.json`], it shows - /// the number of digits past the decimal point for each currency (2 - /// for the majority of currencies). - /// - /// [currency]: https://core.telegram.org/bots/payments#supported-currencies - /// [`currencies.json`]: https://core.telegram.org/bots/payments/currencies.json - pub amount: i32, -} - -impl LabeledPrice { - pub fn new(label: S, amount: i32) -> Self - where - S: Into, - { - Self { label: label.into(), amount } - } - - pub fn label(mut self, val: S) -> Self - where - S: Into, - { - self.label = val.into(); - self - } - - pub fn amount(mut self, val: i32) -> Self { - self.amount = val; - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn serialize() { - let labeled_price = LabeledPrice { label: "Label".to_string(), amount: 60 }; - let expected = r#"{"label":"Label","amount":60}"#; - let actual = serde_json::to_string(&labeled_price).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/src/types/location.rs b/src/types/location.rs deleted file mode 100644 index e34cee1a..00000000 --- a/src/types/location.rs +++ /dev/null @@ -1,28 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a point on the map. -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Location { - /// Longitude as defined by sender. - pub longitude: f64, - - /// Latitude as defined by sender. - pub latitude: f64, -} - -impl Location { - pub fn new(longitude: f64, latitude: f64) -> Self { - Self { longitude, latitude } - } - - pub fn latitude(mut self, val: f64) -> Self { - self.latitude = val; - self - } - - pub fn longitude(mut self, val: f64) -> Self { - self.longitude = val; - self - } -} diff --git a/src/types/login_url.rs b/src/types/login_url.rs deleted file mode 100644 index 36515cd6..00000000 --- a/src/types/login_url.rs +++ /dev/null @@ -1,61 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a parameter of the inline keyboard button used to -/// automatically authorize a user. -/// -/// Serves as a great replacement for the [Telegram Login Widget] when the user -/// is coming from Telegram. All the user needs to do is tap/click a button and -/// confirm that they want to log in: -/// -///

-/// -///
-/// -/// [Telegram Login Widget]: https://core.telegram.org/widgets/login -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct LoginUrl { - pub url: String, - pub forward_text: Option, - pub bot_username: Option, - pub request_write_access: Option, -} - -impl LoginUrl { - pub fn new(url: S) -> Self - where - S: Into, - { - Self { url: url.into(), forward_text: None, bot_username: None, request_write_access: None } - } - - pub fn url(mut self, val: S) -> Self - where - S: Into, - { - self.url = val.into(); - self - } - - pub fn forward_text(mut self, val: S) -> Self - where - S: Into, - { - self.forward_text = Some(val.into()); - self - } - - pub fn bot_username(mut self, val: S) -> Self - where - S: Into, - { - self.bot_username = Some(val.into()); - self - } - - pub fn request_write_access(mut self, val: bool) -> Self { - self.request_write_access = Some(val); - self - } -} diff --git a/src/types/mask_position.rs b/src/types/mask_position.rs deleted file mode 100644 index 8bca0273..00000000 --- a/src/types/mask_position.rs +++ /dev/null @@ -1,58 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object describes the position on faces where a mask should be placed by -/// default. -/// -/// [The official docs](https://core.telegram.org/bots/api#maskposition). -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MaskPosition { - /// The part of the face relative to which the mask should be placed. One - /// of `forehead`, `eyes`, `mouth`, or `chin`. - pub point: String, - - /// Shift by X-axis measured in widths of the mask scaled to the face size, - /// from left to right. For example, choosing `-1.0` will place mask just - /// to the left of the default mask position. - pub x_shift: f64, - - /// Shift by Y-axis measured in heights of the mask scaled to the face - /// size, from top to bottom. For example, `1.0` will place the mask just - /// below the default mask position. - pub y_shift: f64, - - /// Mask scaling coefficient. For example, `2.0` means double size. - pub scale: f64, -} - -impl MaskPosition { - pub fn new(point: S, x_shift: f64, y_shift: f64, scale: f64) -> Self - where - S: Into, - { - Self { point: point.into(), x_shift, y_shift, scale } - } - - pub fn point(mut self, val: S) -> Self - where - S: Into, - { - self.point = val.into(); - self - } - - pub fn x_shift(mut self, val: f64) -> Self { - self.x_shift = val; - self - } - - pub fn y_shift(mut self, val: f64) -> Self { - self.y_shift = val; - self - } - - pub fn scale(mut self, val: f64) -> Self { - self.scale = val; - self - } -} diff --git a/src/types/me.rs b/src/types/me.rs deleted file mode 100644 index 0b46a030..00000000 --- a/src/types/me.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::types::User; -use serde::{Deserialize, Serialize}; - -/// Returned only in [`Bot::get_me`]. -/// -/// [`Bot::get_me`]: crate::Bot::get_me -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Me { - #[serde(flatten)] - pub user: User, - - /// `true`, if the bot can be invited to groups. - pub can_join_groups: bool, - - /// `true`, if [privacy mode] is disabled for the bot. - /// - /// [privacy mode]: https://core.telegram.org/bots#privacy-mode - pub can_read_all_group_messages: bool, - - /// `true`, if the bot supports inline queries. - pub supports_inline_queries: bool, -} - -impl Me { - pub fn new( - user: User, - can_join_groups: bool, - can_read_all_group_messages: bool, - supports_inline_queries: bool, - ) -> Self { - Self { user, can_join_groups, can_read_all_group_messages, supports_inline_queries } - } - - pub fn user(mut self, val: User) -> Self { - self.user = val; - self - } - - #[warn(clippy::wrong_self_convention)] - pub fn can_join_groups(mut self, val: bool) -> Self { - self.can_join_groups = val; - self - } - - #[warn(clippy::wrong_self_convention)] - pub fn can_read_all_group_messages(mut self, val: bool) -> Self { - self.can_read_all_group_messages = val; - self - } - - #[warn(clippy::wrong_self_convention)] - pub fn supports_inline_queries(mut self, val: bool) -> Self { - self.supports_inline_queries = val; - self - } -} diff --git a/src/types/message.rs b/src/types/message.rs deleted file mode 100644 index 79aa8366..00000000 --- a/src/types/message.rs +++ /dev/null @@ -1,1753 +0,0 @@ -#![allow(clippy::large_enum_variant)] - -use serde::{Deserialize, Serialize}; - -use crate::types::{ - chat::{ChatKind, PublicChatKind}, - Animation, Audio, Chat, ChatPublic, Contact, Dice, Document, Game, InlineKeyboardMarkup, - Invoice, Location, MessageEntity, PassportData, PhotoSize, Poll, PublicChatChannel, - PublicChatSupergroup, Sticker, SuccessfulPayment, True, User, Venue, Video, VideoNote, Voice, -}; - -/// This object represents a message. -/// -/// [The official docs](https://core.telegram.org/bots/api#message). -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Message { - /// Unique message identifier inside this chat. - #[serde(rename = "message_id")] - pub id: i32, - - /// Date the message was sent in Unix time. - pub date: i32, - - /// Conversation the message belongs to. - pub chat: Chat, - - /// Bot through which the message was sent. - pub via_bot: Option, - - #[serde(flatten)] - pub kind: MessageKind, -} - -impl Message { - pub fn new(id: i32, date: i32, chat: Chat, kind: MessageKind) -> Self { - Self { id, date, chat, kind, via_bot: None } - } - - pub fn id(mut self, val: i32) -> Self { - self.id = val; - self - } - - pub fn date(mut self, val: i32) -> Self { - self.date = val; - self - } - - pub fn chat(mut self, val: Chat) -> Self { - self.chat = val; - self - } - - pub fn kind(mut self, val: MessageKind) -> Self { - self.kind = val; - self - } - - pub fn via_bot(mut self, val: User) -> Self { - self.via_bot = Some(val); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[non_exhaustive] -pub enum MessageKind { - Common(MessageCommon), - NewChatMembers(MessageNewChatMembers), - LeftChatMember(MessageLeftChatMember), - NewChatTitle(MessageNewChatTitle), - NewChatPhoto(MessageNewChatPhoto), - DeleteChatPhoto(MessageDeleteChatPhoto), - GroupChatCreated(MessageGroupChatCreated), - SupergroupChatCreated(MessageSupergroupChatCreated), - ChannelChatCreated(MessageChannelChatCreated), - Migrate(MessageMigrate), - Pinned(MessagePinned), - Invoice(MessageInvoice), - SuccessfulPayment(MessageSuccessfulPayment), - ConnectedWebsite(MessageConnectedWebsite), - PassportData(MessagePassportData), - Dice(MessageDice), -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageCommon { - /// Sender, empty for messages sent to channels. - pub from: Option, - - #[serde(flatten)] - pub forward_kind: ForwardKind, - - /// Date the message was last edited in Unix time. - pub edit_date: Option, - - #[serde(flatten)] - pub media_kind: MediaKind, - - /// Inline keyboard attached to the message. `login_url` buttons are - /// represented as ordinary `url` buttons. - pub reply_markup: Option, -} - -impl MessageCommon { - pub fn new(forward_kind: ForwardKind, media_kind: MediaKind) -> Self { - Self { from: None, forward_kind, edit_date: None, media_kind, reply_markup: None } - } - - pub fn from(mut self, val: User) -> Self { - self.from = Some(val); - self - } - - pub fn forward_kind(mut self, val: ForwardKind) -> Self { - self.forward_kind = val; - self - } - - pub fn edit_date(mut self, val: i32) -> Self { - self.edit_date = Some(val); - self - } - - pub fn media_kind(mut self, val: MediaKind) -> Self { - self.media_kind = val; - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageNewChatMembers { - /// New members that were added to the group or supergroup and - /// information about them (the bot itself may be one of these - /// members). - pub new_chat_members: Vec, -} - -impl MessageNewChatMembers { - pub fn new(new_chat_members: N) -> Self - where - N: Into>, - { - Self { new_chat_members: new_chat_members.into() } - } - - pub fn new_chat_members(mut self, val: N) -> Self - where - N: Into>, - { - self.new_chat_members = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageLeftChatMember { - /// A member was removed from the group, information about them (this - /// member may be the bot itself). - pub left_chat_member: User, -} - -impl MessageLeftChatMember { - pub fn new(left_chat_member: N) -> Self - where - N: Into, - { - Self { left_chat_member: left_chat_member.into() } - } - - pub fn left_chat_member(mut self, val: N) -> Self - where - N: Into, - { - self.left_chat_member = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageNewChatTitle { - /// A chat title was changed to this value. - pub new_chat_title: String, -} - -impl MessageNewChatTitle { - pub fn new(new_chat_title: N) -> Self - where - N: Into, - { - Self { new_chat_title: new_chat_title.into() } - } - - pub fn new_chat_title(mut self, val: N) -> Self - where - N: Into, - { - self.new_chat_title = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageNewChatPhoto { - /// A chat photo was change to this value. - pub new_chat_photo: Vec, -} - -impl MessageNewChatPhoto { - pub fn new(new_chat_photo: N) -> Self - where - N: Into>, - { - Self { new_chat_photo: new_chat_photo.into() } - } - - pub fn new_chat_photo(mut self, val: N) -> Self - where - N: Into>, - { - self.new_chat_photo = val.into(); - self - } -} - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageDeleteChatPhoto { - /// Service message: the chat photo was deleted. - pub delete_chat_photo: True, -} - -impl MessageDeleteChatPhoto { - pub fn new() -> Self { - Self::default() - } -} - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageGroupChatCreated { - /// Service message: the group has been created. - pub group_chat_created: True, -} - -impl MessageGroupChatCreated { - pub fn new() -> Self { - Self::default() - } -} - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageSupergroupChatCreated { - /// Service message: the supergroup has been created. This field can‘t - /// be received in a message coming through updates, because bot can’t - /// be a member of a supergroup when it is created. It can only be - /// found in `reply_to_message` if someone replies to a very first - /// message in a directly created supergroup. - pub supergroup_chat_created: True, -} - -impl MessageSupergroupChatCreated { - pub fn new() -> Self { - Self::default() - } -} - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageChannelChatCreated { - /// Service message: the channel has been created. This field can‘t be - /// received in a message coming through updates, because bot can’t be - /// a member of a channel when it is created. It can only be found in - /// `reply_to_message` if someone replies to a very first message in a - /// channel. - pub channel_chat_created: True, -} - -impl MessageChannelChatCreated { - pub fn new() -> Self { - Self::default() - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageMigrate { - /// The group has been migrated to a supergroup with the specified - /// identifier. This number may be greater than 32 bits and some - /// programming languages may have difficulty/silent defects in - /// interpreting it. But it is smaller than 52 bits, so a signed 64 bit - /// integer or double-precision float type are safe for storing this - /// identifier. - pub migrate_to_chat_id: i64, - - /// The supergroup has been migrated from a group with the specified - /// identifier. This number may be greater than 32 bits and some - /// programming languages may have difficulty/silent defects in - /// interpreting it. But it is smaller than 52 bits, so a signed 64 bit - /// integer or double-precision float type are safe for storing this - /// identifier. - pub migrate_from_chat_id: i64, -} - -impl MessageMigrate { - pub fn new(migrate_to_chat_id: i64, migrate_from_chat_id: i64) -> Self { - Self { migrate_to_chat_id, migrate_from_chat_id } - } - - pub fn migrate_to_chat_id(mut self, val: i64) -> Self { - self.migrate_to_chat_id = val; - self - } - - pub fn migrate_from_chat_id(mut self, val: i64) -> Self { - self.migrate_from_chat_id = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessagePinned { - /// Specified message was pinned. Note that the Message object in this - /// field will not contain further `reply_to_message` fields even if it - /// is itself a reply. - #[serde(rename = "pinned_message")] - pub pinned: Box, -} - -impl MessagePinned { - pub fn new(pinned: Message) -> Self { - Self { pinned: Box::new(pinned) } - } - - pub fn pinned(mut self, val: Message) -> Self { - self.pinned = Box::new(val); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageInvoice { - /// Message is an invoice for a [payment], information about the - /// invoice. [More about payments »]. - /// - /// [payment]: https://core.telegram.org/bots/api#payments - /// [More about payments »]: https://core.telegram.org/bots/api#payments - pub invoice: Invoice, -} - -impl MessageInvoice { - pub fn new(invoice: Invoice) -> Self { - Self { invoice } - } - - pub fn invoice(mut self, val: Invoice) -> Self { - self.invoice = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageSuccessfulPayment { - /// Message is a service message about a successful payment, - /// information about the payment. [More about payments »]. - /// - /// [More about payments »]: https://core.telegram.org/bots/api#payments - pub successful_payment: SuccessfulPayment, -} - -impl MessageSuccessfulPayment { - pub fn new(successful_payment: SuccessfulPayment) -> Self { - Self { successful_payment } - } - - pub fn successful_payment(mut self, val: SuccessfulPayment) -> Self { - self.successful_payment = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageConnectedWebsite { - /// The domain name of the website on which the user has logged in. - /// [More about Telegram Login »]. - /// - /// [More about Telegram Login »]: https://core.telegram.org/widgets/login - pub connected_website: String, -} - -impl MessageConnectedWebsite { - pub fn new(connected_website: S) -> Self - where - S: Into, - { - Self { connected_website: connected_website.into() } - } - - pub fn connected_website(mut self, val: S) -> Self - where - S: Into, - { - self.connected_website = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessagePassportData { - /// Telegram Passport data. - pub passport_data: PassportData, -} - -impl MessagePassportData { - pub fn new(passport_data: PassportData) -> Self { - Self { passport_data } - } - - pub fn passport_data(mut self, val: PassportData) -> Self { - self.passport_data = val; - self - } -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub enum ForwardedFrom { - #[serde(rename = "forward_from")] - User(User), - #[serde(rename = "forward_sender_name")] - SenderName(String), -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[non_exhaustive] -pub enum ForwardKind { - Channel(ForwardChannel), - NonChannel(ForwardNonChannel), - Origin(ForwardOrigin), -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ForwardChannel { - #[serde(rename = "forward_date")] - pub date: i32, - - #[serde(rename = "forward_from_chat")] - pub chat: Chat, - - #[serde(rename = "forward_from_message_id")] - pub message_id: i32, - - #[serde(rename = "forward_signature")] - pub signature: Option, -} - -impl ForwardChannel { - pub fn new(date: i32, chat: Chat, message_id: i32) -> Self { - Self { date, chat, message_id, signature: None } - } - - pub fn date(mut self, val: i32) -> Self { - self.date = val; - self - } - - pub fn chat(mut self, val: Chat) -> Self { - self.chat = val; - self - } - - pub fn message_id(mut self, val: i32) -> Self { - self.message_id = val; - self - } - - pub fn signature(mut self, val: S) -> Self - where - S: Into, - { - self.signature = Some(val.into()); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ForwardNonChannel { - #[serde(rename = "forward_date")] - pub date: i32, - - #[serde(flatten)] - pub from: ForwardedFrom, -} - -impl ForwardNonChannel { - pub fn new(date: i32, from: ForwardedFrom) -> Self { - Self { date, from } - } - - pub fn date(mut self, val: i32) -> Self { - self.date = val; - self - } - - pub fn from(mut self, val: ForwardedFrom) -> Self { - self.from = val; - self - } -} - -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ForwardOrigin { - pub reply_to_message: Option>, -} - -impl ForwardOrigin { - pub fn new() -> Self { - Self::default() - } - - pub fn reply_to_message(mut self, val: Message) -> Self { - self.reply_to_message = Some(Box::new(val)); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -#[non_exhaustive] -pub enum MediaKind { - Animation(MediaAnimation), - Audio(MediaAudio), - Contact(MediaContact), - Document(MediaDocument), - Game(MediaGame), - Location(MediaLocation), - Photo(MediaPhoto), - Poll(MediaPoll), - Sticker(MediaSticker), - Text(MediaText), - Video(MediaVideo), - VideoNote(MediaVideoNote), - Voice(MediaVoice), - Venue(MediaVenue), -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaAnimation { - /// Message is an animation, information about the animation. For - /// backward compatibility, when this field is set, the document field - /// will also be set. - pub animation: Animation, - - #[doc(hidden)] - /// "For backward compatibility" (c) Telegram Docs. - #[serde(skip)] - pub document: (), - - /// Caption for the animation, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, -} - -impl MediaAnimation { - pub fn new(animation: Animation, caption_entities: CE) -> Self - where - CE: Into>, - { - Self { animation, document: (), caption: None, caption_entities: caption_entities.into() } - } - - pub fn animation(mut self, val: Animation) -> Self { - self.animation = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaAudio { - /// Message is an audio file, information about the file. - pub audio: Audio, - - /// Caption for the audio, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, -} - -impl MediaAudio { - pub fn new(audio: Audio, caption_entities: CE) -> Self - where - CE: Into>, - { - Self { audio, caption: None, caption_entities: caption_entities.into() } - } - - pub fn audio(mut self, val: Audio) -> Self { - self.audio = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaContact { - /// Message is a shared contact, information about the contact. - contact: Contact, -} - -impl MediaContact { - pub fn new(contact: Contact) -> Self { - Self { contact } - } - - pub fn contact(mut self, val: Contact) -> Self { - self.contact = val; - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaDocument { - /// Message is a general file, information about the file. - pub document: Document, - - /// Caption for the document, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, -} - -impl MediaDocument { - pub fn new(document: Document, caption_entities: CE) -> Self - where - CE: Into>, - { - Self { document, caption: None, caption_entities: caption_entities.into() } - } - - pub fn document(mut self, val: Document) -> Self { - self.document = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaGame { - /// Message is a game, information about the game. [More - /// about games »]. - /// - /// [More about games »]: https://core.telegram.org/bots/api#games - pub game: Game, -} - -impl MediaGame { - pub fn new(game: Game) -> Self { - Self { game } - } - - pub fn game(mut self, val: Game) -> Self { - self.game = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaLocation { - /// Message is a shared location, information about the location. - pub location: Location, -} - -impl MediaLocation { - pub fn new(location: Location) -> Self { - Self { location } - } - - pub fn location(mut self, val: Location) -> Self { - self.location = val; - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaPhoto { - /// Message is a photo, available sizes of the photo. - pub photo: Vec, - - /// Caption for the photo, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, - - /// The unique identifier of a media message group this message belongs - /// to. - pub media_group_id: Option, -} - -impl MediaPhoto { - pub fn new(photo: P, caption_entities: CE) -> Self - where - P: Into>, - CE: Into>, - { - Self { - photo: photo.into(), - caption: None, - caption_entities: caption_entities.into(), - media_group_id: None, - } - } - - pub fn photo

(mut self, val: P) -> Self - where - P: Into>, - { - self.photo = val.into(); - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } - - pub fn media_group_id(mut self, val: S) -> Self - where - S: Into, - { - self.media_group_id = Some(val.into()); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaPoll { - /// Message is a native poll, information about the poll. - pub poll: Poll, -} - -impl MediaPoll { - pub fn new(poll: Poll) -> Self { - Self { poll } - } - - pub fn poll(mut self, val: Poll) -> Self { - self.poll = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaSticker { - /// Message is a sticker, information about the sticker. - pub sticker: Sticker, -} - -impl MediaSticker { - pub fn new(sticker: Sticker) -> Self { - Self { sticker } - } - - pub fn poll(mut self, val: Sticker) -> Self { - self.sticker = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaText { - /// For text messages, the actual UTF-8 text of the message, 0-4096 - /// characters. - pub text: String, - - /// For text messages, special entities like usernames, URLs, bot - /// commands, etc. that appear in the text. - #[serde(default = "Vec::new")] - pub entities: Vec, -} - -impl MediaText { - pub fn new(text: S, entities: E) -> Self - where - S: Into, - E: Into>, - { - Self { text: text.into(), entities: entities.into() } - } - - pub fn text(mut self, val: S) -> Self - where - S: Into, - { - self.text = val.into(); - self - } - - pub fn entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.entities = val.into(); - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaVideo { - /// Message is a video, information about the video. - pub video: Video, - - /// Caption for the video, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, - - /// The unique identifier of a media message group this message belongs - /// to. - pub media_group_id: Option, -} - -impl MediaVideo { - pub fn new(video: Video, caption_entities: CE) -> Self - where - CE: Into>, - { - Self { - video, - caption: None, - caption_entities: caption_entities.into(), - media_group_id: None, - } - } - - pub fn video(mut self, val: Video) -> Self { - self.video = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } - - pub fn media_group_id(mut self, val: S) -> Self - where - S: Into, - { - self.media_group_id = Some(val.into()); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaVideoNote { - /// Message is a [video note], information about the video message. - /// - /// [video note]: https://telegram.org/blog/video-messages-and-telescope - pub video_note: VideoNote, -} - -impl MediaVideoNote { - pub fn new(video_note: VideoNote) -> Self { - Self { video_note } - } - - pub fn video_note(mut self, val: VideoNote) -> Self { - self.video_note = val; - self - } -} - -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaVoice { - /// Message is a voice message, information about the file. - pub voice: Voice, - - /// Caption for the voice, 0-1024 characters. - pub caption: Option, - - /// For messages with a caption, special entities like usernames, URLs, - /// bot commands, etc. that appear in the caption. - #[serde(default = "Vec::new")] - pub caption_entities: Vec, -} - -impl MediaVoice { - pub fn new(voice: Voice, caption_entities: CE) -> Self - where - CE: Into>, - { - Self { voice, caption: None, caption_entities: caption_entities.into() } - } - - pub fn voice(mut self, val: Voice) -> Self { - self.voice = val; - self - } - - pub fn caption(mut self, val: S) -> Self - where - S: Into, - { - self.caption = Some(val.into()); - self - } - - pub fn caption_entities(mut self, val: CE) -> Self - where - CE: Into>, - { - self.caption_entities = val.into(); - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MediaVenue { - /// Message is a venue, information about the venue. - pub venue: Venue, -} - -impl MediaVenue { - pub fn new(venue: Venue) -> Self { - Self { venue } - } - - pub fn venue(mut self, val: Venue) -> Self { - self.venue = val; - self - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageDice { - /// Message is a dice with random value from 1 to 6. - pub dice: Dice, -} - -mod getters { - use std::ops::Deref; - - use crate::types::{ - self, - message::{ - ForwardKind::NonChannel, - MessageKind::{ - ChannelChatCreated, Common, ConnectedWebsite, DeleteChatPhoto, GroupChatCreated, - Invoice, LeftChatMember, Migrate, NewChatMembers, NewChatPhoto, NewChatTitle, - PassportData, Pinned, SuccessfulPayment, SupergroupChatCreated, - }, - }, - Chat, ForwardChannel, ForwardKind, ForwardNonChannel, ForwardOrigin, ForwardedFrom, - MediaAnimation, MediaAudio, MediaContact, MediaDocument, MediaGame, MediaKind, - MediaLocation, MediaPhoto, MediaPoll, MediaSticker, MediaText, MediaVenue, MediaVideo, - MediaVideoNote, MediaVoice, Message, MessageChannelChatCreated, MessageCommon, - MessageConnectedWebsite, MessageDeleteChatPhoto, MessageEntity, MessageGroupChatCreated, - MessageInvoice, MessageLeftChatMember, MessageMigrate, MessageNewChatMembers, - MessageNewChatPhoto, MessageNewChatTitle, MessagePassportData, MessagePinned, - MessageSuccessfulPayment, MessageSupergroupChatCreated, PhotoSize, True, User, - }; - - /// Getters for [Message] fields from [telegram docs]. - /// - /// [Message]: crate::types::Message - /// [telegram docs]: https://core.telegram.org/bots/api#message - impl Message { - /// NOTE: this is getter for both `from` and `author_signature` - pub fn from(&self) -> Option<&User> { - match &self.kind { - Common(MessageCommon { from, .. }) => from.as_ref(), - _ => None, - } - } - - pub fn chat_id(&self) -> i64 { - self.chat.id - } - - /// NOTE: this is getter for both `forward_from` and - /// `forward_sender_name` - pub fn forward_from(&self) -> Option<&ForwardedFrom> { - match &self.kind { - Common(MessageCommon { - forward_kind: NonChannel(ForwardNonChannel { from, .. }), - .. - }) => Some(from), - _ => None, - } - } - - pub fn forward_from_chat(&self) -> Option<&Chat> { - match &self.kind { - Common(MessageCommon { - forward_kind: ForwardKind::Channel(ForwardChannel { chat, .. }), - .. - }) => Some(chat), - _ => None, - } - } - - pub fn forward_from_message_id(&self) -> Option<&i32> { - match &self.kind { - Common(MessageCommon { - forward_kind: ForwardKind::Channel(ForwardChannel { message_id, .. }), - .. - }) => Some(message_id), - _ => None, - } - } - - pub fn forward_signature(&self) -> Option<&str> { - match &self.kind { - Common(MessageCommon { - forward_kind: ForwardKind::Channel(ForwardChannel { signature, .. }), - .. - }) => signature.as_ref().map(Deref::deref), - _ => None, - } - } - - pub fn forward_date(&self) -> Option<&i32> { - match &self.kind { - Common(MessageCommon { - forward_kind: ForwardKind::Channel(ForwardChannel { date, .. }), - .. - }) - | Common(MessageCommon { - forward_kind: ForwardKind::NonChannel(ForwardNonChannel { date, .. }), - .. - }) => Some(date), - _ => None, - } - } - - pub fn reply_to_message(&self) -> Option<&Message> { - match &self.kind { - Common(MessageCommon { - forward_kind: ForwardKind::Origin(ForwardOrigin { reply_to_message, .. }), - .. - }) => reply_to_message.as_ref().map(Deref::deref), - _ => None, - } - } - - pub fn edit_date(&self) -> Option<&i32> { - match &self.kind { - Common(MessageCommon { edit_date, .. }) => edit_date.as_ref(), - _ => None, - } - } - - pub fn media_group_id(&self) -> Option<&str> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Video(MediaVideo { media_group_id, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Photo(MediaPhoto { media_group_id, .. }), - .. - }) => media_group_id.as_ref().map(Deref::deref), - _ => None, - } - } - - pub fn text(&self) -> Option<&str> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Text(MediaText { text, .. }), - .. - }) => Some(text), - _ => None, - } - } - - pub fn text_owned(&self) -> Option { - self.text().map(ToOwned::to_owned) - } - - pub fn entities(&self) -> Option<&[MessageEntity]> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Text(MediaText { entities, .. }), - .. - }) => Some(entities), - _ => None, - } - } - - pub fn caption_entities(&self) -> Option<&[MessageEntity]> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Animation(MediaAnimation { caption_entities, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Audio(MediaAudio { caption_entities, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Document(MediaDocument { caption_entities, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Photo(MediaPhoto { caption_entities, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Video(MediaVideo { caption_entities, .. }), - .. - }) - | Common(MessageCommon { - media_kind: MediaKind::Voice(MediaVoice { caption_entities, .. }), - .. - }) => Some(caption_entities), - _ => None, - } - } - - pub fn audio(&self) -> Option<&types::Audio> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Audio(MediaAudio { audio, .. }), - .. - }) => Some(audio), - _ => None, - } - } - - pub fn document(&self) -> Option<&types::Document> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Document(MediaDocument { document, .. }), - .. - }) => Some(document), - _ => None, - } - } - - pub fn animation(&self) -> Option<&types::Animation> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Animation(MediaAnimation { animation, .. }), - .. - }) => Some(animation), - _ => None, - } - } - - pub fn game(&self) -> Option<&types::Game> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Game(MediaGame { game, .. }), - .. - }) => Some(game), - _ => None, - } - } - - pub fn photo(&self) -> Option<&[PhotoSize]> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Photo(MediaPhoto { photo, .. }), - .. - }) => Some(photo), - _ => None, - } - } - - pub fn sticker(&self) -> Option<&types::Sticker> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Sticker(MediaSticker { sticker, .. }), - .. - }) => Some(sticker), - _ => None, - } - } - - pub fn video(&self) -> Option<&types::Video> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Video(MediaVideo { video, .. }), - .. - }) => Some(video), - _ => None, - } - } - - pub fn voice(&self) -> Option<&types::Voice> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Voice(MediaVoice { voice, .. }), - .. - }) => Some(voice), - _ => None, - } - } - - pub fn video_note(&self) -> Option<&types::VideoNote> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::VideoNote(MediaVideoNote { video_note, .. }), - .. - }) => Some(video_note), - _ => None, - } - } - - pub fn caption(&self) -> Option<&str> { - match &self.kind { - Common(MessageCommon { media_kind, .. }) => match media_kind { - MediaKind::Animation(MediaAnimation { caption, .. }) - | MediaKind::Audio(MediaAudio { caption, .. }) - | MediaKind::Document(MediaDocument { caption, .. }) - | MediaKind::Photo(MediaPhoto { caption, .. }) - | MediaKind::Video(MediaVideo { caption, .. }) - | MediaKind::Voice(MediaVoice { caption, .. }) => { - caption.as_ref().map(Deref::deref) - } - _ => None, - }, - _ => None, - } - } - - pub fn contact(&self) -> Option<&types::Contact> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Contact(MediaContact { contact, .. }), - .. - }) => Some(contact), - _ => None, - } - } - - pub fn location(&self) -> Option<&types::Location> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Location(MediaLocation { location, .. }), - .. - }) => Some(location), - _ => None, - } - } - - pub fn venue(&self) -> Option<&types::Venue> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Venue(MediaVenue { venue, .. }), - .. - }) => Some(venue), - _ => None, - } - } - - pub fn poll(&self) -> Option<&types::Poll> { - match &self.kind { - Common(MessageCommon { - media_kind: MediaKind::Poll(MediaPoll { poll, .. }), - .. - }) => Some(poll), - _ => None, - } - } - - pub fn new_chat_members(&self) -> Option<&[User]> { - match &self.kind { - NewChatMembers(MessageNewChatMembers { new_chat_members }) => { - Some(new_chat_members.as_ref()) - } - _ => None, - } - } - - pub fn left_chat_member(&self) -> Option<&User> { - match &self.kind { - LeftChatMember(MessageLeftChatMember { left_chat_member }) => { - Some(left_chat_member) - } - _ => None, - } - } - - pub fn new_chat_title(&self) -> Option<&str> { - match &self.kind { - NewChatTitle(MessageNewChatTitle { new_chat_title }) => Some(new_chat_title), - _ => None, - } - } - - pub fn new_chat_photo(&self) -> Option<&[PhotoSize]> { - match &self.kind { - NewChatPhoto(MessageNewChatPhoto { new_chat_photo }) => Some(new_chat_photo), - _ => None, - } - } - - // TODO: OK, `Option` is weird, can we do something with it? - // mb smt like `is_delete_chat_photo(&self) -> bool`? - pub fn delete_chat_photo(&self) -> Option { - match &self.kind { - DeleteChatPhoto(MessageDeleteChatPhoto { delete_chat_photo }) => { - Some(*delete_chat_photo) - } - _ => None, - } - } - - pub fn group_chat_created(&self) -> Option { - match &self.kind { - GroupChatCreated(MessageGroupChatCreated { group_chat_created }) => { - Some(*group_chat_created) - } - _ => None, - } - } - - pub fn super_group_chat_created(&self) -> Option { - match &self.kind { - SupergroupChatCreated(MessageSupergroupChatCreated { supergroup_chat_created }) => { - Some(*supergroup_chat_created) - } - _ => None, - } - } - - pub fn channel_chat_created(&self) -> Option { - match &self.kind { - ChannelChatCreated(MessageChannelChatCreated { channel_chat_created }) => { - Some(*channel_chat_created) - } - _ => None, - } - } - - pub fn migrate_to_chat_id(&self) -> Option { - match &self.kind { - Migrate(MessageMigrate { migrate_to_chat_id, .. }) => Some(*migrate_to_chat_id), - _ => None, - } - } - - pub fn migrate_from_chat_id(&self) -> Option { - match &self.kind { - Migrate(MessageMigrate { migrate_from_chat_id, .. }) => Some(*migrate_from_chat_id), - _ => None, - } - } - - pub fn pinned_message(&self) -> Option<&Message> { - match &self.kind { - Pinned(MessagePinned { pinned }) => Some(pinned), - _ => None, - } - } - - pub fn invoice(&self) -> Option<&types::Invoice> { - match &self.kind { - Invoice(MessageInvoice { invoice }) => Some(invoice), - _ => None, - } - } - - pub fn successful_payment(&self) -> Option<&types::SuccessfulPayment> { - match &self.kind { - SuccessfulPayment(MessageSuccessfulPayment { successful_payment }) => { - Some(successful_payment) - } - _ => None, - } - } - - pub fn connected_website(&self) -> Option<&str> { - match &self.kind { - ConnectedWebsite(MessageConnectedWebsite { connected_website }) => { - Some(connected_website) - } - _ => None, - } - } - - pub fn passport_data(&self) -> Option<&types::PassportData> { - match &self.kind { - PassportData(MessagePassportData { passport_data }) => Some(passport_data), - _ => None, - } - } - - pub fn reply_markup(&self) -> Option<&types::InlineKeyboardMarkup> { - match &self.kind { - Common(MessageCommon { reply_markup, .. }) => reply_markup.as_ref(), - _ => None, - } - } - } -} - -impl Message { - pub fn url(&self) -> Option { - match &self.chat.kind { - ChatKind::Public(ChatPublic { - kind: PublicChatKind::Channel(PublicChatChannel { username: Some(username) }), - .. - }) - | ChatKind::Public(ChatPublic { - kind: - PublicChatKind::Supergroup(PublicChatSupergroup { - username: Some(username), .. - }), - .. - }) => Some( - reqwest::Url::parse(format!("https://t.me/{0}/{1}/", username, self.id).as_str()) - .unwrap(), - ), - _ => None, - } - } -} - -#[cfg(test)] -mod tests { - use serde_json::from_str; - - use crate::types::*; - - #[test] - fn de_media_forwarded() { - let json = r#"{ - "message_id": 198283, - "from": { - "id": 250918540, - "is_bot": false, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "language_code": "en" - }, - "chat": { - "id": 250918540, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "type": "private" - }, - "date": 1567927221, - "video": { - "duration": 13, - "width": 512, - "height": 640, - "mime_type": "video/mp4", - "thumb": { - "file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE", - "file_unique_id":"", - "file_size": 10339, - "width": 256, - "height": 320 - }, - "file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE", - "file_unique_id":"", - "file_size": 1381334 - } - }"#; - let message = from_str::(json); - assert!(message.is_ok()); - } - - #[test] - fn de_media_group_forwarded() { - let json = r#"{ - "message_id": 198283, - "from": { - "id": 250918540, - "is_bot": false, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "language_code": "en" - }, - "chat": { - "id": 250918540, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "type": "private" - }, - "date": 1567927221, - "media_group_id": "12543417770506682", - "video": { - "duration": 13, - "width": 512, - "height": 640, - "mime_type": "video/mp4", - "thumb": { - "file_id": "AAQCAAOmBAACBf2oS53pByA-I4CWWCObDwAEAQAHbQADMWcAAhYE", - "file_unique_id":"", - "file_size": 10339, - "width": 256, - "height": 320 - }, - "file_id": "BAADAgADpgQAAgX9qEud6QcgPiOAlhYE", - "file_unique_id":"", - "file_size": 1381334 - } - }"#; - let message = from_str::(json); - assert!(message.is_ok()); - } - - #[test] - fn de_text() { - let json = r#"{ - "message_id": 199785, - "from": { - "id": 250918540, - "is_bot": false, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "language_code": "en" - }, - "chat": { - "id": 250918540, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "type": "private" - }, - "date": 1568289890, - "text": "Лол кек 😂" - }"#; - let message = from_str::(json); - assert!(message.is_ok()); - } - - #[test] - fn de_sticker() { - let json = r#"{ - "message_id": 199787, - "from": { - "id": 250918540, - "is_bot": false, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "language_code": "en" - }, - "chat": { - "id": 250918540, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "type": "private" - }, - "date": 1568290188, - "sticker": { - "width": 512, - "height": 512, - "emoji": "😡", - "set_name": "AdvenTimeAnim", - "is_animated": true, - "thumb": { - "file_id": "AAQCAAMjAAOw0PgMaabKAcaXKCBLubkPAAQBAAdtAAPGKwACFgQ", - "file_unique_id":"", - "file_size": 4118, - "width": 128, - "height": 128 - }, - "file_id": "CAADAgADIwADsND4DGmmygHGlyggFgQ", - "file_unique_id":"", - "file_size": 16639 - } - }"#; - let message = from_str::(json); - assert!(message.is_ok()); - } - - #[test] - fn de_image() { - let json = r#"{ - "message_id": 199791, - "from": { - "id": 250918540, - "is_bot": false, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "language_code": "en" - }, - "chat": { - "id": 250918540, - "first_name": "Андрей", - "last_name": "Власов", - "username": "aka_dude", - "type": "private" - }, - "date": 1568290622, - "photo": [ - { - "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA20AAybcBAABFgQ", - "file_unique_id":"", - "file_size": 18188, - "width": 320, - "height": 239 - }, - { - "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3gAAyfcBAABFgQ", - "file_unique_id":"", - "file_size": 62123, - "width": 800, - "height": 598 - }, - { - "file_id": "AgADAgAD36sxG-PX0UvQSXIn9rccdw-ACA4ABAEAAwIAA3kAAyTcBAABFgQ", - "file_unique_id":"", - "file_size": 75245, - "width": 962, - "height": 719 - } - ] - }"#; - let message = from_str::(json); - assert!(message.is_ok()); - } -} diff --git a/src/types/message_entity.rs b/src/types/message_entity.rs deleted file mode 100644 index c39459be..00000000 --- a/src/types/message_entity.rs +++ /dev/null @@ -1,162 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{Message, User}; - -/// This object represents one special entity in a text message. -/// -/// For example, hashtags, usernames, URLs, etc. -/// -/// [The official docs](https://core.telegram.org/bots/api#messageentity). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct MessageEntity { - #[serde(flatten)] - pub kind: MessageEntityKind, - - /// Offset in UTF-16 code units to the start of the entity. - pub offset: usize, - - /// Length of the entity in UTF-16 code units. - pub length: usize, -} - -impl MessageEntity { - pub fn new(kind: MessageEntityKind, offset: usize, length: usize) -> Self { - Self { kind, offset, length } - } - - pub fn kind(mut self, val: MessageEntityKind) -> Self { - self.kind = val; - self - } - - pub fn offset(mut self, val: usize) -> Self { - self.offset = val; - self - } - - pub fn length(mut self, val: usize) -> Self { - self.length = val; - self - } -} - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[serde(tag = "type")] -#[non_exhaustive] -pub enum MessageEntityKind { - Mention, - Hashtag, - Cashtag, - BotCommand, - Url, - Email, - PhoneNumber, - Bold, - Italic, - Code, - Pre { language: Option }, - TextLink { url: String }, - TextMention { user: User }, - Underline, - Strikethrough, -} - -impl MessageEntity { - pub fn text_from(&self, message: &Message) -> Option { - let text = message.text(); - Some(String::from(&text?[self.offset..self.offset + self.length])) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::types::{ - Chat, ChatKind, ChatPrivate, ForwardKind, ForwardOrigin, MediaKind, MediaText, - MessageCommon, MessageKind, - }; - - #[test] - fn recursive_kind() { - use serde_json::from_str; - - assert_eq!( - MessageEntity { - kind: MessageEntityKind::TextLink { url: "ya.ru".into() }, - offset: 1, - length: 2, - }, - from_str::( - r#"{"type":"text_link","url":"ya.ru","offset":1,"length":2}"# - ) - .unwrap() - ); - } - - #[test] - fn pre() { - use serde_json::from_str; - - assert_eq!( - MessageEntity { - kind: MessageEntityKind::Pre { language: Some("rust".to_string()) }, - offset: 1, - length: 2, - }, - from_str::( - r#"{"type":"pre","url":"ya.ru","offset":1,"length":2,"language":"rust"}"# - ) - .unwrap() - ); - } - - #[test] - fn text_from() { - let message = message(); - let expected = Some("yes".to_string()); - let entity = message.entities().unwrap()[0].clone(); - let actual = entity.text_from(&message); - assert_eq!(actual, expected); - } - - fn message() -> Message { - Message { - via_bot: None, - id: 0, - date: 0, - chat: Chat { - id: 0, - kind: ChatKind::Private(ChatPrivate { - type_: (), - username: None, - first_name: None, - last_name: None, - }), - photo: None, - }, - kind: MessageKind::Common(MessageCommon { - from: Some(User { - id: 0, - is_bot: false, - first_name: "".to_string(), - last_name: None, - username: None, - language_code: None, - }), - forward_kind: ForwardKind::Origin(ForwardOrigin { reply_to_message: None }), - edit_date: None, - media_kind: MediaKind::Text(MediaText { - text: "no yes no".to_string(), - entities: vec![MessageEntity { - kind: MessageEntityKind::Mention, - offset: 3, - length: 3, - }], - }), - reply_markup: None, - }), - } - } -} diff --git a/src/types/mod.rs b/src/types/mod.rs deleted file mode 100644 index e6f7e5fa..00000000 --- a/src/types/mod.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! API types. - -pub use allowed_update::*; -pub use animation::*; -pub use audio::*; -pub use bot_command::*; -pub use callback_game::*; -pub use callback_query::*; -pub use chat::*; -pub use chat_action::*; -pub use chat_id::*; -pub use chat_member::*; -pub use chat_permissions::*; -pub use chat_photo::*; -pub use chosen_inline_result::*; -pub use contact::*; -pub use dice::*; -pub use dice_emoji::*; -pub use document::*; -pub use encrypted_credentials::*; -pub use encrypted_passport_element::*; -pub use file::*; -pub use force_reply::*; -pub use game::*; -pub use game_high_score::*; -pub use inline_keyboard_button::*; -pub use inline_keyboard_markup::*; -pub use inline_query::*; -pub use inline_query_result::*; -pub use inline_query_result_article::*; -pub use inline_query_result_audio::*; -pub use inline_query_result_cached_audio::*; -pub use inline_query_result_cached_document::*; -pub use inline_query_result_cached_gif::*; -pub use inline_query_result_cached_mpeg4_gif::*; -pub use inline_query_result_cached_photo::*; -pub use inline_query_result_cached_sticker::*; -pub use inline_query_result_cached_video::*; -pub use inline_query_result_cached_voice::*; -pub use inline_query_result_contact::*; -pub use inline_query_result_document::*; -pub use inline_query_result_game::*; -pub use inline_query_result_gif::*; -pub use inline_query_result_location::*; -pub use inline_query_result_mpeg4_gif::*; -pub use inline_query_result_photo::*; -pub use inline_query_result_venue::*; -pub use inline_query_result_video::*; -pub use inline_query_result_voice::*; -pub use input_file::*; -pub use input_media::*; -pub use input_message_content::*; -pub use invoice::*; -pub use keyboard_button::*; -pub use keyboard_button_poll_type::*; -pub use label_price::*; -pub use location::*; -pub use login_url::*; -pub use mask_position::*; -pub use me::*; -pub use message::*; -pub use message_entity::*; -pub use order_info::*; -pub use parse_mode::*; -pub use passport_data::*; -pub use passport_element_error::*; -pub use passport_file::*; -pub use photo_size::*; -pub use poll::*; -pub use poll_answer::*; -pub use poll_type::*; -pub use pre_checkout_query::*; -pub use reply_keyboard_markup::*; -pub use reply_keyboard_remove::*; -pub use reply_markup::*; -pub use response_parameters::*; -pub use send_invoice::*; -pub use shipping_address::*; -pub use shipping_option::*; -pub use shipping_query::*; -pub use sticker::*; -pub use sticker_set::*; -pub use sticker_type::*; -pub use successful_payment::*; -pub use target_message::*; -pub use unit_false::*; -pub use unit_true::*; -pub use update::*; -pub use user::*; -pub use user_profile_photos::*; -pub use venue::*; -pub use video::*; -pub use video_note::*; -pub use voice::*; -pub use webhook_info::*; - -mod allowed_update; -mod animation; -mod audio; -mod bot_command; -mod callback_game; -mod callback_query; -mod chat; -mod chat_action; -mod chat_id; -mod chat_member; -mod chat_permissions; -mod chat_photo; -mod chosen_inline_result; -mod contact; -mod dice; -mod dice_emoji; -mod document; -mod file; -mod force_reply; -mod game; -mod game_high_score; -mod inline_keyboard_button; -mod inline_keyboard_markup; -mod input_file; -mod input_media; -mod input_message_content; -mod invoice; -mod keyboard_button; -mod keyboard_button_poll_type; -mod label_price; -mod location; -mod login_url; -mod mask_position; -mod me; -mod message; -mod message_entity; -mod order_info; -mod parse_mode; -mod photo_size; -mod poll; -mod poll_answer; -mod poll_type; -mod pre_checkout_query; -mod reply_keyboard_markup; -mod reply_keyboard_remove; -mod reply_markup; -mod response_parameters; -mod send_invoice; -mod shipping_address; -mod shipping_option; -mod shipping_query; -mod sticker; -mod sticker_set; -mod sticker_type; -mod successful_payment; -mod target_message; -mod unit_false; -mod unit_true; -mod update; -mod user; -mod user_profile_photos; -mod venue; -mod video; -mod video_note; -mod voice; -mod webhook_info; - -mod inline_query; -mod inline_query_result; -mod inline_query_result_article; -mod inline_query_result_audio; -mod inline_query_result_cached_audio; -mod inline_query_result_cached_document; -mod inline_query_result_cached_gif; -mod inline_query_result_cached_mpeg4_gif; -mod inline_query_result_cached_photo; -mod inline_query_result_cached_sticker; -mod inline_query_result_cached_video; -mod inline_query_result_cached_voice; -mod inline_query_result_contact; -mod inline_query_result_document; -mod inline_query_result_game; -mod inline_query_result_gif; -mod inline_query_result_location; -mod inline_query_result_mpeg4_gif; -mod inline_query_result_photo; -mod inline_query_result_venue; -mod inline_query_result_video; -mod inline_query_result_voice; - -mod encrypted_credentials; -mod encrypted_passport_element; -mod passport_data; -mod passport_element_error; -mod passport_file; - -pub use non_telegram_types::*; -mod non_telegram_types; diff --git a/src/types/non_telegram_types/country_code.rs b/src/types/non_telegram_types/country_code.rs deleted file mode 100644 index 4f7705ac..00000000 --- a/src/types/non_telegram_types/country_code.rs +++ /dev/null @@ -1,254 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub enum CountryCode { - AD, - AE, - AF, - AG, - AI, - AL, - AM, - AO, - AQ, - AR, - AS, - AT, - AU, - AW, - AX, - AZ, - BA, - BB, - BD, - BE, - BF, - BG, - BH, - BI, - BJ, - BL, - BM, - BN, - BO, - BQ, - BR, - BS, - BT, - BV, - BW, - BY, - BZ, - CA, - CC, - CD, - CF, - CG, - CH, - CI, - CK, - CL, - CM, - CN, - CO, - CR, - CU, - CV, - CW, - CX, - CY, - CZ, - DE, - DJ, - DK, - DM, - DO, - DZ, - EC, - EE, - EG, - EH, - ER, - ES, - ET, - FI, - FJ, - FK, - FM, - FO, - FR, - GA, - GB, - GD, - GE, - GF, - GG, - GH, - GI, - GL, - GM, - GN, - GP, - GQ, - GR, - GS, - GT, - GU, - GW, - GY, - HK, - HM, - HN, - HR, - HT, - HU, - ID, - IE, - IL, - IM, - IN, - IO, - IQ, - IR, - IS, - IT, - JE, - JM, - JO, - JP, - KE, - KG, - KH, - KI, - KM, - KN, - KP, - KR, - KW, - KY, - KZ, - LA, - LB, - LC, - LI, - LK, - LR, - LS, - LT, - LU, - LV, - LY, - MA, - MC, - MD, - ME, - MF, - MG, - MH, - MK, - ML, - MM, - MN, - MO, - MP, - MQ, - MR, - MS, - MT, - MU, - MV, - MW, - MX, - MY, - MZ, - NA, - NC, - NE, - NF, - NG, - NI, - NL, - NO, - NP, - NR, - NU, - NZ, - OM, - PA, - PE, - PF, - PG, - PH, - PK, - PL, - PM, - PN, - PR, - PS, - PT, - PW, - PY, - QA, - RE, - RO, - RS, - RU, - RW, - SA, - SB, - SC, - SD, - SE, - SG, - SH, - SI, - SJ, - SK, - SL, - SM, - SN, - SO, - SR, - SS, - ST, - SV, - SX, - SY, - SZ, - TC, - TD, - TF, - TG, - TH, - TJ, - TK, - TL, - TM, - TN, - TO, - TR, - TT, - TV, - TW, - TZ, - UA, - UG, - UM, - US, - UY, - UZ, - VA, - VC, - VE, - VG, - VI, - VN, - VU, - WF, - WS, - YE, - YT, - ZA, - ZM, - ZW, -} diff --git a/src/types/non_telegram_types/currency.rs b/src/types/non_telegram_types/currency.rs deleted file mode 100644 index 0cdebce6..00000000 --- a/src/types/non_telegram_types/currency.rs +++ /dev/null @@ -1,89 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub enum Currency { - AED, - AFN, - ALL, - AMD, - ARS, - AUD, - AZN, - BAM, - BDT, - BGN, - BND, - BOB, - BRL, - CAD, - CHF, - CLP, - CNY, - COP, - CRC, - CZK, - DKK, - DOP, - DZD, - EGP, - EUR, - GBP, - GEL, - GTQ, - HKD, - HNL, - HRK, - HUF, - IDR, - ILS, - INR, - ISK, - JMD, - JPY, - KES, - KGS, - KRW, - KZT, - LBP, - LKR, - MAD, - MDL, - MNT, - MUR, - MVR, - MXN, - MYR, - MZN, - NGN, - NIO, - NOK, - NPR, - NZD, - PAB, - PEN, - PHP, - PKR, - PLN, - PYG, - QAR, - RON, - RSD, - RUB, - SAR, - SEK, - SGD, - THB, - TJS, - TRY, - TTD, - TWD, - TZS, - UAH, - UGX, - USD, - UYU, - UZS, - VND, - YER, - ZAR, -} diff --git a/src/types/non_telegram_types/mime_wrapper.rs b/src/types/non_telegram_types/mime_wrapper.rs deleted file mode 100644 index 848b3376..00000000 --- a/src/types/non_telegram_types/mime_wrapper.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::fmt::Formatter; - -use derive_more::From; -use mime::Mime; -use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; - -/// Serializable & deserializable `MIME` wrapper. -#[derive(Clone, Debug, Eq, Hash, PartialEq, From)] -pub struct MimeWrapper(pub Mime); - -impl Serialize for MimeWrapper { - fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> - where - S: Serializer, - { - serializer.serialize_str(self.0.as_ref()) - } -} - -struct MimeVisitor; -impl<'a> Visitor<'a> for MimeVisitor { - type Value = MimeWrapper; - - fn expecting(&self, formatter: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { - formatter.write_str("mime type") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - match v.parse::() { - Ok(mime_type) => Ok(MimeWrapper(mime_type)), - Err(e) => Err(E::custom(e)), - } - } -} - -impl<'de> Deserialize<'de> for MimeWrapper { - fn deserialize(deserializer: D) -> Result>::Error> - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(MimeVisitor) - } -} diff --git a/src/types/non_telegram_types/mod.rs b/src/types/non_telegram_types/mod.rs deleted file mode 100644 index 8add54b6..00000000 --- a/src/types/non_telegram_types/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub use country_code::*; -pub use currency::*; -pub use mime_wrapper::*; - -mod country_code; -mod currency; -mod mime_wrapper; diff --git a/src/types/order_info.rs b/src/types/order_info.rs deleted file mode 100644 index 7f41f7a9..00000000 --- a/src/types/order_info.rs +++ /dev/null @@ -1,72 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::ShippingAddress; - -/// This object represents information about an order. -/// -/// [The official docs](https://core.telegram.org/bots/api#orderinfo). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct OrderInfo { - /// User's name. - pub name: String, - - /// User's phone number. - pub phone_number: String, - - /// User's email. - pub email: String, - - /// User's shipping address. - pub shipping_address: ShippingAddress, -} - -impl OrderInfo { - pub fn new( - name: S1, - phone_number: S2, - email: S3, - shipping_address: ShippingAddress, - ) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - name: name.into(), - phone_number: phone_number.into(), - email: email.into(), - shipping_address, - } - } - - pub fn name(mut self, val: S) -> Self - where - S: Into, - { - self.name = val.into(); - self - } - - pub fn phone_number(mut self, val: S) -> Self - where - S: Into, - { - self.phone_number = val.into(); - self - } - - pub fn email(mut self, val: S) -> Self - where - S: Into, - { - self.email = val.into(); - self - } - - pub fn shipping_address(mut self, val: ShippingAddress) -> Self { - self.shipping_address = val; - self - } -} diff --git a/src/types/parse_mode.rs b/src/types/parse_mode.rs deleted file mode 100644 index 44a0ecff..00000000 --- a/src/types/parse_mode.rs +++ /dev/null @@ -1,189 +0,0 @@ -// see https://github.com/rust-lang/rust/issues/38832 -// (for built ins there no warnings, but for (De)Serialize, there are) -#![allow(deprecated)] - -use std::{ - convert::{TryFrom, TryInto}, - str::FromStr, -}; - -use serde::{Deserialize, Serialize}; - -/// Formatting options. -/// -/// The Bot API supports basic formatting for messages. You can use bold, -/// italic, underlined and strikethrough text, as well as inline links and -/// pre-formatted code in your bots' messages. Telegram clients will render -/// them accordingly. You can use either markdown-style or HTML-style -/// formatting. -/// -/// Note that Telegram clients will display an **alert** to the user before -/// opening an inline link (‘Open this link?’ together with the full URL). -/// -/// Links `tg://user?id=` can be used to mention a user by their ID -/// without using a username. Please note: -/// -/// - These links will work **only** if they are used inside an inline link. For -/// example, they will not work, when used in an inline keyboard button or in -/// a message text. -/// - These mentions are only guaranteed to work if the user has contacted the -/// bot in the past, has sent a callback query to the bot via inline button or -/// is a member in the group where he was mentioned. -/// -/// ## MarkdownV2 style -/// -/// To use this mode, pass [`MarkdownV2`] in the `parse_mode` field. -/// Use the following syntax in your message: -/// ````text -/// *bold \*text* -/// _italic \*text_ -/// __underline__ -/// ~strikethrough~ -/// *bold _italic bold ~italic bold strikethrough~ __underline italic bold___ bold* -/// [inline URL](http://www.example.com/) -/// [inline mention of a user](tg://user?id=123456789) -/// `inline fixed-width code` -/// ``` -/// pre-formatted fixed-width code block -/// ``` -/// ```rust -/// pre-formatted fixed-width code block written in the Rust programming -/// language ``` -/// ```` -/// -/// Please note: -/// - Any character between 1 and 126 inclusively can be escaped anywhere with a -/// preceding '\' character, in which case it is treated as an ordinary -/// character and not a part of the markup. -/// - Inside `pre` and `code` entities, all '`‘ and ’\‘ characters must be -/// escaped with a preceding ’\' character. -/// - Inside `(...)` part of inline link definition, all ')‘ and ’\‘ must be -/// escaped with a preceding ’\' character. -/// - In all other places characters ’_‘, ’*‘, ’[‘, ’]‘, ’(‘, ’)‘, ’~‘, ’`‘, -/// ’>‘, ’#‘, ’+‘, ’+‘, ’-‘, ’|‘, ’{‘, ’}‘, ’.‘, ’!‘ must be escaped with the -/// preceding character ’\'. -/// - In case of ambiguity between `italic` and `underline` entities ‘__’ is -/// always greadily treated from left to right as beginning or end of -/// `underline` entity, so instead of `___italic underline___` use `___italic -/// underline_\r__`, where `\r` is a character with code `13`, which will be -/// ignored. -/// -/// ## HTML style -/// To use this mode, pass [`HTML`] in the `parse_mode` field. -/// The following tags are currently supported: -/// ````text -/// bold, bold -/// italic, italic -/// underline, underline -/// strikethrough, strikethrough, -/// strikethrough bold italic bold italic bold -/// strikethrough underline italic bold bold inline URL -/// inline mention of a user -/// inline fixed-width code -///

pre-formatted fixed-width code block
-///
pre-formatted fixed-width code block
-/// written in the Rust programming language
```` -/// -/// Please note: -/// -/// - Only the tags mentioned above are currently supported. -/// - All `<`, `>` and `&` symbols that are not a part of a tag or an HTML -/// entity must be replaced with the corresponding HTML entities (`<` with -/// `<`, `>` with `>` and `&` with `&`). -/// - All numerical HTML entities are supported. -/// - The API currently supports only the following named HTML entities: `<`, -/// `>`, `&` and `"`. -/// - Use nested `pre` and `code` tags, to define programming language for `pre` -/// entity. -/// - Programming language can't be specified for standalone `code` tags. -/// -/// ## Markdown style -/// This is a legacy mode, retained for backward compatibility. To use this -/// mode, pass [`Markdown`] in the `parse_mode` field. -/// Use the following syntax in your message: -/// ````text -/// *bold text* -/// _italic text_ -/// [inline URL](http://www.example.com/) -/// [inline mention of a user](tg://user?id=123456789) -/// `inline fixed-width code` -/// ```rust -/// pre-formatted fixed-width code block written in the Rust programming -/// language ``` -/// ```` -/// -/// Please note: -/// - Entities must not be nested, use parse mode [`MarkdownV2`] instead. -/// - There is no way to specify underline and strikethrough entities, use parse -/// mode [`MarkdownV2`] instead. -/// - To escape characters ’_‘, ’*‘, ’`‘, ’[‘ outside of an entity, prepend the -/// characters ’\' before them. -/// - Escaping inside entities is not allowed, so entity must be closed first -/// and reopened again: use `_snake_\__case_` for italic `snake_case` and -/// `*2*\**2=4*` for bold `2*2=4`. -/// -/// [`MarkdownV2`]: ParseMode::MarkdownV2 -/// [`HTML`]: ParseMode::HTML -/// [`Markdown`]: ParseMode::Markdown -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub enum ParseMode { - MarkdownV2, - HTML, - #[deprecated = "This is a legacy mode, retained for backward compatibility. Use `MarkdownV2` \ - instead."] - Markdown, -} - -impl TryFrom<&str> for ParseMode { - type Error = (); - - fn try_from(value: &str) -> Result { - let normalized = value.to_lowercase(); - match normalized.as_ref() { - "html" => Ok(ParseMode::HTML), - "markdown" => Ok(ParseMode::Markdown), - "markdownv2" => Ok(ParseMode::MarkdownV2), - _ => Err(()), - } - } -} - -impl TryFrom for ParseMode { - type Error = (); - - fn try_from(value: String) -> Result { - value.as_str().try_into() - } -} - -impl FromStr for ParseMode { - type Err = (); - - fn from_str(s: &str) -> Result { - s.try_into() - } -} - -#[cfg(test)] -mod tests { - #![allow(deprecated)] - - use super::*; - - #[test] - fn html_serialization() { - let expected_json = String::from(r#""HTML""#); - let actual_json = serde_json::to_string(&ParseMode::HTML).unwrap(); - - assert_eq!(expected_json, actual_json) - } - - #[test] - fn markdown_serialization() { - let expected_json = String::from(r#""Markdown""#); - let actual_json = serde_json::to_string(&ParseMode::Markdown).unwrap(); - - assert_eq!(expected_json, actual_json) - } -} diff --git a/src/types/passport_data.rs b/src/types/passport_data.rs deleted file mode 100644 index 3abaef93..00000000 --- a/src/types/passport_data.rs +++ /dev/null @@ -1,40 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::{EncryptedCredentials, EncryptedPassportElement}; - -/// Contains information about Telegram Passport data shared with the bot by the -/// user. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportdata). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportData { - /// Array with information about documents and other Telegram Passport - /// elements that was shared with the bot. - pub data: Vec, - - /// Encrypted credentials required to decrypt the data. - pub credentials: EncryptedCredentials, -} - -impl PassportData { - pub fn new(data: E, credentials: EncryptedCredentials) -> Self - where - E: Into>, - { - Self { data: data.into(), credentials } - } - - pub fn data(mut self, val: E) -> Self - where - E: Into>, - { - self.data = val.into(); - self - } - - pub fn credentials(mut self, val: EncryptedCredentials) -> Self { - self.credentials = val; - self - } -} diff --git a/src/types/passport_element_error.rs b/src/types/passport_element_error.rs deleted file mode 100644 index 521584e5..00000000 --- a/src/types/passport_element_error.rs +++ /dev/null @@ -1,558 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents an error in the Telegram Passport element which was -/// submitted that should be resolved by the user. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerror). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementError { - /// Error message. - message: String, - - #[serde(flatten)] - kind: PassportElementErrorKind, -} - -impl PassportElementError { - pub fn new(message: S, kind: PassportElementErrorKind) -> Self - where - S: Into, - { - Self { message: message.into(), kind } - } - - pub fn message(mut self, val: S) -> Self - where - S: Into, - { - self.message = val.into(); - self - } - - pub fn kind(mut self, val: PassportElementErrorKind) -> Self { - self.kind = val; - self - } -} - -#[serde(tag = "source")] -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub enum PassportElementErrorKind { - #[serde(rename = "data")] - DataField(PassportElementErrorDataField), - - #[serde(rename = "snake_case")] - FrontSide(PassportElementErrorFrontSide), - - #[serde(rename = "snake_case")] - ReverseSide(PassportElementErrorReverseSide), - - #[serde(rename = "snake_case")] - Selfie(PassportElementErrorSelfie), - - #[serde(rename = "snake_case")] - File(PassportElementErrorFile), - - #[serde(rename = "snake_case")] - Files(PassportElementErrorFiles), - - #[serde(rename = "snake_case")] - TranslationFile(PassportElementErrorTranslationFile), - - #[serde(rename = "snake_case")] - TranslationFiles(PassportElementErrorTranslationFiles), - - #[serde(rename = "snake_case")] - Unspecified(PassportElementErrorUnspecified), -} - -/// Represents an issue in one of the data fields that was provided by the -/// user. -/// -/// The error is considered resolved when the field's value changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrordatafield). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorDataField { - /// The section of the user's Telegram Passport which has the error. - pub r#type: PassportElementErrorDataFieldType, - - /// Name of the data field which has the error. - pub field_name: String, - - /// Base64-encoded data hash. - pub data_hash: String, -} - -impl PassportElementErrorDataField { - pub fn new( - r#type: PassportElementErrorDataFieldType, - field_name: S1, - data_hash: S2, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { r#type, field_name: field_name.into(), data_hash: data_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorDataFieldType) -> Self { - self.r#type = val; - self - } - - pub fn field_name(mut self, val: S) -> Self - where - S: Into, - { - self.field_name = val.into(); - self - } - - pub fn data_hash(mut self, val: S) -> Self - where - S: Into, - { - self.data_hash = val.into(); - self - } -} - -/// Represents an issue with the front side of a document. -/// -/// The error is considered resolved when the file with the front side of the -/// document changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfrontside). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorFrontSide { - /// The section of the user's Telegram Passport which has the issue. - pub r#type: PassportElementErrorFrontSideType, - - /// Base64-encoded hash of the file with the front side of the - /// document. - pub file_hash: String, -} - -impl PassportElementErrorFrontSide { - pub fn new(r#type: PassportElementErrorFrontSideType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, file_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorFrontSideType) -> Self { - self.r#type = val; - self - } - - pub fn file_hash(mut self, val: S) -> Self - where - S: Into, - { - self.file_hash = val.into(); - self - } -} - -/// Represents an issue with the reverse side of a document. -/// -/// The error is considered resolved when the file with reverse side of the -/// document changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorreverseside). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorReverseSide { - /// The section of the user's Telegram Passport which has the issue. - pub r#type: PassportElementErrorReverseSideType, - - //// Base64-encoded hash of the file with the reverse side of the - //// document. - pub file_hash: String, -} - -impl PassportElementErrorReverseSide { - pub fn new(r#type: PassportElementErrorReverseSideType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, file_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorReverseSideType) -> Self { - self.r#type = val; - self - } - - pub fn file_hash(mut self, val: S) -> Self - where - S: Into, - { - self.file_hash = val.into(); - self - } -} - -//// Represents an issue with the selfie with a document. -// -/// The error is considered resolved when the file with the selfie changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorselfie). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorSelfie { - /// The section of the user's Telegram Passport which has the issue. - pub r#type: PassportElementErrorSelfieType, - - /// Base64-encoded hash of the file with the selfie. - pub file_hash: String, -} - -impl PassportElementErrorSelfie { - pub fn new(r#type: PassportElementErrorSelfieType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, file_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorSelfieType) -> Self { - self.r#type = val; - self - } - - pub fn file_hash(mut self, val: S) -> Self - where - S: Into, - { - self.file_hash = val.into(); - self - } -} - -/// Represents an issue with a document scan. -/// -/// The error is considered resolved when the file with the document scan -/// changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfile). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorFile { - /// The section of the user's Telegram Passport which has the issue. - pub r#type: PassportElementErrorFileType, - - /// Base64-encoded file hash. - pub file_hash: String, -} - -impl PassportElementErrorFile { - pub fn new(r#type: PassportElementErrorFileType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, file_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorFileType) -> Self { - self.r#type = val; - self - } - - pub fn file_hash(mut self, val: S) -> Self - where - S: Into, - { - self.file_hash = val.into(); - self - } -} - -/// Represents an issue with a list of scans. -/// -/// The error is considered resolved when the list of files containing the scans -/// changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorfiles). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorFiles { - /// The section of the user's Telegram Passport which has the issue. - pub r#type: PassportElementErrorFilesType, - - /// List of base64-encoded file hashes. - pub file_hashes: Vec, -} - -impl PassportElementErrorFiles { - pub fn new(r#type: PassportElementErrorFilesType, file_hashes: S) -> Self - where - S: Into>, - { - Self { r#type, file_hashes: file_hashes.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorFilesType) -> Self { - self.r#type = val; - self - } - - pub fn file_hashes(mut self, val: S) -> Self - where - S: Into>, - { - self.file_hashes = val.into(); - self - } -} - -/// Represents an issue with one of the files that constitute the -/// translation of a document. -/// -/// The error is considered resolved when the file changes. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrortranslationfile). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorTranslationFile { - /// Type of element of the user's Telegram Passport which has the - /// issue. - pub r#type: PassportElementErrorTranslationFileType, - - /// Base64-encoded file hash. - pub file_hash: String, -} - -impl PassportElementErrorTranslationFile { - pub fn new(r#type: PassportElementErrorTranslationFileType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, file_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorTranslationFileType) -> Self { - self.r#type = val; - self - } - - pub fn file_hash(mut self, val: S) -> Self - where - S: Into, - { - self.file_hash = val.into(); - self - } -} - -/// Represents an issue with the translated version of a document. -/// -/// The error is considered resolved when a file with the document translation -/// change. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrortranslationfiles). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorTranslationFiles { - /// Type of element of the user's Telegram Passport which has the issue - pub r#type: PassportElementErrorTranslationFilesType, - - /// List of base64-encoded file hashes - pub file_hashes: Vec, -} - -impl PassportElementErrorTranslationFiles { - pub fn new(r#type: PassportElementErrorTranslationFilesType, file_hashes: S) -> Self - where - S: Into>, - { - Self { r#type, file_hashes: file_hashes.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorTranslationFilesType) -> Self { - self.r#type = val; - self - } - - pub fn file_hashes(mut self, val: S) -> Self - where - S: Into>, - { - self.file_hashes = val.into(); - self - } -} - -/// Represents an issue in an unspecified place. -/// -/// The error is considered resolved when new data is added. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportelementerrorunspecified). -#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportElementErrorUnspecified { - /// Type of element of the user's Telegram Passport which has the - /// issue. - pub r#type: PassportElementErrorUnspecifiedType, - - /// Base64-encoded element hash. - pub element_hash: String, -} - -impl PassportElementErrorUnspecified { - pub fn new(r#type: PassportElementErrorUnspecifiedType, file_hash: S) -> Self - where - S: Into, - { - Self { r#type, element_hash: file_hash.into() } - } - - pub fn r#type(mut self, val: PassportElementErrorUnspecifiedType) -> Self { - self.r#type = val; - self - } - - pub fn element_hash(mut self, val: S) -> Self - where - S: Into, - { - self.element_hash = val.into(); - self - } -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorDataFieldType { - PersonalDetails, - Passport, - DriverLicense, - IdentityCard, - InternalPassport, - Address, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorFrontSideType { - Passport, - DriverLicense, - IdentityCard, - InternalPassport, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorReverseSideType { - DriverLicense, - IdentityCard, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorSelfieType { - Passport, - DriverLicense, - IdentityCard, - InternalPassport, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorFileType { - UtilityBill, - BankStatement, - RentalAgreement, - PassportRegistration, - TemporaryRegistration, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorFilesType { - UtilityBill, - BankStatement, - RentalAgreement, - PassportRegistration, - TemporaryRegistration, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorTranslationFileType { - Passport, - DriverLicense, - IdentityCard, - InternalPassport, - UtilityBill, - BankStatement, - RentalAgreement, - PassportRegistration, - TemporaryRegistration, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorTranslationFilesType { - Passport, - DriverLicense, - IdentityCard, - InternalPassport, - UtilityBill, - BankStatement, - RentalAgreement, - PassportRegistration, - TemporaryRegistration, -} - -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum PassportElementErrorUnspecifiedType { - DataField, - FrontSide, - ReverseSide, - Selfie, - File, - Files, - TranslationFile, - TranslationFiles, - Unspecified, -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn serialize_data_field() { - let data = PassportElementError { - message: "This is an error message!".to_owned(), - kind: PassportElementErrorKind::DataField(PassportElementErrorDataField { - r#type: PassportElementErrorDataFieldType::InternalPassport, - field_name: "The field name".to_owned(), - data_hash: "This is a data hash".to_owned(), - }), - }; - - assert_eq!( - serde_json::to_string(&data).unwrap(), - r#"{"message":"This is an error message!","source":"data","type":"internal_passport","field_name":"The field name","data_hash":"This is a data hash"}"# - ); - } -} diff --git a/src/types/passport_file.rs b/src/types/passport_file.rs deleted file mode 100644 index 448d0c62..00000000 --- a/src/types/passport_file.rs +++ /dev/null @@ -1,66 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a file uploaded to Telegram Passport. -/// -/// Currently all Telegram Passport files are in JPEG format when decrypted and -/// don't exceed 10MB. -/// -/// [The official docs](https://core.telegram.org/bots/api#passportfile). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PassportFile { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// File size. - pub file_size: u64, - - /// Unix time when the file was uploaded. - pub file_date: u64, -} - -impl PassportFile { - pub fn new(file_id: S1, file_unique_id: S2, file_size: u64, file_date: u64) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - file_size, - file_date, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn file_size(mut self, val: u64) -> Self { - self.file_size = val; - self - } - - pub fn file_date(mut self, val: u64) -> Self { - self.file_date = val; - self - } -} diff --git a/src/types/photo_size.rs b/src/types/photo_size.rs deleted file mode 100644 index 64ddfac7..00000000 --- a/src/types/photo_size.rs +++ /dev/null @@ -1,94 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents one size of a photo or a [file]/[sticker] thumbnail. -/// -/// [file]: crate::types::Document -/// [sticker]: crate::types::Sticker -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PhotoSize { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// Photo width. - pub width: i32, - - /// Photo height. - pub height: i32, - - /// File size. - pub file_size: Option, -} - -impl PhotoSize { - pub fn new(file_id: S1, file_unique_id: S2, width: i32, height: i32) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - width, - height, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn width(mut self, val: i32) -> Self { - self.width = val; - self - } - - pub fn height(mut self, val: i32) -> Self { - self.height = val; - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn deserialize() { - let json = r#"{"file_id":"id","file_unique_id":"","width":320,"height":320, - "file_size":3452}"#; - let expected = PhotoSize { - file_id: "id".to_string(), - file_unique_id: "".to_string(), - width: 320, - height: 320, - file_size: Some(3452), - }; - let actual = serde_json::from_str::(json).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/src/types/poll.rs b/src/types/poll.rs deleted file mode 100644 index c3646e3b..00000000 --- a/src/types/poll.rs +++ /dev/null @@ -1,250 +0,0 @@ -use crate::types::{MessageEntity, PollType}; -use serde::{Deserialize, Serialize}; - -/// This object contains information about a poll. -/// -/// [The official docs](https://core.telegram.org/bots/api#poll). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Poll { - /// Unique poll identifier. - pub id: String, - - /// Poll question, 1-255 characters. - pub question: String, - - /// List of poll options. - pub options: Vec, - - /// `true`, if the poll is closed. - pub is_closed: bool, - - /// Total number of users that voted in the poll - pub total_voter_count: i32, - - /// True, if the poll is anonymous - pub is_anonymous: bool, - - /// Poll type, currently can be “regular” or “quiz” - #[serde(rename = "type")] - pub poll_type: PollType, - - /// True, if the poll allows multiple answers - pub allows_multiple_answers: bool, - - /// 0-based identifier of the correct answer option. Available only for - /// polls in the quiz mode, which are closed, or was sent (not - /// forwarded) by the bot or to the private chat with the bot. - pub correct_option_id: Option, - - /// Text that is shown when a user chooses an incorrect answer or taps on - /// the lamp icon in a quiz-style poll, 0-200 characters. - pub explanation: Option, - - /// Special entities like usernames, URLs, bot commands, etc. that appear in - /// the explanation. - pub explanation_entities: Option>, - - /// Amount of time in seconds the poll will be active after creation. - open_period: Option, - - /// Point in time (Unix timestamp) when the poll will be automatically - /// closed. - close_date: Option, -} - -impl Poll { - #[allow(clippy::too_many_arguments)] - pub fn new( - id: S1, - question: S2, - options: O, - is_closed: bool, - total_voter_count: i32, - is_anonymous: bool, - poll_type: PollType, - allows_multiple_answers: bool, - ) -> Self - where - S1: Into, - S2: Into, - O: Into>, - { - Self { - id: id.into(), - question: question.into(), - options: options.into(), - is_closed, - total_voter_count, - is_anonymous, - poll_type, - allows_multiple_answers, - correct_option_id: None, - explanation: None, - explanation_entities: None, - open_period: None, - close_date: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn question(mut self, val: S) -> Self - where - S: Into, - { - self.question = val.into(); - self - } - - pub fn options

(mut self, val: P) -> Self - where - P: Into>, - { - self.options = val.into(); - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_closed(mut self, val: bool) -> Self { - self.is_closed = val; - self - } - - pub fn total_voter_count(mut self, val: i32) -> Self { - self.total_voter_count = val; - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_anonymous(mut self, val: bool) -> Self { - self.is_anonymous = val; - self - } - - pub fn poll_type(mut self, val: PollType) -> Self { - self.poll_type = val; - self - } - - pub fn allows_multiple_answers(mut self, val: bool) -> Self { - self.allows_multiple_answers = val; - self - } - - pub fn correct_option_id(mut self, val: i32) -> Self { - self.correct_option_id = Some(val); - self - } - - pub fn explanation(mut self, val: S) -> Self - where - S: Into, - { - self.explanation = Some(val.into()); - self - } - - pub fn explanation_entities(mut self, val: S) -> Self - where - S: Into>, - { - self.explanation_entities = Some(val.into()); - self - } - - pub fn open_period(mut self, val: i32) -> Self { - self.open_period = Some(val); - self - } - - pub fn close_date(mut self, val: i32) -> Self { - self.close_date = Some(val); - self - } -} - -/// This object contains information about one answer option in a poll. -/// -/// [The official docs](https://core.telegram.org/bots/api#polloption). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PollOption { - /// Option text, 1-100 characters. - pub text: String, - - /// Number of users that voted for this option. - pub voter_count: i32, -} - -impl PollOption { - pub fn new(text: S, voter_count: i32) -> Self - where - S: Into, - { - Self { text: text.into(), voter_count } - } - - pub fn text(mut self, val: S) -> Self - where - S: Into, - { - self.text = val.into(); - self - } - - pub fn voter_count(mut self, val: i32) -> Self { - self.voter_count = val; - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn deserialize() { - let data = r#" - { - "allows_multiple_answers": false, - "id": "5377643193141559299", - "is_anonymous": true, - "is_closed": false, - "options": [ - { - "text": "1", - "voter_count": 1 - }, - { - "text": "2", - "voter_count": 0 - }, - { - "text": "3", - "voter_count": 0 - }, - { - "text": "4", - "voter_count": 0 - }, - { - "text": "5", - "voter_count": 0 - } - ], - "question": "Rate me from 1 to 5.", - "total_voter_count": 1, - "type": "regular" - } - "#; - serde_json::from_str::(data).unwrap(); - } -} diff --git a/src/types/poll_answer.rs b/src/types/poll_answer.rs deleted file mode 100644 index 6ddb0b06..00000000 --- a/src/types/poll_answer.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::types::User; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PollAnswer { - /// Unique poll identifier. - pub poll_id: String, - - /// The user, who changed the answer to the poll. - pub user: User, - - /// 0-based identifiers of answer options, chosen by the user. - /// - /// May be empty if the user retracted their vote. - pub option_ids: Vec, -} - -impl PollAnswer { - pub fn new(poll_id: S, user: User, option_ids: O) -> Self - where - S: Into, - O: Into>, - { - Self { poll_id: poll_id.into(), user, option_ids: option_ids.into() } - } - - pub fn poll_id(mut self, val: S) -> Self - where - S: Into, - { - self.poll_id = val.into(); - self - } - - pub fn user(mut self, val: User) -> Self { - self.user = val; - self - } - - pub fn option_ids(mut self, val: S) -> Self - where - S: Into>, - { - self.option_ids = val.into(); - self - } -} diff --git a/src/types/poll_type.rs b/src/types/poll_type.rs deleted file mode 100644 index 0243f7c1..00000000 --- a/src/types/poll_type.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -#[non_exhaustive] -pub enum PollType { - Quiz, - Regular, -} diff --git a/src/types/pre_checkout_query.rs b/src/types/pre_checkout_query.rs deleted file mode 100644 index 87fd9707..00000000 --- a/src/types/pre_checkout_query.rs +++ /dev/null @@ -1,108 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{Currency, OrderInfo, User}; - -/// This object contains information about an incoming pre-checkout query. -/// -/// [The official docs](https://core.telegram.org/bots/api#precheckoutquery). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct PreCheckoutQuery { - /// Unique query identifier. - pub id: String, - - /// User who sent the query. - pub from: User, - - /// Three-letter ISO 4217 [currency] code. - /// - /// [currency]: https://core.telegram.org/bots/payments#supported-currencies - pub currency: Currency, - - /// Total price in the _smallest units_ of the currency (integer, **not** - /// float/double). For example, for a price of `US$ 1.45` pass `amount = - /// 145`. See the exp parameter in [`currencies.json`], it shows the number - /// of digits past the decimal point for each currency (2 for the - /// majority of currencies). - /// - /// [`currencies.json`]: https://core.telegram.org/bots/payments/currencies.json - pub total_amount: i32, - - /// Bot specified invoice payload. - pub invoice_payload: String, - - /// Identifier of the shipping option chosen by the user. - pub shipping_option_id: Option, - - /// Order info provided by the user. - pub order_info: Option, -} - -impl PreCheckoutQuery { - pub fn new( - id: S1, - from: User, - currency: Currency, - total_amount: i32, - invoice_payload: S2, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { - id: id.into(), - from, - currency, - total_amount, - invoice_payload: invoice_payload.into(), - shipping_option_id: None, - order_info: None, - } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn from(mut self, val: User) -> Self { - self.from = val; - self - } - - pub fn currency(mut self, val: Currency) -> Self { - self.currency = val; - self - } - - pub fn total_amount(mut self, val: i32) -> Self { - self.total_amount = val; - self - } - - pub fn invoice_payload(mut self, val: S) -> Self - where - S: Into, - { - self.invoice_payload = val.into(); - self - } - - pub fn shipping_option_id(mut self, val: S) -> Self - where - S: Into, - { - self.shipping_option_id = Some(val.into()); - self - } - - pub fn order_info(mut self, val: OrderInfo) -> Self { - self.order_info = Some(val); - self - } -} diff --git a/src/types/reply_keyboard_markup.rs b/src/types/reply_keyboard_markup.rs deleted file mode 100644 index a8d5983e..00000000 --- a/src/types/reply_keyboard_markup.rs +++ /dev/null @@ -1,98 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::KeyboardButton; - -/// This object represents a [custom keyboard] with reply options (see -/// [Introduction to bots] for details and examples). -/// -/// [The official docs](https://core.telegram.org/bots/api#replykeyboardmarkup). -/// -/// [custom keyboard]: https://core.telegram.org/bots#keyboards -/// [Introduction to bots]: https://core.telegram.org/bots#keyboards -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, Default)] -#[non_exhaustive] -pub struct ReplyKeyboardMarkup { - /// Array of button rows, each represented by an Array of - /// [`KeyboardButton`] objects - /// - /// [`KeyboardButton`]: crate::types::KeyboardButton - pub keyboard: Vec>, - - /// Requests clients to resize the keyboard vertically for optimal fit - /// (e.g., make the keyboard smaller if there are just two rows of - /// buttons). Defaults to `false`, in which case the custom keyboard is - /// always of the same height as the app's standard keyboard. - pub resize_keyboard: Option, - - /// Requests clients to hide the keyboard as soon as it's been used. The - /// keyboard will still be available, but clients will automatically - /// display the usual letter-keyboard in the chat – the user can press a - /// special button in the input field to see the custom keyboard again. - /// Defaults to `false`. - pub one_time_keyboard: Option, - - /// Use this parameter if you want to show the keyboard to specific users - /// only. Targets: 1) users that are `@mentioned` in the `text` of the - /// [`Message`] object; 2) if the bot's message is a reply (has - /// `reply_to_message_id`), sender of the original message. - /// - /// Example: A user requests to change the bot‘s language, bot replies to - /// the request with a keyboard to select the new language. Other users - /// in the group don’t see the keyboard. - /// - /// [`Message`]: crate::types::Message - pub selective: Option, -} - -impl ReplyKeyboardMarkup { - pub fn new(keyboard: K1) -> Self - where - K1: Into>, - K2: Into>, - { - Self { - keyboard: keyboard.into().into_iter().map(Into::into).collect(), - resize_keyboard: None, - one_time_keyboard: None, - selective: None, - } - } - - pub fn append_row(mut self, buttons: Vec) -> Self { - self.keyboard.push(buttons); - self - } - - pub fn append_to_row(mut self, button: KeyboardButton, index: usize) -> Self { - match self.keyboard.get_mut(index) { - Some(buttons) => buttons.push(button), - None => self.keyboard.push(vec![button]), - }; - self - } - - pub fn resize_keyboard(mut self, val: T) -> Self - where - T: Into>, - { - self.resize_keyboard = val.into(); - self - } - - pub fn one_time_keyboard(mut self, val: T) -> Self - where - T: Into>, - { - self.one_time_keyboard = val.into(); - self - } - - pub fn selective(mut self, val: T) -> Self - where - T: Into>, - { - self.selective = val.into(); - self - } -} diff --git a/src/types/reply_keyboard_remove.rs b/src/types/reply_keyboard_remove.rs deleted file mode 100644 index deb8351b..00000000 --- a/src/types/reply_keyboard_remove.rs +++ /dev/null @@ -1,52 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::True; - -/// Upon receiving a message with this object, Telegram clients will remove the -/// current custom keyboard and display the default letter-keyboard. -/// -/// By default, custom keyboards are displayed until a new keyboard is sent by a -/// bot. An exception is made for one-time keyboards that are hidden immediately -/// after the user presses a button (see [`ReplyKeyboardMarkup`]). -/// -/// [The official docs](https://core.telegram.org/bots/api#replykeyboardremove). -/// -/// [`ReplyKeyboardMarkup`]: crate::types::ReplyKeyboardMarkup -#[serde_with_macros::skip_serializing_none] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ReplyKeyboardRemove { - /// Requests clients to remove the custom keyboard (user will not be able - /// to summon this keyboard; if you want to hide the keyboard from sight - /// but keep it accessible, use one_time_keyboard in - /// [`ReplyKeyboardMarkup`]). - /// - /// [`ReplyKeyboardMarkup`]: crate::types::ReplyKeyboardMarkup - pub remove_keyboard: True, - - /// Use this parameter if you want to remove the keyboard for specific - /// users only. Targets: 1) users that are `@mentioned` in the `text` of - /// the [`Message`] object; 2) if the bot's message is a reply (has - /// `reply_to_message_id`), sender of the original message. - /// - /// Example: A user votes in a poll, bot returns confirmation message in - /// reply to the vote and removes the keyboard for that user, while still - /// showing the keyboard with poll options to users who haven't voted yet. - /// - /// [`Message`]: crate::types::Message - pub selective: Option, -} - -impl ReplyKeyboardRemove { - pub fn new() -> Self { - Self::default() - } - - pub fn selective(mut self, val: T) -> Self - where - T: Into, - { - self.selective = Some(val.into()); - self - } -} diff --git a/src/types/reply_markup.rs b/src/types/reply_markup.rs deleted file mode 100644 index 4bddc56c..00000000 --- a/src/types/reply_markup.rs +++ /dev/null @@ -1,27 +0,0 @@ -use derive_more::From; -use serde::{Deserialize, Serialize}; - -use crate::types::{ForceReply, InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove}; - -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, From)] -#[serde(untagged)] -#[non_exhaustive] -pub enum ReplyMarkup { - InlineKeyboardMarkup(InlineKeyboardMarkup), - ReplyKeyboardMarkup(ReplyKeyboardMarkup), - ReplyKeyboardRemove(ReplyKeyboardRemove), - ForceReply(ForceReply), -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn inline_keyboard_markup() { - let data = InlineKeyboardMarkup::default(); - let expected = ReplyMarkup::InlineKeyboardMarkup(data.clone()); - let actual: ReplyMarkup = data.into(); - assert_eq!(actual, expected) - } -} diff --git a/src/types/response_parameters.rs b/src/types/response_parameters.rs deleted file mode 100644 index 2f0fb43f..00000000 --- a/src/types/response_parameters.rs +++ /dev/null @@ -1,43 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// Contains information about why a request was unsuccessful. -/// -/// [The official docs](https://core.telegram.org/bots/api#responseparameters). -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum ResponseParameters { - /// The group has been migrated to a supergroup with the specified - /// identifier. This number may be greater than 32 bits and some - /// programming languages may have difficulty/silent defects in - /// interpreting it. But it is smaller than 52 bits, so a signed 64 bit - /// integer or double-precision float type are safe for storing this - /// identifier. - MigrateToChatId(i64), - - /// In case of exceeding flood control, the number of seconds left to wait - /// before the request can be repeated. - RetryAfter(i32), -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn migrate_to_chat_id_deserialization() { - let expected = ResponseParameters::MigrateToChatId(123_456); - let actual: ResponseParameters = - serde_json::from_str(r#"{"migrate_to_chat_id":123456}"#).unwrap(); - - assert_eq!(expected, actual); - } - - #[test] - fn retry_after_deserialization() { - let expected = ResponseParameters::RetryAfter(123_456); - let actual: ResponseParameters = serde_json::from_str(r#"{"retry_after":123456}"#).unwrap(); - - assert_eq!(expected, actual); - } -} diff --git a/src/types/send_invoice.rs b/src/types/send_invoice.rs deleted file mode 100644 index bc527b45..00000000 --- a/src/types/send_invoice.rs +++ /dev/null @@ -1,229 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{ChatId, InlineKeyboardMarkup, LabeledPrice}; - -// TODO: missing docs -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct SendInvoice { - pub chat_id: ChatId, - pub title: String, - pub description: String, - pub payload: String, - pub provider_token: String, - pub start_parameter: String, - pub currency: String, - pub prices: Vec, - pub provider_data: Option, - pub photo_url: Option, - pub photo_size: Option, - pub photo_width: Option, - pub photo_height: Option, - pub need_name: Option, - pub need_phone_number: Option, - pub need_email: Option, - pub need_shipping_address: Option, - pub send_phone_number_to_provider: Option, - pub send_email_to_provider: Option, - pub is_flexible: Option, - pub disable_notification: Option, - pub reply_to_message_id: Option, - pub reply_markup: Option, -} - -impl SendInvoice { - #[allow(clippy::too_many_arguments)] - pub fn new( - chat_id: C, - title: S1, - description: S2, - payload: S3, - provider_token: S4, - start_parameter: S5, - currency: S6, - prices: P, - ) -> Self - where - C: Into, - S1: Into, - S2: Into, - S3: Into, - S4: Into, - S5: Into, - S6: Into, - P: Into>, - { - Self { - chat_id: chat_id.into(), - title: title.into(), - description: description.into(), - payload: payload.into(), - provider_token: provider_token.into(), - start_parameter: start_parameter.into(), - currency: currency.into(), - prices: prices.into(), - provider_data: None, - photo_url: None, - photo_size: None, - photo_width: None, - photo_height: None, - need_name: None, - need_phone_number: None, - need_email: None, - need_shipping_address: None, - send_phone_number_to_provider: None, - send_email_to_provider: None, - is_flexible: None, - disable_notification: None, - reply_to_message_id: None, - reply_markup: None, - } - } - - pub fn chat_id(mut self, val: C) -> Self - where - C: Into, - { - self.chat_id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn description(mut self, val: S) -> Self - where - S: Into, - { - self.description = val.into(); - self - } - - pub fn payload(mut self, val: S) -> Self - where - S: Into, - { - self.payload = val.into(); - self - } - - pub fn provider_token(mut self, val: S) -> Self - where - S: Into, - { - self.provider_token = val.into(); - self - } - - pub fn start_parameter(mut self, val: S) -> Self - where - S: Into, - { - self.start_parameter = val.into(); - self - } - - pub fn currency(mut self, val: S) -> Self - where - S: Into, - { - self.currency = val.into(); - self - } - - pub fn prices

(mut self, val: P) -> Self - where - P: Into>, - { - self.prices = val.into(); - self - } - - pub fn provider_data(mut self, val: S) -> Self - where - S: Into, - { - self.provider_data = Some(val.into()); - self - } - - pub fn photo_url(mut self, val: S) -> Self - where - S: Into, - { - self.photo_url = Some(val.into()); - self - } - - pub fn photo_size(mut self, val: i32) -> Self { - self.photo_size = Some(val); - self - } - - pub fn photo_width(mut self, val: i32) -> Self { - self.photo_width = Some(val); - self - } - - pub fn photo_height(mut self, val: i32) -> Self { - self.photo_height = Some(val); - self - } - - pub fn need_name(mut self, val: bool) -> Self { - self.need_name = Some(val); - self - } - - pub fn need_phone_number(mut self, val: bool) -> Self { - self.need_phone_number = Some(val); - self - } - - pub fn need_email(mut self, val: bool) -> Self { - self.need_email = Some(val); - self - } - - pub fn need_shipping_address(mut self, val: bool) -> Self { - self.need_shipping_address = Some(val); - self - } - - pub fn send_phone_number_to_provider(mut self, val: bool) -> Self { - self.send_phone_number_to_provider = Some(val); - self - } - - pub fn send_email_to_provider(mut self, val: bool) -> Self { - self.send_email_to_provider = Some(val); - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_flexible(mut self, val: bool) -> Self { - self.is_flexible = Some(val); - self - } - - pub fn disable_notification(mut self, val: bool) -> Self { - self.disable_notification = Some(val); - self - } - - pub fn reply_to_message_id(mut self, value: i32) -> Self { - self.reply_to_message_id = Some(value); - self - } - - pub fn reply_markup(mut self, val: InlineKeyboardMarkup) -> Self { - self.reply_markup = Some(val); - self - } -} diff --git a/src/types/shipping_address.rs b/src/types/shipping_address.rs deleted file mode 100644 index 3a0adb58..00000000 --- a/src/types/shipping_address.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::types::CountryCode; -use serde::{Deserialize, Serialize}; - -/// This object represents a shipping address. -/// -/// [The official docs](https://core.telegram.org/bots/api#shippingaddress). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ShippingAddress { - /// ISO 3166-1 alpha-2 country code. - pub country_code: CountryCode, - - /// State, if applicable. - pub state: String, - - /// City. - pub city: String, - - /// First line for the address. - pub street_line1: String, - - /// Second line for the address. - pub street_line2: String, - - /// Address post code. - pub post_code: String, -} - -impl ShippingAddress { - pub fn new( - country_code: CountryCode, - - state: S1, - city: S2, - street_line1: S3, - street_line2: S4, - post_code: S5, - ) -> Self - where - S1: Into, - S2: Into, - S3: Into, - S4: Into, - S5: Into, - { - Self { - country_code, - state: state.into(), - city: city.into(), - street_line1: street_line1.into(), - street_line2: street_line2.into(), - post_code: post_code.into(), - } - } - - pub fn country_code(mut self, val: CountryCode) -> Self { - self.country_code = val; - self - } - - pub fn state(mut self, val: S) -> Self - where - S: Into, - { - self.state = val.into(); - self - } - - pub fn city(mut self, val: S) -> Self - where - S: Into, - { - self.city = val.into(); - self - } - - pub fn street_line1(mut self, val: S) -> Self - where - S: Into, - { - self.street_line1 = val.into(); - self - } - - pub fn street_line2(mut self, val: S) -> Self - where - S: Into, - { - self.street_line2 = val.into(); - self - } - - pub fn post_code(mut self, val: S) -> Self - where - S: Into, - { - self.post_code = val.into(); - self - } -} diff --git a/src/types/shipping_option.rs b/src/types/shipping_option.rs deleted file mode 100644 index 983c7eef..00000000 --- a/src/types/shipping_option.rs +++ /dev/null @@ -1,71 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::LabeledPrice; - -/// This object represents one shipping option. -/// -/// [The official docs](https://core.telegram.org/bots/api#shippingoption). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ShippingOption { - /// Shipping option identifier. - pub id: String, - - /// Option title. - pub title: String, - - /// List of price portions. - pub prices: Vec, -} - -impl ShippingOption { - pub fn new(id: S1, title: S2, prices: P) -> Self - where - S1: Into, - S2: Into, - P: Into>, - { - Self { id: id.into(), title: title.into(), prices: prices.into() } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn prices

(mut self, val: P) -> Self - where - P: Into>, - { - self.prices = val.into(); - self - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn serialize() { - let shipping_option = ShippingOption { - id: "0".to_string(), - title: "Option".to_string(), - prices: vec![LabeledPrice { label: "Label".to_string(), amount: 60 }], - }; - let expected = r#"{"id":"0","title":"Option","prices":[{"label":"Label","amount":60}]}"#; - let actual = serde_json::to_string(&shipping_option).unwrap(); - assert_eq!(actual, expected); - } -} diff --git a/src/types/shipping_query.rs b/src/types/shipping_query.rs deleted file mode 100644 index bfdf7dc8..00000000 --- a/src/types/shipping_query.rs +++ /dev/null @@ -1,63 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{ShippingAddress, User}; - -/// This object contains information about an incoming shipping query. -/// -/// [The official docs](https://core.telegram.org/bots/api#shippingquery). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct ShippingQuery { - /// Unique query identifier. - pub id: String, - - /// User who sent the query. - pub from: User, - - /// Bot specified invoice payload. - pub invoice_payload: String, - - /// User specified shipping address. - pub shipping_address: ShippingAddress, -} - -impl ShippingQuery { - pub fn new( - id: S1, - from: User, - invoice_payload: S2, - shipping_address: ShippingAddress, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { id: id.into(), from, invoice_payload: invoice_payload.into(), shipping_address } - } - - pub fn id(mut self, val: S) -> Self - where - S: Into, - { - self.id = val.into(); - self - } - - pub fn from(mut self, val: User) -> Self { - self.from = val; - self - } - - pub fn invoice_payload(mut self, val: S) -> Self - where - S: Into, - { - self.invoice_payload = val.into(); - self - } - - pub fn shipping_address(mut self, val: ShippingAddress) -> Self { - self.shipping_address = val; - self - } -} diff --git a/src/types/sticker.rs b/src/types/sticker.rs deleted file mode 100644 index d133f1cc..00000000 --- a/src/types/sticker.rs +++ /dev/null @@ -1,135 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{MaskPosition, PhotoSize}; - -/// This object represents a sticker. -/// -/// [The official docs](https://core.telegram.org/bots/api#sticker). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Sticker { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// Sticker width. - pub width: u16, - - /// Sticker height. - pub height: u16, - - /// `true`, if the sticker is [animated]. - /// - /// [animated]: https://telegram.org/blog/animated-stickers - pub is_animated: bool, - - /// Sticker thumbnail in the .webp or .jpg format. - pub thumb: Option, - - /// Emoji associated with the sticker. - pub emoji: Option, - - /// Name of the sticker set to which the sticker belongs. - pub set_name: Option, - - /// For mask stickers, the position where the mask should be placed. - pub mask_position: Option, - - /// File size. - pub file_size: Option, -} - -impl Sticker { - pub fn new( - file_id: S1, - file_unique_id: S2, - width: u16, - height: u16, - is_animated: bool, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - width, - height, - is_animated, - thumb: None, - emoji: None, - set_name: None, - mask_position: None, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn height(mut self, val: u16) -> Self { - self.height = val; - self - } - - pub fn width(mut self, val: u16) -> Self { - self.width = val; - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_animated(mut self, val: bool) -> Self { - self.is_animated = val; - self - } - - pub fn thumb(mut self, val: PhotoSize) -> Self { - self.thumb = Some(val); - self - } - - pub fn emoji(mut self, val: S) -> Self - where - S: Into, - { - self.emoji = Some(val.into()); - self - } - - pub fn set_name(mut self, val: S) -> Self - where - S: Into, - { - self.set_name = Some(val.into()); - self - } - - pub fn mask_position(mut self, val: MaskPosition) -> Self { - self.mask_position = Some(val); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } -} diff --git a/src/types/sticker_set.rs b/src/types/sticker_set.rs deleted file mode 100644 index 0c617205..00000000 --- a/src/types/sticker_set.rs +++ /dev/null @@ -1,89 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{PhotoSize, Sticker}; - -/// This object represents a sticker set. -/// -/// [The official docs](https://core.telegram.org/bots/api#stickerset). -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct StickerSet { - /// Sticker set name. - pub name: String, - - /// Sticker set title. - pub title: String, - - /// `true`, if the sticker set contains [animated stickers]. - /// - /// [animates stickers]: https://telegram.org/blog/animated-stickers - pub is_animated: bool, - - /// `true`, if the sticker set contains masks. - pub contains_masks: bool, - - /// List of all set stickers. - pub stickers: Vec, - - /// Sticker set thumbnail in the .WEBP or .TGS format. - thumb: Option, -} - -impl StickerSet { - pub fn new( - name: S1, - title: S2, - is_animated: bool, - contains_masks: bool, - stickers: St, - ) -> Self - where - S1: Into, - S2: Into, - St: Into>, - { - Self { - name: name.into(), - title: title.into(), - is_animated, - contains_masks, - stickers: stickers.into(), - thumb: None, - } - } - - pub fn name(mut self, val: S) -> Self - where - S: Into, - { - self.name = val.into(); - self - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_animated(mut self, val: bool) -> Self { - self.is_animated = val; - self - } - - pub fn contains_masks(mut self, val: bool) -> Self { - self.contains_masks = val; - self - } - - pub fn stickers(mut self, val: S) -> Self - where - S: Into>, - { - self.stickers = val.into(); - self - } -} diff --git a/src/types/sticker_type.rs b/src/types/sticker_type.rs deleted file mode 100644 index 398ffb3a..00000000 --- a/src/types/sticker_type.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::types::InputFile; - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum StickerType { - /// PNG image with the sticker, must be up to 512 kilobytes in size, - /// dimensions must not exceed 512px, and either width or height must be - /// exactly 512px. - /// - /// Pass [`InputFile::FileId`] to send a sticker that exists on the Telegram - /// servers (recommended), pass an [`InputFile::Url`] for Telegram to get a - /// sticker (.WEBP file) from the Internet, pass [`InputFile::File`] to - /// upload a sticker from the file system or [`InputFile::Memory`] to upload - /// a sticker from memory [More info on Sending Files »]. - /// - /// [`InputFile::FileId`]: crate::types::InputFile::FileId - /// [`InputFile::Url`]: crate::types::InputFile::Url - /// [`InputFile::File`]: crate::types::InputFile::File - /// [`InputFile::Memory`]: crate::types::InputFile::Memory - /// - /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files - Png(InputFile), - - /// TGS animation with the sticker, uploaded using multipart/form-data. - /// - /// See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements - Tgs(InputFile), -} diff --git a/src/types/successful_payment.rs b/src/types/successful_payment.rs deleted file mode 100644 index 439dbc23..00000000 --- a/src/types/successful_payment.rs +++ /dev/null @@ -1,112 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{Currency, OrderInfo}; - -/// This object contains basic information about a successful payment. -/// -/// [The official docs](https://core.telegram.org/bots/api#successfulpayment). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct SuccessfulPayment { - /// Three-letter ISO 4217 [currency] code. - /// - /// [currency]: https://core.telegram.org/bots/payments#supported-currencies - pub currency: Currency, - - /// Total price in the smallest units of the currency (integer, not - /// float/double). For example, for a price of `US$ 1.45` pass `amount = - /// 145`. See the exp parameter in [`currencies.json`], it shows the - /// number of digits past the decimal point for each currency (2 for - /// the majority of currencies). - /// - /// [`currencies.json`]: https://core.telegram.org/bots/payments/currencies.json - pub total_amount: i32, - - /// Bot specified invoice payload. - pub invoice_payload: String, - - /// Identifier of the shipping option chosen by the user. - pub shipping_option_id: Option, - - /// Order info provided by the user. - pub order_info: Option, - - /// Telegram payment identifier. - pub telegram_payment_charge_id: String, - - /// Provider payment identifier. - pub provider_payment_charge_id: String, -} - -impl SuccessfulPayment { - pub fn new( - currency: Currency, - total_amount: i32, - invoice_payload: S1, - telegram_payment_charge_id: S2, - provider_payment_charge_id: S3, - ) -> Self - where - S1: Into, - S2: Into, - S3: Into, - { - Self { - currency, - total_amount, - invoice_payload: invoice_payload.into(), - shipping_option_id: None, - order_info: None, - telegram_payment_charge_id: telegram_payment_charge_id.into(), - provider_payment_charge_id: provider_payment_charge_id.into(), - } - } - - pub fn currency(mut self, val: Currency) -> Self { - self.currency = val; - self - } - - pub fn total_amount(mut self, val: i32) -> Self { - self.total_amount = val; - self - } - - pub fn invoice_payload(mut self, val: S) -> Self - where - S: Into, - { - self.invoice_payload = val.into(); - self - } - - pub fn shipping_option_id(mut self, val: S) -> Self - where - S: Into, - { - self.shipping_option_id = Some(val.into()); - self - } - - pub fn order_info(mut self, val: OrderInfo) -> Self { - self.order_info = Some(val); - self - } - - pub fn telegram_payment_charge_id(mut self, val: S) -> Self - where - S: Into, - { - self.telegram_payment_charge_id = val.into(); - self - } - - pub fn provider_payment_charge_id(mut self, val: S) -> Self - where - S: Into, - { - self.provider_payment_charge_id = val.into(); - self - } -} diff --git a/src/types/target_message.rs b/src/types/target_message.rs deleted file mode 100644 index 0c0d8cc1..00000000 --- a/src/types/target_message.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::types::ChatId; - -use serde::{Deserialize, Serialize}; - -/// A message in chat or inline message. -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[serde(untagged)] -pub enum TargetMessage { - Common { chat_id: ChatId, message_id: i32 }, - Inline { inline_message_id: String }, -} - -impl From for TargetMessage { - fn from(inline_message_id: String) -> Self { - Self::Inline { inline_message_id } - } -} diff --git a/src/types/unit_false.rs b/src/types/unit_false.rs deleted file mode 100644 index bde6410b..00000000 --- a/src/types/unit_false.rs +++ /dev/null @@ -1,76 +0,0 @@ -use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; - -/// A type that is always false. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Default)] -pub struct False; - -impl std::convert::TryFrom for False { - type Error = (); - - fn try_from(value: bool) -> Result { - match value { - true => Err(()), - false => Ok(False), - } - } -} - -impl<'de> Deserialize<'de> for False { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_bool(FalseVisitor) - } -} - -struct FalseVisitor; - -impl<'de> Visitor<'de> for FalseVisitor { - type Value = False; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(formatter, "bool, equal to `false`") - } - - fn visit_bool(self, value: bool) -> Result - where - E: serde::de::Error, - { - match value { - true => Err(E::custom("expected `false`, found `true`")), - false => Ok(False), - } - } -} - -impl Serialize for False { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_bool(false) - } -} - -#[cfg(test)] -mod tests { - use serde_json::{from_str, to_string}; - - use super::False; - - #[test] - fn unit_false_de() { - let json = "false"; - let expected = False; - let actual = from_str(json).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn unit_false_se() { - let actual = to_string(&False).unwrap(); - let expected = "false"; - assert_eq!(expected, actual); - } -} diff --git a/src/types/unit_true.rs b/src/types/unit_true.rs deleted file mode 100644 index cd71e5c2..00000000 --- a/src/types/unit_true.rs +++ /dev/null @@ -1,79 +0,0 @@ -use serde::{ - de::{self, Deserialize, Deserializer, Visitor}, - ser::{Serialize, Serializer}, -}; - -/// A type that is always true. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Default)] -pub struct True; - -impl std::convert::TryFrom for True { - type Error = (); - - fn try_from(value: bool) -> Result { - match value { - true => Ok(True), - false => Err(()), - } - } -} - -impl<'de> Deserialize<'de> for True { - fn deserialize(des: D) -> Result - where - D: Deserializer<'de>, - { - des.deserialize_bool(TrueVisitor) - } -} - -struct TrueVisitor; - -impl<'de> Visitor<'de> for TrueVisitor { - type Value = True; - - fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "bool, equal to `true`") - } - - fn visit_bool(self, value: bool) -> Result - where - E: de::Error, - { - match value { - true => Ok(True), - false => Err(E::custom("expected `true`, found `false`")), - } - } -} - -impl Serialize for True { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_bool(true) - } -} - -#[cfg(test)] -mod tests { - use serde_json::{from_str, to_string}; - - use super::True; - - #[test] - fn unit_true_de() { - let json = "true"; - let expected = True; - let actual = from_str(json).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn unit_true_se() { - let actual = to_string(&True).unwrap(); - let expected = "true"; - assert_eq!(expected, actual); - } -} diff --git a/src/types/update.rs b/src/types/update.rs deleted file mode 100644 index 6b047dcf..00000000 --- a/src/types/update.rs +++ /dev/null @@ -1,321 +0,0 @@ -#![allow(clippy::large_enum_variant)] - -use serde::{Deserialize, Serialize}; - -use crate::types::{ - CallbackQuery, Chat, ChosenInlineResult, InlineQuery, Message, Poll, PollAnswer, - PreCheckoutQuery, ShippingQuery, User, -}; -use serde_json::Value; - -/// This [object] represents an incoming update. -/// -/// [The official docs](https://core.telegram.org/bots/api#update). -/// -/// [object]: https://core.telegram.org/bots/api#available-types -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Update { - /// The update‘s unique identifier. Update identifiers start from a certain - /// positive number and increase sequentially. This ID becomes especially - /// handy if you’re using [Webhooks], since it allows you to ignore - /// repeated updates or to restore the correct update sequence, should - /// they get out of order. If there are no new updates for at least a - /// week, then identifier of the next update will be chosen randomly - /// instead of sequentially. - /// - /// [Webhooks]: crate::Bot::set_webhook - #[serde(rename = "update_id")] - pub id: i32, - - #[serde(flatten)] - pub kind: UpdateKind, -} - -impl Update { - pub fn new(id: i32, kind: UpdateKind) -> Self { - Self { id, kind } - } - - pub fn id(mut self, val: i32) -> Self { - self.id = val; - self - } - - pub fn kind(mut self, val: UpdateKind) -> Self { - self.kind = val; - self - } -} - -impl Update { - /// Tries to parse `value` into `Update`, logging an error if failed. - /// - /// It is used to implement update listeners. - pub fn try_parse(value: &Value) -> Result { - match serde_json::from_str(&value.to_string()) { - Ok(update) => Ok(update), - Err(error) => { - log::error!( - "Cannot parse an update.\nError: {:?}\nValue: {}\n\ - This is a bug in teloxide, please open an issue here: \ - https://github.com/teloxide/teloxide/issues.", - error, - value - ); - Err(error) - } - } - } -} - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -#[non_exhaustive] -pub enum UpdateKind { - /// New incoming message of any kind — text, photo, sticker, etc. - Message(Message), - - /// New version of a message that is known to the bot and was edited. - EditedMessage(Message), - - /// New incoming channel post of any kind — text, photo, sticker, etc. - ChannelPost(Message), - - /// New version of a channel post that is known to the bot and was edited. - EditedChannelPost(Message), - - /// New incoming [inline] query. - /// - /// [inline]: https://core.telegram.org/bots/api#inline-mode - InlineQuery(InlineQuery), - - /// The result of an [inline] query that was chosen by a user and sent to - /// their chat partner. Please see our documentation on the [feedback - /// collecting] for details on how to enable these updates for your bot. - /// - /// [inline]: https://core.telegram.org/bots/api#inline-mode - /// [feedback collecting]: https://core.telegram.org/bots/inline#collecting-feedback - ChosenInlineResult(ChosenInlineResult), - - /// New incoming callback query. - CallbackQuery(CallbackQuery), - - /// New incoming shipping query. Only for invoices with flexible price. - ShippingQuery(ShippingQuery), - - /// New incoming pre-checkout query. Contains full information about - /// checkout. - PreCheckoutQuery(PreCheckoutQuery), - - /// New poll state. Bots receive only updates about stopped polls and - /// polls, which are sent by the bot. - Poll(Poll), - - /// A user changed their answer in a non-anonymous poll. Bots receive new - /// votes only in polls that were sent by the bot itself. - PollAnswer(PollAnswer), -} - -impl Update { - pub fn user(&self) -> Option<&User> { - match &self.kind { - UpdateKind::Message(m) => m.from(), - UpdateKind::EditedMessage(m) => m.from(), - UpdateKind::CallbackQuery(query) => Some(&query.from), - UpdateKind::ChosenInlineResult(chosen) => Some(&chosen.from), - UpdateKind::InlineQuery(query) => Some(&query.from), - UpdateKind::ShippingQuery(query) => Some(&query.from), - UpdateKind::PreCheckoutQuery(query) => Some(&query.from), - UpdateKind::PollAnswer(answer) => Some(&answer.user), - _ => None, - } - } - - pub fn chat(&self) -> Option<&Chat> { - match &self.kind { - UpdateKind::Message(m) => Some(&m.chat), - UpdateKind::EditedMessage(m) => Some(&m.chat), - UpdateKind::ChannelPost(p) => Some(&p.chat), - UpdateKind::EditedChannelPost(p) => Some(&p.chat), - UpdateKind::CallbackQuery(q) => Some(&q.message.as_ref()?.chat), - _ => None, - } - } -} - -#[cfg(test)] -mod test { - use crate::types::{ - Chat, ChatKind, ChatPrivate, ForwardKind, ForwardOrigin, MediaKind, MediaText, Message, - MessageCommon, MessageKind, Update, UpdateKind, User, - }; - - // TODO: more tests for deserialization - #[test] - fn message() { - let json = r#"{ - "update_id":892252934, - "message":{ - "message_id":6557, - "from":{ - "id":218485655, - "is_bot": false, - "first_name":"Waffle", - "username":"WaffleLapkin", - "language_code":"en" - }, - "chat":{ - "id":218485655, - "first_name":"Waffle", - "username":"WaffleLapkin", - "type":"private" - }, - "date":1569518342, - "text":"hello there" - } - }"#; - - let expected = Update { - id: 892_252_934, - kind: UpdateKind::Message(Message { - via_bot: None, - id: 6557, - date: 1_569_518_342, - chat: Chat { - id: 218_485_655, - kind: ChatKind::Private(ChatPrivate { - type_: (), - username: Some(String::from("WaffleLapkin")), - first_name: Some(String::from("Waffle")), - last_name: None, - }), - photo: None, - }, - kind: MessageKind::Common(MessageCommon { - from: Some(User { - id: 218_485_655, - is_bot: false, - first_name: String::from("Waffle"), - last_name: None, - username: Some(String::from("WaffleLapkin")), - language_code: Some(String::from("en")), - }), - forward_kind: ForwardKind::Origin(ForwardOrigin { reply_to_message: None }), - edit_date: None, - media_kind: MediaKind::Text(MediaText { - text: String::from("hello there"), - entities: vec![], - }), - reply_markup: None, - }), - }), - }; - - let actual = serde_json::from_str::(json).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn de_private_chat_text_message() { - let text = r#" - { - "message": { - "chat": { - "first_name": "Hirrolot", - "id": 408258968, - "type": "private", - "username": "hirrolot" - }, - "date": 1581448857, - "from": { - "first_name": "Hirrolot", - "id": 408258968, - "is_bot": false, - "language_code": "en", - "username": "hirrolot" - }, - "message_id": 154, - "text": "4" - }, - "update_id": 306197398 - } -"#; - - assert!(serde_json::from_str::(text).is_ok()); - } - - #[test] - fn pinned_message_works() { - let json = r#"{ - "message": { - "chat": { - "id": -1001276785818, - "title": "teloxide dev", - "type": "supergroup", - "username": "teloxide_dev" - }, - "date": 1582134655, - "from": { - "first_name": "Hirrolot", - "id": 408258968, - "is_bot": false, - "username": "hirrolot" - }, - "message_id": 20225, - "pinned_message": { - "chat": { - "id": -1001276785818, - "title": "teloxide dev", - "type": "supergroup", - "username": "teloxide_dev" - }, - "date": 1582134643, - "from": { - "first_name": "Hirrolot", - "id": 408258968, - "is_bot": false, - "username": "hirrolot" - }, - "message_id": 20224, - "text": "Faster than a bullet" - } - }, - "update_id": 845402291 -}"#; - - serde_json::from_str::(json).unwrap(); - } - - #[test] - fn dice_works() { - let json = r#" - { - "message": { - "chat": { - "id": -1001276785818, - "title": "bla bla bla chat", - "type": "supergroup", - "username": "teloxide_dev" - }, - "date": 1596014550, - "dice": { - "emoji": "🎲", - "value": 2 - }, - "from": { - "first_name": "Hirrolot", - "id": 408258968, - "is_bot": false, - "language_code": "en", - "username": "hirrolot" - }, - "message_id": 35410 - }, - "update_id": 573255266 -} - "#; - - serde_json::from_str::(json).unwrap(); - } -} diff --git a/src/types/user.rs b/src/types/user.rs deleted file mode 100644 index d24f5caa..00000000 --- a/src/types/user.rs +++ /dev/null @@ -1,132 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// This object represents a Telegram user or bot. -/// -/// [The official docs](https://core.telegram.org/bots/api#user). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct User { - /// Unique identifier for this user or bot. - pub id: i32, - - /// `true`, if this user is a bot. - pub is_bot: bool, - - /// User‘s or bot’s first name. - pub first_name: String, - - /// User‘s or bot’s last name. - pub last_name: Option, - - /// User‘s or bot’s username. - pub username: Option, - - /// [IETF language tag] of the user's language. - /// - /// [IETF language tag]: https://en.wikipedia.org/wiki/IETF_language_tag - pub language_code: Option, -} - -impl User { - pub fn new(id: i32, is_bot: bool, first_name: S) -> Self - where - S: Into, - { - Self { - id, - is_bot, - first_name: first_name.into(), - last_name: None, - username: None, - language_code: None, - } - } - - pub fn id(mut self, val: i32) -> Self { - self.id = val; - self - } - - #[allow(clippy::wrong_self_convention)] - pub fn is_bot(mut self, val: bool) -> Self { - self.is_bot = val; - self - } - - pub fn first_name(mut self, val: S) -> Self - where - S: Into, - { - self.first_name = val.into(); - self - } - - pub fn last_name(mut self, val: S) -> Self - where - S: Into, - { - self.last_name = Some(val.into()); - self - } - - pub fn username(mut self, val: S) -> Self - where - S: Into, - { - self.username = Some(val.into()); - self - } - - pub fn language_code(mut self, val: S) -> Self - where - S: Into, - { - self.language_code = Some(val.into()); - self - } -} - -impl User { - pub fn full_name(&self) -> String { - match &self.last_name { - Some(last_name) => (format!("{0} {1}", self.first_name, last_name)), - None => self.first_name.clone(), - } - } - - pub fn mention(&self) -> Option { - Some(format!("@{}", self.username.as_ref()?)) - } - - pub fn url(&self) -> reqwest::Url { - reqwest::Url::parse(format!("tg://user/?id={}", self.id).as_str()).unwrap() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn deserialize() { - let json = r#"{ - "id":12345, - "is_bot":false, - "first_name":"firstName", - "last_name":"lastName", - "username":"Username", - "language_code":"ru" - }"#; - let expected = User { - id: 12345, - is_bot: false, - first_name: "firstName".to_string(), - last_name: Some("lastName".to_string()), - username: Some("Username".to_string()), - language_code: Some(String::from("ru")), - }; - let actual = serde_json::from_str::(&json).unwrap(); - assert_eq!(actual, expected) - } -} diff --git a/src/types/user_profile_photos.rs b/src/types/user_profile_photos.rs deleted file mode 100644 index 26d8a934..00000000 --- a/src/types/user_profile_photos.rs +++ /dev/null @@ -1,40 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::PhotoSize; - -/// This object represent a user's profile pictures. -/// -/// [The official docs](https://core.telegram.org/bots/api#userprofilephotos). -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct UserProfilePhotos { - /// Total number of profile pictures the target user has. - pub total_count: u32, - - /// Requested profile pictures (in up to 4 sizes each). - pub photos: Vec>, -} - -impl UserProfilePhotos { - pub fn new(total_count: u32, photos: P1) -> Self - where - P1: Into>, - P2: Into>, - { - Self { total_count, photos: photos.into().into_iter().map(Into::into).collect() } - } - - pub fn total_count(mut self, val: u32) -> Self { - self.total_count = val; - self - } - - pub fn photos(mut self, val: P1) -> Self - where - P1: Into>, - P2: Into>, - { - self.photos = val.into().into_iter().map(Into::into).collect(); - self - } -} diff --git a/src/types/venue.rs b/src/types/venue.rs deleted file mode 100644 index 3a8ff38a..00000000 --- a/src/types/venue.rs +++ /dev/null @@ -1,74 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::Location; - -/// This object represents a venue. -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Venue { - /// Venue location. - pub location: Location, - - /// Name of the venue. - pub title: String, - - /// Address of the venue. - pub address: String, - - /// Foursquare identifier of the venue. - pub foursquare_id: Option, - - /// Foursquare type of the venue. (For example, - /// `arts_entertainment/default`, `arts_entertainment/aquarium` or - /// `food/icecream`.) - pub foursquare_type: Option, -} - -impl Venue { - pub fn new(location: Location, title: S1, address: S2) -> Self - where - S1: Into, - S2: Into, - { - Self { - location, - title: title.into(), - address: address.into(), - foursquare_id: None, - foursquare_type: None, - } - } - - pub fn title(mut self, val: S) -> Self - where - S: Into, - { - self.title = val.into(); - self - } - - pub fn address(mut self, val: S) -> Self - where - S: Into, - { - self.address = val.into(); - self - } - - pub fn foursquare_id(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_id = Some(val.into()); - self - } - - pub fn foursquare_type(mut self, val: S) -> Self - where - S: Into, - { - self.foursquare_type = Some(val.into()); - self - } -} diff --git a/src/types/video.rs b/src/types/video.rs deleted file mode 100644 index 84de086a..00000000 --- a/src/types/video.rs +++ /dev/null @@ -1,108 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::{MimeWrapper, PhotoSize}; - -/// This object represents a video file. -/// -/// [The official docs](https://core.telegram.org/bots/api#video). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Video { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// Video width as defined by sender. - pub width: u32, - - /// Video height as defined by sender. - pub height: u32, - - /// Duration of the video in seconds as defined by sender. - pub duration: u32, - - /// Video thumbnail. - pub thumb: Option, - - /// Mime type of a file as defined by sender. - pub mime_type: Option, - - /// File size. - pub file_size: Option, -} - -impl Video { - pub fn new( - file_id: S1, - file_unique_id: S2, - width: u32, - height: u32, - duration: u32, - ) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - width, - height, - duration, - thumb: None, - mime_type: None, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn width(mut self, val: u32) -> Self { - self.width = val; - self - } - - pub fn height(mut self, val: u32) -> Self { - self.height = val; - self - } - - pub fn duration(mut self, val: u32) -> Self { - self.duration = val; - self - } - - pub fn thumb(mut self, val: PhotoSize) -> Self { - self.thumb = Some(val); - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = Some(val); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } -} diff --git a/src/types/video_note.rs b/src/types/video_note.rs deleted file mode 100644 index 467ace0e..00000000 --- a/src/types/video_note.rs +++ /dev/null @@ -1,89 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use crate::types::PhotoSize; - -/// This object represents a [video message] (available in Telegram apps as of -/// [v.4.0]). -/// -/// [The official docs](https://core.telegram.org/bots/api#videonote). -/// -/// [video message]: https://telegram.org/blog/video-messages-and-telescope -/// [v4.0]: https://telegram.org/blog/video-messages-and-telescope -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct VideoNote { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// Video width and height (diameter of the video message) as defined by - /// sender. - pub length: u32, - - /// Duration of the video in seconds as defined by sender. - pub duration: u32, - - /// Video thumbnail. - pub thumb: Option, - - /// File size. - pub file_size: Option, -} - -impl VideoNote { - pub fn new(file_id: S1, file_unique_id: S2, length: u32, duration: u32) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - length, - duration, - thumb: None, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn length(mut self, val: u32) -> Self { - self.length = val; - self - } - - pub fn duration(mut self, val: u32) -> Self { - self.duration = val; - self - } - - pub fn thumb(mut self, val: PhotoSize) -> Self { - self.thumb = Some(val); - self - } - - pub fn file_size(mut self, val: u32) -> Self { - self.file_size = Some(val); - self - } -} diff --git a/src/types/voice.rs b/src/types/voice.rs deleted file mode 100644 index bd522cbb..00000000 --- a/src/types/voice.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::types::MimeWrapper; -use serde::{Deserialize, Serialize}; - -/// This object represents a voice note. -/// -/// [The official docs](https://core.telegram.org/bots/api#voice). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct Voice { - /// Identifier for this file. - pub file_id: String, - - /// Unique identifier for this file, which is supposed to be the same over - /// time and for different bots. Can't be used to download or reuse the - /// file. - pub file_unique_id: String, - - /// Duration of the audio in seconds as defined by sender. - pub duration: u32, - - /// MIME type of the file as defined by sender. - pub mime_type: Option, - - /// File size. - pub file_size: Option, -} - -impl Voice { - pub fn new(file_id: S1, file_unique_id: S2, duration: u32) -> Self - where - S1: Into, - S2: Into, - { - Self { - file_id: file_id.into(), - file_unique_id: file_unique_id.into(), - duration, - mime_type: None, - file_size: None, - } - } - - pub fn file_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_id = val.into(); - self - } - - pub fn file_unique_id(mut self, val: S) -> Self - where - S: Into, - { - self.file_unique_id = val.into(); - self - } - - pub fn duration(mut self, val: u32) -> Self { - self.duration = val; - self - } - - pub fn mime_type(mut self, val: MimeWrapper) -> Self { - self.mime_type = Some(val); - self - } - - pub fn file_size(mut self, val: u64) -> Self { - self.file_size = Some(val); - self - } -} diff --git a/src/types/webhook_info.rs b/src/types/webhook_info.rs deleted file mode 100644 index 782a588d..00000000 --- a/src/types/webhook_info.rs +++ /dev/null @@ -1,98 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// Contains information about the current status of a webhook. -/// -/// [The official docs](https://core.telegram.org/bots/api#webhookinfo). -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -#[non_exhaustive] -pub struct WebhookInfo { - /// Webhook URL, may be empty if webhook is not set up. - pub url: String, - - /// `true`, if a custom certificate was provided for webhook certificate - /// checks. - pub has_custom_certificate: bool, - - /// Number of updates awaiting delivery. - pub pending_update_count: u32, - - /// Unix time for the most recent error that happened when trying to - /// deliver an update via webhook. - pub last_error_date: Option, - - /// Error message in human-readable format for the most recent error that - /// happened when trying to deliver an update via webhook. - pub last_error_message: Option, - - /// Maximum allowed number of simultaneous HTTPS connections to the webhook - /// for update delivery. - pub max_connections: Option, - - /// A list of update types the bot is subscribed to. Defaults to all update - /// types. - pub allowed_updates: Option>, -} - -impl WebhookInfo { - pub fn new(url: S, has_custom_certificate: bool, pending_update_count: u32) -> Self - where - S: Into, - { - Self { - url: url.into(), - has_custom_certificate, - pending_update_count, - last_error_date: None, - - last_error_message: None, - max_connections: None, - allowed_updates: None, - } - } - - pub fn url(mut self, val: S) -> Self - where - S: Into, - { - self.url = val.into(); - self - } - - pub fn has_custom_certificate(mut self, val: bool) -> Self { - self.has_custom_certificate = val; - self - } - - pub fn pending_update_count(mut self, val: u32) -> Self { - self.pending_update_count = val; - self - } - - pub fn last_error_date(mut self, val: u64) -> Self { - self.last_error_date = Some(val); - self - } - - pub fn last_error_message(mut self, val: S) -> Self - where - S: Into, - { - self.last_error_message = Some(val.into()); - self - } - - pub fn max_connections(mut self, val: u32) -> Self { - self.max_connections = Some(val); - self - } - - pub fn allowed_updates(mut self, val: A) -> Self - where - A: Into>, - S: Into, - { - self.allowed_updates = Some(val.into().into_iter().map(Into::into).collect()); - self - } -} diff --git a/src/utils/client_from_env.rs b/src/utils/client_from_env.rs deleted file mode 100644 index 8857e387..00000000 --- a/src/utils/client_from_env.rs +++ /dev/null @@ -1,26 +0,0 @@ -use crate::bot::{sound_bot, TELOXIDE_PROXY}; - -/// Constructs a client from the `TELOXIDE_PROXY` environmental variable. -/// -/// This function passes the value of `TELOXIDE_PROXY` into -/// [`reqwest::Proxy::all`], if it exists, otherwise returns the default -/// client. -/// -/// # Note -/// The created client will have safe settings, meaning that it will be able to -/// work in long time durations, see the [issue 223]. -/// -/// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all -/// [issue 223]: https://github.com/teloxide/teloxide/issues/223 -pub fn client_from_env() -> reqwest::Client { - use reqwest::Proxy; - - let builder = sound_bot(); - - match std::env::var(TELOXIDE_PROXY).ok() { - Some(proxy) => builder.proxy(Proxy::all(&proxy).expect("creating reqwest::Proxy")), - None => builder, - } - .build() - .expect("creating reqwest::Client") -} diff --git a/src/utils/html.rs b/src/utils/html.rs index 71c7bec9..cf22acc4 100644 --- a/src/utils/html.rs +++ b/src/utils/html.rs @@ -1,8 +1,8 @@ //! Utils for working with the [HTML message style][spec]. //! //! [spec]: https://core.telegram.org/bots/api#html-style -use crate::types::User; -use std::string::String; + +use teloxide_core::types::User; /// Applies the bold font style to the string. /// diff --git a/src/utils/markdown.rs b/src/utils/markdown.rs index f96236d6..f96fafaa 100644 --- a/src/utils/markdown.rs +++ b/src/utils/markdown.rs @@ -1,8 +1,8 @@ //! Utils for working with the [Markdown V2 message style][spec]. //! //! [spec]: https://core.telegram.org/bots/api#markdownv2-style -use crate::types::User; -use std::string::String; + +use teloxide_core::types::User; /// Applies the bold font style to the string. /// @@ -131,6 +131,7 @@ pub fn user_mention_or_link(user: &User) -> String { #[cfg(test)] mod tests { use super::*; + use teloxide_core::types::User; #[test] fn test_bold() { diff --git a/src/utils/mod.rs b/src/utils/mod.rs index e20a7a81..e34561ae 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,12 +1,11 @@ //! Some useful utilities. -mod client_from_env; pub mod command; pub mod html; pub mod markdown; mod up_state; -pub use client_from_env::client_from_env; +pub use teloxide_core::net::client_from_env; #[cfg(feature = "frunk")] // FIXME(waffle): use `docsrs` here when issue with combine is resolved