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<String> + ...` 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/<token>`. 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<U>(&self, url: U) -> SetWebhook
-    where
-        U: Into<String>,
-    {
-        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<C, T>(&self, chat_id: C, text: T) -> SendMessage
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<C, F>(
-        &self,
-        chat_id: C,
-        from_chat_id: F,
-        message_id: i32,
-    ) -> ForwardMessage
-    where
-        C: Into<ChatId>,
-        F: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, photo: InputFile) -> SendPhoto
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, audio: InputFile) -> SendAudio
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, document: InputFile) -> SendDocument
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, video: InputFile) -> SendVideo
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, animation: InputFile) -> SendAnimation
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, voice: InputFile) -> SendVoice
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, video_note: InputFile) -> SendVideoNote
-    where
-        C: Into<ChatId>,
-    {
-        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<C, M>(&self, chat_id: C, media: M) -> SendMediaGroup
-    where
-        C: Into<ChatId>,
-        M: Into<Vec<InputMedia>>,
-    {
-        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<C>(&self, chat_id: C, latitude: f32, longitude: f32) -> SendLocation
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        message_id: i32,
-        latitude: f32,
-        longitude: f32,
-    ) -> EditMessageLiveLocation
-    where
-        C: Into<ChatId>,
-    {
-        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<I>(
-        &self,
-        inline_message_id: I,
-        latitude: f32,
-        longitude: f32,
-    ) -> EditInlineMessageLiveLocation
-    where
-        I: Into<String>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        message_id: i32,
-    ) -> StopMessageLiveLocation
-    where
-        C: Into<ChatId>,
-    {
-        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<I>(
-        &self,
-        inline_message_id: I,
-    ) -> StopInlineMessageLiveLocation
-    where
-        I: Into<String>,
-    {
-        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<C, T, A>(
-        &self,
-        chat_id: C,
-        latitude: f32,
-        longitude: f32,
-        title: T,
-        address: A,
-    ) -> SendVenue
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-        A: Into<String>,
-    {
-        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<C, P, F>(&self, chat_id: C, phone_number: P, first_name: F) -> SendContact
-    where
-        C: Into<ChatId>,
-        P: Into<String>,
-        F: Into<String>,
-    {
-        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<C, Q, O>(&self, chat_id: C, question: Q, options: O) -> SendPoll
-    where
-        C: Into<ChatId>,
-        Q: Into<String>,
-        O: Into<Vec<String>>,
-    {
-        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<C>(&self, chat_id: C, action: SendChatActionKind) -> SendChatAction
-    where
-        C: Into<ChatId>,
-    {
-        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<token>/<file_path>`, where `<file_path>`
-    /// is taken from the response. It is guaranteed that the link will be valid
-    /// for at least `1` hour. When the link expires, a new one can be requested
-    /// by calling [`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<F>(&self, file_id: F) -> GetFile
-    where
-        F: Into<String>,
-    {
-        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<C>(&self, chat_id: C, user_id: i32) -> KickChatMember
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, user_id: i32) -> UnbanChatMember
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        user_id: i32,
-        permissions: ChatPermissions,
-    ) -> RestrictChatMember
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, user_id: i32) -> PromoteChatMember
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        permissions: ChatPermissions,
-    ) -> SetChatPermissions
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> ExportChatInviteLink
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, photo: InputFile) -> SetChatPhoto
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> DeleteChatPhoto
-    where
-        C: Into<ChatId>,
-    {
-        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<C, T>(&self, chat_id: C, title: T) -> SetChatTitle
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<C>(&self, chat_id: C) -> SetChatDescription
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, message_id: i32) -> PinChatMessage
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> UnpinChatMessage
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> LeaveChat
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> GetChat
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> GetChatAdministrators
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C) -> GetChatMembersCount
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, user_id: i32) -> GetChatMember
-    where
-        C: Into<ChatId>,
-    {
-        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<C, S>(&self, chat_id: C, sticker_set_name: S) -> SetChatStickerSet
-    where
-        C: Into<ChatId>,
-        S: Into<String>,
-    {
-        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<C>(&self, chat_id: C) -> DeleteChatStickerSet
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, callback_query_id: C) -> AnswerCallbackQuery
-    where
-        C: Into<String>,
-    {
-        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<C, T>(&self, chat_id: C, message_id: i32, text: T) -> EditMessageText
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<I, T>(
-        &self,
-        inline_message_id: I,
-        text: T,
-    ) -> EditInlineMessageText
-    where
-        I: Into<String>,
-        T: Into<String>,
-    {
-        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<C>(&self, chat_id: C, message_id: i32) -> EditMessageCaption
-    where
-        C: Into<ChatId>,
-    {
-        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<I>(&self, inline_message_id: I) -> EditInlineMessageCaption
-    where
-        I: Into<String>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        message_id: i32,
-        media: InputMedia,
-    ) -> EditMessageMedia
-    where
-        C: Into<ChatId>,
-    {
-        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<I>(
-        &self,
-        inline_message_id: I,
-        media: InputMedia,
-    ) -> EditInlineMessageMedia
-    where
-        I: Into<String>,
-    {
-        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<C>(
-        &self,
-        chat_id: C,
-        message_id: i32,
-    ) -> EditMessageReplyMarkup
-    where
-        C: Into<ChatId>,
-    {
-        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<I>(
-        &self,
-        inline_message_id: I,
-    ) -> EditInlineMessageReplyMarkup
-    where
-        I: Into<String>,
-    {
-        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<C>(&self, chat_id: C, message_id: i32) -> StopPoll
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, message_id: i32) -> DeleteMessage
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, chat_id: C, sticker: InputFile) -> SendSticker
-    where
-        C: Into<ChatId>,
-    {
-        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<N>(&self, name: N) -> GetStickerSet
-    where
-        N: Into<String>,
-    {
-        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_<bot username>`. `<bot_username>` is case insensitive. 1-64
-    /// characters.
-    ///   - `title`: Sticker set title, 1-64 characters.
-    pub fn create_new_sticker_set<N, T, E>(
-        &self,
-        user_id: i32,
-        name: N,
-        title: T,
-        sticker_type: StickerType,
-        emojis: E,
-    ) -> CreateNewStickerSet
-    where
-        N: Into<String>,
-        T: Into<String>,
-        E: Into<String>,
-    {
-        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<N, E>(
-        &self,
-        user_id: i32,
-        name: N,
-        sticker_type: StickerType,
-        emojis: E,
-    ) -> AddStickerToSet
-    where
-        N: Into<String>,
-        E: Into<String>,
-    {
-        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<S>(
-        &self,
-        sticker: S,
-        position: i32,
-    ) -> SetStickerPositionInSet
-    where
-        S: Into<String>,
-    {
-        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<S>(&self, sticker: S) -> DeleteStickerFromSet
-    where
-        S: Into<String>,
-    {
-        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<I, R>(&self, inline_query_id: I, results: R) -> AnswerInlineQuery
-    where
-        I: Into<String>,
-        R: Into<Vec<InlineQueryResult>>,
-    {
-        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<T, D, Pl, Pt, S, C, Pr>(
-        &self,
-        chat_id: i32,
-        title: T,
-        description: D,
-        payload: Pl,
-        provider_token: Pt,
-        start_parameter: S,
-        currency: C,
-        prices: Pr,
-    ) -> SendInvoice
-    where
-        T: Into<String>,
-        D: Into<String>,
-        Pl: Into<String>,
-        Pt: Into<String>,
-        S: Into<String>,
-        C: Into<String>,
-        Pr: Into<Vec<LabeledPrice>>,
-    {
-        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<S>(&self, shipping_query_id: S, ok: bool) -> AnswerShippingQuery
-    where
-        S: Into<String>,
-    {
-        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<P>(
-        &self,
-        pre_checkout_query_id: P,
-        ok: bool,
-    ) -> AnswerPreCheckoutQuery
-    where
-        P: Into<String>,
-    {
-        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<G>(&self, chat_id: i32, game_short_name: G) -> SendGame
-    where
-        G: Into<String>,
-    {
-        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<T>(&self, target: T, user_id: i32, score: i32) -> SetGameScore
-    where
-        T: Into<TargetMessage>,
-    {
-        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<T>(&self, target: T, user_id: i32) -> GetGameHighScores
-    where
-        T: Into<TargetMessage>,
-    {
-        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<C, CT>(
-        &self,
-        chat_id: C,
-        user_id: i32,
-        custom_title: CT,
-    ) -> SetChatAdministratorCustomTitle
-    where
-        C: Into<ChatId>,
-        CT: Into<String>,
-    {
-        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<C>(&self, chat_id: C) -> SendDice
-    where
-        C: Into<ChatId>,
-    {
-        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<C>(&self, commands: C) -> SetMyCommands
-    where
-        C: Into<Vec<BotCommand>>,
-    {
-        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<S>(&self, name: S, user_id: i32) -> SetStickerSetThumb
-    where
-        S: Into<String>,
-    {
-        SetStickerSetThumb::new(self.clone(), name, user_id)
-    }
-
-    fn with_default_parse_mode_if_specified<Builder>(
-        &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<dyn std::error::Error>> {
-    /// 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<D>(
-        &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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>
-    #[cfg_attr(all(teloxide_docsrs, feature = "nightly"), doc(cfg(feature = "unstable-stream")))]
-    pub async fn download_file_stream(
-        &self,
-        path: &str,
-    ) -> Result<impl Stream<Item = Result<Bytes, reqwest::Error>>, 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<str>,
-    client: Client,
-    parse_mode: Option<ParseMode>,
-}
-
-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<S>(token: S) -> Self
-    where
-        S: Into<String>,
-    {
-        #[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<S>(token: S, client: Client) -> Self
-    where
-        S: Into<String>,
-    {
-        Self {
-            token: Into::<Arc<str>>::into(Into::<String>::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<String>,
-    client: Option<Client>,
-    parse_mode: Option<ParseMode>,
-}
-
-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<S>(mut self, token: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<D, S, H, Upd> {
+pub struct DialogueDispatcher<R, D, S, H, Upd> {
     storage: Arc<S>,
     handler: Arc<H>,
     _phantom: PhantomData<Mutex<D>>,
@@ -34,12 +35,12 @@ pub struct DialogueDispatcher<D, S, H, Upd> {
     /// 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<Map<i64, mpsc::UnboundedSender<UpdateWithCx<Upd>>>>,
+    senders: Arc<Map<i64, mpsc::UnboundedSender<UpdateWithCx<R, Upd>>>>,
 }
 
-impl<D, H, Upd> DialogueDispatcher<D, InMemStorage<D>, H, Upd>
+impl<R, D, H, Upd> DialogueDispatcher<R, D, InMemStorage<D>, H, Upd>
 where
-    H: DialogueDispatcherHandler<Upd, D, Infallible> + Send + Sync + 'static,
+    H: DialogueDispatcherHandler<R, Upd, D, Infallible> + Send + Sync + 'static,
     Upd: GetChatId + Send + 'static,
     D: Default + Send + 'static,
 {
@@ -58,9 +59,9 @@ where
     }
 }
 
-impl<D, S, H, Upd> DialogueDispatcher<D, S, H, Upd>
+impl<R, D, S, H, Upd> DialogueDispatcher<R, D, S, H, Upd>
 where
-    H: DialogueDispatcherHandler<Upd, D, S::Error> + Send + Sync + 'static,
+    H: DialogueDispatcherHandler<R, Upd, D, S::Error> + Send + Sync + 'static,
     Upd: GetChatId + Send + 'static,
     D: Default + Send + 'static,
     S: Storage<D> + Send + Sync + 'static,
@@ -78,14 +79,17 @@ where
     }
 
     #[must_use]
-    fn new_tx(&self) -> mpsc::UnboundedSender<UpdateWithCx<Upd>> {
+    fn new_tx(&self) -> mpsc::UnboundedSender<UpdateWithCx<R, Upd>>
+    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<Upd>| {
+        tokio::spawn(UnboundedReceiverStream::new(rx).for_each(move |cx: UpdateWithCx<R, Upd>| {
             let storage = Arc::clone(&storage);
             let handler = Arc::clone(&handler);
             let senders = Arc::clone(&senders);
@@ -124,17 +128,21 @@ where
     }
 }
 
-impl<D, S, H, Upd> DispatcherHandler<Upd> for DialogueDispatcher<D, S, H, Upd>
+impl<R, D, S, H, Upd> DispatcherHandler<R, Upd> for DialogueDispatcher<R, D, S, H, Upd>
 where
-    H: DialogueDispatcherHandler<Upd, D, S::Error> + Send + Sync + 'static,
+    H: DialogueDispatcherHandler<R, Upd, D, S::Error> + Send + Sync + 'static,
     Upd: GetChatId + Send + 'static,
     D: Default + Send + 'static,
     S: Storage<D> + Send + Sync + 'static,
     S::Error: Send + 'static,
+    R: Requester + Send,
 {
-    fn handle(self, updates: mpsc::UnboundedReceiver<UpdateWithCx<Upd>>) -> BoxFuture<'static, ()>
+    fn handle(
+        self,
+        updates: mpsc::UnboundedReceiver<UpdateWithCx<R, Upd>>,
+    ) -> BoxFuture<'static, ()>
     where
-        UpdateWithCx<Upd>: 'static,
+        UpdateWithCx<R, Upd>: '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<Upd, D, E> {
+pub trait DialogueDispatcherHandler<R, Upd, D, E> {
     #[must_use]
     fn handle(
         self: Arc<Self>,
-        cx: DialogueWithCx<Upd, D, E>,
+        cx: DialogueWithCx<R, Upd, D, E>,
     ) -> BoxFuture<'static, DialogueStage<D>>
     where
-        DialogueWithCx<Upd, D, E>: Send + 'static;
+        DialogueWithCx<R, Upd, D, E>: Send + 'static,
+        R: Send,
+        Upd: Send,
+        D: Send,
+        E: Send;
 }
 
-impl<Upd, D, E, F, Fut> DialogueDispatcherHandler<Upd, D, E> for F
+impl<R, Upd, D, E, F, Fut> DialogueDispatcherHandler<R, Upd, D, E> for F
 where
-    F: Fn(DialogueWithCx<Upd, D, E>) -> Fut + Send + Sync + 'static,
+    F: Fn(DialogueWithCx<R, Upd, D, E>) -> Fut + Send + Sync + 'static,
     Fut: Future<Output = DialogueStage<D>> + Send + 'static,
 {
-    fn handle(self: Arc<Self>, cx: DialogueWithCx<Upd, D, E>) -> BoxFuture<'static, Fut::Output>
+    fn handle(self: Arc<Self>, cx: DialogueWithCx<R, Upd, D, E>) -> BoxFuture<'static, Fut::Output>
     where
-        DialogueWithCx<Upd, D, E>: Send + 'static,
+        DialogueWithCx<R, Upd, D, E>: 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<Upd, D, E> {
-    pub cx: UpdateWithCx<Upd>,
+pub struct DialogueWithCx<R, Upd, D, E> {
+    pub cx: UpdateWithCx<R, Upd>,
     pub dialogue: Result<D, E>,
 }
 
-impl<Upd, D, E> DialogueWithCx<Upd, D, E> {
+impl<Upd, R, D, E> DialogueWithCx<R, Upd, D, E> {
     /// Creates a new instance with the provided fields.
-    pub fn new(cx: UpdateWithCx<Upd>, dialogue: D) -> Self {
+    pub fn new(cx: UpdateWithCx<R, Upd>, dialogue: D) -> Self {
         Self { cx, dialogue: Ok(dialogue) }
     }
 }
 
-impl<Upd, D, E> GetChatId for DialogueWithCx<Upd, D, E>
+impl<Upd, R, D, E> GetChatId for DialogueWithCx<R, Upd, D, E>
 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<u8>, Option<Vec<u8>>>(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<u8>,
 }
 
@@ -123,7 +123,7 @@ async fn get_dialogue(
     chat_id: i64,
 ) -> Result<Option<Box<Vec<u8>>>, 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<Self::Requester>,
         aux: Self::Aux,
     ) -> BoxFuture<'static, TransitionOut<Self, Self::Error>>;
 }
@@ -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<Self::Requester>,
         aux: Self::Aux,
     ) -> BoxFuture<'static, TransitionOut<Self::Dialogue, Self::Error>>;
 }
@@ -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<D, E> SubtransitionOutputType for TransitionOut<D, E> {
 }
 
 /// An input passed into a FSM (sub)transition function.
-pub type TransitionIn = UpdateWithCx<Message>;
+pub type TransitionIn<R> = UpdateWithCx<R, Message>;
 
 /// A type returned from a FSM (sub)transition function.
 pub type TransitionOut<D, E = crate::RequestError> = Result<DialogueStage<D>, 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<Upd> = Option<mpsc::UnboundedSender<UpdateWithCx<Upd>>>;
+type Tx<Upd, R> = Option<mpsc::UnboundedSender<UpdateWithCx<Upd, R>>>;
 
 #[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<Upd>, update: Upd, variant: &'static str)
+fn send<'a, R, Upd>(requester: &'a R, tx: &'a Tx<R, Upd>, 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<R> {
+    requester: R,
 
-    messages_queue: Tx<Message>,
-    edited_messages_queue: Tx<Message>,
-    channel_posts_queue: Tx<Message>,
-    edited_channel_posts_queue: Tx<Message>,
-    inline_queries_queue: Tx<InlineQuery>,
-    chosen_inline_results_queue: Tx<ChosenInlineResult>,
-    callback_queries_queue: Tx<CallbackQuery>,
-    shipping_queries_queue: Tx<ShippingQuery>,
-    pre_checkout_queries_queue: Tx<PreCheckoutQuery>,
-    polls_queue: Tx<Poll>,
-    poll_answers_queue: Tx<PollAnswer>,
+    messages_queue: Tx<R, Message>,
+    edited_messages_queue: Tx<R, Message>,
+    channel_posts_queue: Tx<R, Message>,
+    edited_channel_posts_queue: Tx<R, Message>,
+    inline_queries_queue: Tx<R, InlineQuery>,
+    chosen_inline_results_queue: Tx<R, ChosenInlineResult>,
+    callback_queries_queue: Tx<R, CallbackQuery>,
+    shipping_queries_queue: Tx<R, ShippingQuery>,
+    pre_checkout_queries_queue: Tx<R, PreCheckoutQuery>,
+    polls_queue: Tx<R, Poll>,
+    poll_answers_queue: Tx<R, PollAnswer>,
 }
 
-impl Dispatcher {
-    /// Constructs a new dispatcher with the specified `bot`.
+impl<R> Dispatcher<R>
+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<H, Upd>(&self, h: H) -> Tx<Upd>
+    #[allow(clippy::unnecessary_wraps)]
+    fn new_tx<H, Upd>(&self, h: H) -> Tx<R, Upd>
     where
-        H: DispatcherHandler<Upd> + Send + 'static,
+        H: DispatcherHandler<R, Upd> + 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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<Message> + 'static + Send,
+        H: DispatcherHandler<R, Message> + 'static + Send,
     {
         self.messages_queue = self.new_tx(h);
         self
@@ -106,7 +114,7 @@ impl Dispatcher {
     #[must_use]
     pub fn edited_messages_handler<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<Message> + 'static + Send,
+        H: DispatcherHandler<R, Message> + 'static + Send,
     {
         self.edited_messages_queue = self.new_tx(h);
         self
@@ -115,7 +123,7 @@ impl Dispatcher {
     #[must_use]
     pub fn channel_posts_handler<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<Message> + 'static + Send,
+        H: DispatcherHandler<R, Message> + '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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<Message> + 'static + Send,
+        H: DispatcherHandler<R, Message> + '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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<InlineQuery> + 'static + Send,
+        H: DispatcherHandler<R, InlineQuery> + '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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<ChosenInlineResult> + 'static + Send,
+        H: DispatcherHandler<R, ChosenInlineResult> + '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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<CallbackQuery> + 'static + Send,
+        H: DispatcherHandler<R, CallbackQuery> + 'static + Send,
     {
         self.callback_queries_queue = self.new_tx(h);
         self
@@ -160,7 +168,7 @@ impl Dispatcher {
     #[must_use]
     pub fn shipping_queries_handler<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<ShippingQuery> + 'static + Send,
+        H: DispatcherHandler<R, ShippingQuery> + '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<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<PreCheckoutQuery> + 'static + Send,
+        H: DispatcherHandler<R, PreCheckoutQuery> + 'static + Send,
     {
         self.pre_checkout_queries_queue = self.new_tx(h);
         self
@@ -178,7 +186,7 @@ impl Dispatcher {
     #[must_use]
     pub fn polls_handler<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<Poll> + 'static + Send,
+        H: DispatcherHandler<R, Poll> + 'static + Send,
     {
         self.polls_queue = self.new_tx(h);
         self
@@ -187,7 +195,7 @@ impl Dispatcher {
     #[must_use]
     pub fn poll_answers_handler<H>(mut self, h: H) -> Self
     where
-        H: DispatcherHandler<PollAnswer> + 'static + Send,
+        H: DispatcherHandler<R, PollAnswer> + '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,
+        <R as Requester>::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<ListenerE> + 'a,
         Eh: ErrorHandler<ListenerE> + '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<Upd> {
+pub trait DispatcherHandler<R, Upd> {
     #[must_use]
-    fn handle(self, updates: DispatcherHandlerRx<Upd>) -> BoxFuture<'static, ()>
+    fn handle(self, updates: DispatcherHandlerRx<R, Upd>) -> BoxFuture<'static, ()>
     where
-        UpdateWithCx<Upd>: Send + 'static;
+        UpdateWithCx<R, Upd>: Send + 'static;
 }
 
-impl<Upd, F, Fut> DispatcherHandler<Upd> for F
+impl<R, Upd, F, Fut> DispatcherHandler<R, Upd> for F
 where
-    F: FnOnce(DispatcherHandlerRx<Upd>) -> Fut + Send + 'static,
+    F: FnOnce(DispatcherHandlerRx<R, Upd>) -> Fut + Send + 'static,
     Fut: Future<Output = ()> + Send + 'static,
 {
-    fn handle(self, updates: DispatcherHandlerRx<Upd>) -> BoxFuture<'static, ()>
+    fn handle(self, updates: DispatcherHandlerRx<R, Upd>) -> BoxFuture<'static, ()>
     where
-        UpdateWithCx<Upd>: Send + 'static,
+        UpdateWithCx<R, Upd>: 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<R> {
     /// Extracts only text messages from this stream of arbitrary messages.
-    fn text_messages(self) -> BoxStream<'static, (UpdateWithCx<Message>, String)>
+    fn text_messages(self) -> BoxStream<'static, (UpdateWithCx<R, Message>, String)>
     where
-        Self: Stream<Item = UpdateWithCx<Message>>;
+        Self: Stream<Item = UpdateWithCx<R, Message>>,
+        R: Send + 'static;
 
     /// Extracts only commands with their arguments from this stream of
     /// arbitrary messages.
-    fn commands<C, N>(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx<Message>, C)>
+    fn commands<C, N>(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx<R, Message>, C)>
     where
-        Self: Stream<Item = UpdateWithCx<Message>>,
+        Self: Stream<Item = UpdateWithCx<R, Message>>,
         C: BotCommand,
-        N: Into<String> + Send;
+        N: Into<String> + Send,
+        R: Send + 'static;
 }
 
-impl<T> DispatcherHandlerRxExt for T
+impl<R, T> DispatcherHandlerRxExt<R> for T
 where
     T: Send + 'static,
 {
-    fn text_messages(self) -> BoxStream<'static, (UpdateWithCx<Message>, String)>
+    fn text_messages(self) -> BoxStream<'static, (UpdateWithCx<R, Message>, String)>
     where
-        Self: Stream<Item = UpdateWithCx<Message>>,
+        Self: Stream<Item = UpdateWithCx<R, Message>>,
+        R: Send + 'static,
     {
         self.filter_map(|cx| async move { cx.update.text_owned().map(|text| (cx, text)) }).boxed()
     }
 
-    fn commands<C, N>(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx<Message>, C)>
+    fn commands<C, N>(self, bot_name: N) -> BoxStream<'static, (UpdateWithCx<R, Message>, C)>
     where
-        Self: Stream<Item = UpdateWithCx<Message>>,
+        Self: Stream<Item = UpdateWithCx<R, Message>>,
         C: BotCommand,
         N: Into<String> + 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<Upd> = UnboundedReceiver<UpdateWithCx<Upd>>;
+pub type DispatcherHandlerRx<R, Upd> = UnboundedReceiver<UpdateWithCx<R, Upd>>;
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<Cmd, H, Fut, HandlerE, N>(bot: Bot, bot_name: N, handler: H)
+pub async fn commands_repl<R, Cmd, H, Fut, HandlerE, N>(requester: R, bot_name: N, handler: H)
 where
     Cmd: BotCommand + Send + 'static,
-    H: Fn(UpdateWithCx<Message>, Cmd) -> Fut + Send + Sync + 'static,
+    H: Fn(UpdateWithCx<R, Message>, Cmd) -> Fut + Send + Sync + 'static,
     Fut: Future<Output = Result<(), HandlerE>> + Send + 'static,
     Result<(), HandlerE>: OnError<HandlerE>,
     HandlerE: Debug + Send,
     N: Into<String> + Send + 'static,
+    R: Requester + Send + Clone + 'static,
+    <R as Requester>::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<Message>, Cmd) -> Fut + Send + Sync + 'static,
+    H: Fn(UpdateWithCx<R, Message>, Cmd) -> Fut + Send + Sync + 'static,
     Fut: Future<Output = Result<(), HandlerE>> + Send + 'static,
     L: UpdateListener<ListenerE> + Send + 'a,
     ListenerE: Debug + Send + 'a,
     Result<(), HandlerE>: OnError<HandlerE>,
     HandlerE: Debug + Send,
     N: Into<String> + Send + 'static,
+    R: Requester + Clone + Send + 'static,
 {
     let handler = Arc::new(handler);
 
-    Dispatcher::new(bot)
-        .messages_handler(move |rx: DispatcherHandlerRx<Message>| {
+    Dispatcher::<R>::new(requester)
+        .messages_handler(move |rx: DispatcherHandlerRx<R, Message>| {
             UnboundedReceiverStream::new(rx).commands::<Cmd, N>(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<Message>, D) -> Fut + Send + Sync + 'static,
+    H: Fn(UpdateWithCx<R, Message>, D) -> Fut + Send + Sync + 'static,
     D: Default + Send + 'static,
     Fut: Future<Output = DialogueStage<D>> + Send + 'static,
+    R: Requester + Send + Clone + 'static,
+    <R as Requester>::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<Message>, D) -> Fut + Send + Sync + 'static,
+    H: Fn(UpdateWithCx<R, Message>, D) -> Fut + Send + Sync + 'static,
     D: Default + Send + 'static,
     Fut: Future<Output = DialogueStage<D>> + Send + 'static,
     L: UpdateListener<ListenerE> + 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<Message, D, Infallible>| {
+            move |DialogueWithCx { cx, dialogue }: DialogueWithCx<R, Message, D, Infallible>| {
                 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<H, Fut, E>(bot: Bot, handler: H)
+pub async fn repl<R, H, Fut, E>(requester: R, handler: H)
 where
-    H: Fn(UpdateWithCx<Message>) -> Fut + Send + Sync + 'static,
+    H: Fn(UpdateWithCx<R, Message>) -> Fut + Send + Sync + 'static,
     Fut: Future<Output = Result<(), E>> + Send + 'static,
     Result<(), E>: OnError<E>,
     E: Debug + Send,
+    R: Requester + Send + Clone + 'static,
+    <R as Requester>::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<Message>) -> 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<R, Message>) -> Fut + Send + Sync + 'static,
     Fut: Future<Output = Result<(), E>> + Send + 'static,
     L: UpdateListener<ListenerE> + Send + 'a,
     ListenerE: Debug,
     Result<(), E>: OnError<E>,
     E: Debug + Send,
+    R: Requester + Clone + Send + 'static,
 {
     let handler = Arc::new(handler);
 
-    Dispatcher::new(bot)
-        .messages_handler(|rx: DispatcherHandlerRx<Message>| {
+    Dispatcher::new(requester)
+        .messages_handler(|rx: DispatcherHandlerRx<R, Message>| {
             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<E>: Stream<Item = Result<Update, E>> {
@@ -123,8 +120,12 @@ impl<S, E> UpdateListener<E> for S where S: Stream<Item = Result<Update, E>> {}
 /// Returns a long polling update listener with `timeout` of 10 seconds.
 ///
 /// See also: [`polling`](polling).
-pub fn polling_default(bot: Bot) -> impl UpdateListener<RequestError> {
-    polling(bot, Some(Duration::from_secs(10)), None, None)
+pub fn polling_default<R, E>(requester: R) -> impl UpdateListener<E>
+where
+    R: Requester<Err = E>,
+    <R as 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<RequestError> {
 /// See also: [`polling_default`](polling_default).
 ///
 /// [`GetUpdates`]: crate::requests::GetUpdates
-pub fn polling(
-    bot: Bot,
+pub fn polling<R, E>(
+    requester: R,
     timeout: Option<Duration>,
     limit: Option<u8>,
     allowed_updates: Option<Vec<AllowedUpdate>>,
-) -> impl UpdateListener<RequestError> {
+) -> impl UpdateListener<E>
+where
+    R: Requester<Err = E>,
+    <R as 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<Upd> {
-    pub bot: Bot,
+pub struct UpdateWithCx<R, Upd> {
+    pub requester: R,
     pub update: Upd,
 }
 
-impl<Upd> GetChatId for UpdateWithCx<Upd>
+impl<Upd, R> GetChatId for UpdateWithCx<R, Upd>
 where
     Upd: GetChatId,
 {
@@ -31,121 +26,136 @@ where
     }
 }
 
-impl UpdateWithCx<Message> {
+#[doc(hidden)]
+// Now it is used only inside `#[teloxide(subtransition)]` for type inference.
+pub trait UpdateWithCxRequesterType {
+    type Requester;
+}
+
+impl<R, Upd> UpdateWithCxRequesterType for UpdateWithCx<R, Upd> {
+    type Requester = R;
+}
+
+impl<R> UpdateWithCx<R, Message>
+where
+    R: Requester,
+{
     /// A shortcut for `.answer(text).send().await`.
-    pub async fn answer_str<T>(&self, text: T) -> ResponseResult<Message>
+    #[deprecated(note = "Use .answer(text).await instead")]
+    pub async fn answer_str<T>(&self, text: T) -> Result<Message, R::Err>
     where
         T: Into<String>,
+        R::SendMessage: std::future::Future,
     {
         self.answer(text).send().await
     }
 
-    pub fn answer<T>(&self, text: T) -> SendMessage
+    pub fn answer<T>(&self, text: T) -> R::SendMessage
     where
         T: Into<String>,
     {
-        self.bot.send_message(self.chat_id(), text)
+        self.requester.send_message(self.chat_id(), text)
     }
 
-    pub fn reply_to<T>(&self, text: T) -> SendMessage
+    pub fn reply_to<T>(&self, text: T) -> R::SendMessage
     where
         T: Into<String>,
     {
-        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<T>(&self, media_group: T) -> SendMediaGroup
+    pub fn answer_media_group<T>(&self, media_group: T) -> R::SendMediaGroup
     where
-        T: Into<Vec<InputMedia>>,
+        T: IntoIterator<Item = InputMedia>,
     {
-        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<T, U>(
         &self,
-        latitude: f32,
-        longitude: f32,
+        latitude: f64,
+        longitude: f64,
         title: T,
         address: U,
-    ) -> SendVenue
+    ) -> R::SendVenue
     where
         T: Into<String>,
         U: Into<String>,
     {
-        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<T, U>(&self, phone_number: T, first_name: U) -> SendContact
+    pub fn answer_contact<T, U>(&self, phone_number: T, first_name: U) -> R::SendContact
     where
         T: Into<String>,
         U: Into<String>,
     {
-        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<T>(&self, chat_id: T) -> ForwardMessage
+    pub fn forward_to<T>(&self, chat_id: T) -> R::ForwardMessage
     where
         T: Into<ChatId>,
     {
-        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<T>(&self, text: T) -> EditMessageText
+    pub fn edit_message_text<T>(&self, text: T) -> R::EditMessageText
     where
         T: Into<String>,
     {
-        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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>
 #![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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>
 #[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<T>(val: T) -> ResponseResult<T> {
+    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<D>(
-    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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>
-#[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<impl Stream<Item = reqwest::Result<Bytes>>, 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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>
-#[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<T>(
-    client: &Client,
-    token: &str,
-    method_name: &str,
-    params: Form,
-) -> ResponseResult<T>
-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<T, P>(
-    client: &Client,
-    token: &str,
-    method_name: &str,
-    params: &P,
-) -> ResponseResult<T>
-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<T>(response: Response) -> ResponseResult<T>
-where
-    T: DeserializeOwned,
-{
-    if response.status().is_server_error() {
-        tokio::time::sleep(DELAY_ON_SERVER_ERROR).await;
-    }
-
-    serde_json::from_str::<TelegramResponse<T>>(
-        &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<R> {
-    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<ResponseParameters>,
-    },
-}
-
-impl<R> Into<ResponseResult<R>> for TelegramResponse<R> {
-    fn into(self) -> Result<R, RequestError> {
-        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::<TelegramResponse<Update>>(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<MaskPosition>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for AddStickerToSet {
-    type Output = True;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<True>> {
-        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<N, E>(
-        bot: Bot,
-        user_id: i32,
-        name: N,
-        sticker_type: StickerType,
-        emojis: E,
-    ) -> Self
-    where
-        N: Into<String>,
-        E: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String>,
-    show_alert: Option<bool>,
-    url: Option<String>,
-    cache_time: Option<i32>,
-}
-
-#[async_trait::async_trait]
-impl Request for AnswerCallbackQuery {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "answerCallbackQuery", &self).await
-    }
-}
-
-impl AnswerCallbackQuery {
-    pub(crate) fn new<C>(bot: Bot, callback_query_id: C) -> Self
-    where
-        C: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineQueryResult>,
-    cache_time: Option<i32>,
-    is_personal: Option<bool>,
-    next_offset: Option<String>,
-    switch_pm_text: Option<String>,
-    switch_pm_parameter: Option<String>,
-}
-
-#[async_trait::async_trait]
-impl Request for AnswerInlineQuery {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "answerInlineQuery", &self).await
-    }
-}
-
-impl AnswerInlineQuery {
-    pub(crate) fn new<I, R>(bot: Bot, inline_query_id: I, results: R) -> Self
-    where
-        I: Into<String>,
-        R: Into<Vec<InlineQueryResult>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.inline_query_id = val.into();
-        self
-    }
-
-    /// A JSON-serialized array of results for the inline query.
-    pub fn results<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<InlineQueryResult>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String>,
-}
-
-#[async_trait::async_trait]
-impl Request for AnswerPreCheckoutQuery {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "answerPreCheckoutQuery", &self)
-            .await
-    }
-}
-
-impl AnswerPreCheckoutQuery {
-    pub(crate) fn new<P>(bot: Bot, pre_checkout_query_id: P, ok: bool) -> Self
-    where
-        P: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<Vec<ShippingOption>>,
-    error_message: Option<String>,
-}
-
-#[async_trait::async_trait]
-impl Request for AnswerShippingQuery {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "answerShippingQuery", &self).await
-    }
-}
-
-impl AnswerShippingQuery {
-    pub(crate) fn new<S>(bot: Bot, shipping_query_id: S, ok: bool) -> Self
-    where
-        S: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<ShippingOption>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<bool>,
-    mask_position: Option<MaskPosition>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for CreateNewStickerSet {
-    type Output = True;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<True>> {
-        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<N, T, E>(
-        bot: Bot,
-        user_id: i32,
-        name: N,
-        title: T,
-        sticker_type: StickerType,
-        emojis: E,
-    ) -> Self
-    where
-        N: Into<String>,
-        T: Into<String>,
-        E: Into<String>,
-    {
-        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_<bot username>`. `<bot_username>` is case insensitive.
-    /// 1-64 characters.
-    pub fn name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.name = val.into();
-        self
-    }
-
-    /// Sticker set title, 1-64 characters.
-    pub fn title<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "deleteChatPhoto", &self).await
-    }
-}
-
-impl DeleteChatPhoto {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "deleteChatStickerSet", &self).await
-    }
-}
-
-impl DeleteChatStickerSet {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "deleteMessage", &self).await
-    }
-}
-
-impl DeleteMessage {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "deleteStickerFromSet", &self).await
-    }
-}
-
-impl DeleteStickerFromSet {
-    pub(crate) fn new<S>(bot: Bot, sticker: S) -> Self
-    where
-        S: Into<String>,
-    {
-        let sticker = sticker.into();
-        Self { bot, sticker }
-    }
-
-    /// File identifier of the sticker.
-    pub fn sticker<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        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<String>,
-    parse_mode: Option<ParseMode>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditInlineMessageCaption {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageCaption", &self).await
-    }
-}
-
-impl EditInlineMessageCaption {
-    pub(crate) fn new<I>(bot: Bot, inline_message_id: I) -> Self
-    where
-        I: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.inline_message_id = val.into();
-        self
-    }
-
-    /// New caption of the message.
-    pub fn caption<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditInlineMessageLiveLocation {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageLiveLocation", &self)
-            .await
-    }
-}
-
-impl EditInlineMessageLiveLocation {
-    pub(crate) fn new<I>(bot: Bot, inline_message_id: I, latitude: f32, longitude: f32) -> Self
-    where
-        I: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditInlineMessageMedia {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        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<I>(bot: Bot, inline_message_id: I, media: InputMedia) -> Self
-    where
-        I: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditInlineMessageReplyMarkup {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageReplyMarkup", &self)
-            .await
-    }
-}
-
-impl EditInlineMessageReplyMarkup {
-    pub(crate) fn new<I>(bot: Bot, inline_message_id: I) -> Self
-    where
-        I: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<ParseMode>,
-    disable_web_page_preview: Option<bool>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditInlineMessageText {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageText", &self).await
-    }
-}
-
-impl EditInlineMessageText {
-    pub(crate) fn new<I, T>(bot: Bot, inline_message_id: I, text: T) -> Self
-    where
-        I: Into<String>,
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.inline_message_id = val.into();
-        self
-    }
-
-    /// New text of the message.
-    pub fn text<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String>,
-    parse_mode: Option<ParseMode>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditMessageCaption {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageCaption", &self).await
-    }
-}
-
-impl EditMessageCaption {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditMessageLiveLocation {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageLiveLocation", &self)
-            .await
-    }
-}
-
-impl EditMessageLiveLocation {
-    pub(crate) fn new<C>(
-        bot: Bot,
-        chat_id: C,
-        message_id: i32,
-        latitude: f32,
-        longitude: f32,
-    ) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditMessageMedia {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        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<C>(bot: Bot, chat_id: C, message_id: i32, media: InputMedia) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditMessageReplyMarkup {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageReplyMarkup", &self)
-            .await
-    }
-}
-
-impl EditMessageReplyMarkup {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<ParseMode>,
-    disable_web_page_preview: Option<bool>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for EditMessageText {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "editMessageText", &self).await
-    }
-}
-
-impl EditMessageText {
-    pub(crate) fn new<C, T>(bot: Bot, chat_id: C, message_id: i32, text: T) -> Self
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String> {
-        net::request_json(self.bot.client(), self.bot.token(), "exportChatInviteLink", &self).await
-    }
-}
-
-impl ExportChatInviteLink {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<bool>,
-    message_id: i32,
-}
-
-#[async_trait::async_trait]
-impl Request for ForwardMessage {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "forwardMessage", &self).await
-    }
-}
-
-impl ForwardMessage {
-    pub(crate) fn new<C, F>(bot: Bot, chat_id: C, from_chat_id: F, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-        F: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<Chat> {
-        net::request_json(self.bot.client(), self.bot.token(), "getChat", &self).await
-    }
-}
-
-impl GetChat {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<ChatMember>;
-
-    /// On success, returns an array that contains information about all chat
-    /// administrators except other bots.
-    async fn send(&self) -> ResponseResult<Vec<ChatMember>> {
-        net::request_json(self.bot.client(), self.bot.token(), "getChatAdministrators", &self).await
-    }
-}
-
-impl GetChatAdministrators {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<ChatMember> {
-        net::request_json(self.bot.client(), self.bot.token(), "getChatMember", &self).await
-    }
-}
-
-impl GetChatMember {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, user_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<i32> {
-        net::request_json(self.bot.client(), self.bot.token(), "getChatMembersCount", &self).await
-    }
-}
-
-impl GetChatMembersCount {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<token>/<file_path>`, where `<file_path>`
-/// is taken from the response. It is guaranteed that the link will be valid
-/// for at least `1` hour. When the link expires, a new one can be requested by
-/// calling [`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<File> {
-        net::request_json(self.bot.client(), self.bot.token(), "getFile", &self).await
-    }
-}
-
-impl GetFile {
-    pub(crate) fn new<F>(bot: Bot, file_id: F) -> Self
-    where
-        F: Into<String>,
-    {
-        Self { bot, file_id: file_id.into() }
-    }
-
-    /// File identifier to get info about.
-    pub fn file_id<F>(mut self, value: F) -> Self
-    where
-        F: Into<String>,
-    {
-        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<GameHighScore>;
-
-    async fn send(&self) -> ResponseResult<Vec<GameHighScore>> {
-        net::request_json(self.bot.client(), self.bot.token(), "getGameHighScores", &self).await
-    }
-}
-
-impl GetGameHighScores {
-    pub(crate) fn new<T>(bot: Bot, target: T, user_id: i32) -> Self
-    where
-        T: Into<TargetMessage>,
-    {
-        let target = target.into();
-        Self { bot, target, user_id }
-    }
-
-    /// Target message, either chat id and message id or inline message id.
-    pub fn target<T>(mut self, val: T) -> Self
-    where
-        T: Into<TargetMessage>,
-    {
-        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<Me> {
-        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<BotCommand>;
-
-    async fn send(&self) -> ResponseResult<Self::Output> {
-        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<StickerSet> {
-        net::request_json(self.bot.client(), self.bot.token(), "getStickerSet", &self).await
-    }
-}
-
-impl GetStickerSet {
-    pub(crate) fn new<N>(bot: Bot, name: N) -> Self
-    where
-        N: Into<String>,
-    {
-        let name = name.into();
-        Self { bot, name }
-    }
-
-    /// Name of the sticker set.
-    pub fn name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<i32>,
-    pub(crate) limit: Option<u8>,
-    pub(crate) timeout: Option<u32>,
-    pub(crate) allowed_updates: Option<Vec<AllowedUpdate>>,
-}
-
-#[async_trait::async_trait]
-impl Request for GetUpdates {
-    type Output = Vec<Result<Update, (Value, serde_json::Error)>>;
-
-    /// Deserialize to `Vec<serde_json::Result<Update>>` instead of
-    /// `Vec<Update>`, because we want to parse the rest of updates even if our
-    /// library hasn't parsed one.
-    async fn send(&self) -> ResponseResult<Vec<Result<Update, (Value, serde_json::Error)>>> {
-        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::<Vec<Update>>(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<T>(mut self, value: T) -> Self
-    where
-        T: Into<Vec<AllowedUpdate>>,
-    {
-        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<i32>,
-    limit: Option<i32>,
-}
-
-#[async_trait::async_trait]
-impl Request for GetUserProfilePhotos {
-    type Output = UserProfilePhotos;
-
-    async fn send(&self) -> ResponseResult<UserProfilePhotos> {
-        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<WebhookInfo> {
-        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<i32>,
-}
-
-#[async_trait::async_trait]
-impl Request for KickChatMember {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "kickChatMember", &self).await
-    }
-}
-
-impl KickChatMember {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, user_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "leaveChat", &self).await
-    }
-}
-
-impl LeaveChat {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<bool>,
-}
-
-#[async_trait::async_trait]
-impl Request for PinChatMessage {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "pinChatMessage", &self).await
-    }
-}
-
-impl PinChatMessage {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<bool>,
-    can_post_messages: Option<bool>,
-    can_edit_messages: Option<bool>,
-    can_delete_messages: Option<bool>,
-    can_invite_users: Option<bool>,
-    can_restrict_members: Option<bool>,
-    can_pin_messages: Option<bool>,
-    can_promote_members: Option<bool>,
-}
-
-#[async_trait::async_trait]
-impl Request for PromoteChatMember {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "promoteChatMember", &self).await
-    }
-}
-
-impl PromoteChatMember {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, user_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<i32>,
-}
-
-#[async_trait::async_trait]
-impl Request for RestrictChatMember {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "restrictChatMember", &self).await
-    }
-}
-
-impl RestrictChatMember {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, user_id: i32, permissions: ChatPermissions) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<u32>,
-    pub width: Option<u32>,
-    pub height: Option<u32>,
-    pub thumb: Option<InputFile>,
-    pub caption: Option<String>,
-    pub parse_mode: Option<ParseMode>,
-    pub disable_notification: Option<bool>,
-    pub reply_to_message_id: Option<i32>,
-    pub reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendAnimation {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, animation: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<ReplyMarkup>,
-    {
-        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<String>,
-    parse_mode: Option<ParseMode>,
-    duration: Option<i32>,
-    performer: Option<String>,
-    title: Option<String>,
-    thumb: Option<InputFile>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendAudio {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, audio: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.performer = Some(val.into());
-        self
-    }
-
-    /// Track name.
-    pub fn title<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendChatAction", &self).await
-    }
-}
-
-impl SendChatAction {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, action: SendChatActionKind) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<String>,
-    vcard: Option<String>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendContact {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendContact", &self).await
-    }
-}
-
-impl SendContact {
-    pub(crate) fn new<C, P, F>(bot: Bot, chat_id: C, phone_number: P, first_name: F) -> Self
-    where
-        C: Into<ChatId>,
-        P: Into<String>,
-        F: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    /// Contact's phone number.
-    pub fn phone_number<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.phone_number = val.into();
-        self
-    }
-
-    /// Contact's first name.
-    pub fn first_name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.first_name = val.into();
-        self
-    }
-
-    /// Contact's last name.
-    pub fn last_name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<DiceEmoji>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendDice {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendDice", &self).await
-    }
-}
-
-impl SendDice {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<InputFile>,
-    caption: Option<String>,
-    parse_mode: Option<ParseMode>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendDocument {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, document: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendGame {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendGame", &self).await
-    }
-}
-
-impl SendGame {
-    pub(crate) fn new<G>(bot: Bot, chat_id: i32, game_short_name: G) -> Self
-    where
-        G: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<LabeledPrice>,
-    provider_data: Option<String>,
-    photo_url: Option<String>,
-    photo_size: Option<i32>,
-    photo_width: Option<i32>,
-    photo_height: Option<i32>,
-    need_name: Option<bool>,
-    need_phone_number: Option<bool>,
-    need_email: Option<bool>,
-    need_shipping_address: Option<bool>,
-    send_phone_number_to_provider: Option<bool>,
-    send_email_to_provider: Option<bool>,
-    is_flexible: Option<bool>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendInvoice {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendInvoice", &self).await
-    }
-}
-
-impl SendInvoice {
-    #[allow(clippy::too_many_arguments)]
-    pub(crate) fn new<T, D, Pl, Pt, S, C, Pr>(
-        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<String>,
-        D: Into<String>,
-        Pl: Into<String>,
-        Pt: Into<String>,
-        S: Into<String>,
-        C: Into<String>,
-        Pr: Into<Vec<LabeledPrice>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    /// Product description, 1-255 characters.
-    pub fn description<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.payload = val.into();
-        self
-    }
-
-    /// Payments provider token, obtained via [@Botfather].
-    ///
-    /// [@Botfather]: https://t.me/botfather
-    pub fn provider_token<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<LabeledPrice>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<i64>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendLocation {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendLocation", &self).await
-    }
-}
-
-impl SendLocation {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, latitude: f32, longitude: f32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<InputMedia>, // TODO: InputMediaPhoto and InputMediaVideo
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendMediaGroup {
-    type Output = Vec<Message>;
-
-    async fn send(&self) -> ResponseResult<Vec<Message>> {
-        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<C, M>(bot: Bot, chat_id: C, media: M) -> Self
-    where
-        C: Into<ChatId>,
-        M: Into<Vec<InputMedia>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<InputMedia>>,
-    {
-        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<ParseMode>,
-    pub disable_web_page_preview: Option<bool>,
-    pub disable_notification: Option<bool>,
-    pub reply_to_message_id: Option<i32>,
-    pub reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendMessage {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendMessage", &self).await
-    }
-}
-
-impl SendMessage {
-    pub(crate) fn new<C, T>(bot: Bot, chat_id: C, text: T) -> Self
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = value.into();
-        self
-    }
-
-    /// Text of the message to be sent.
-    pub fn text<T>(mut self, value: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, value: T) -> Self
-    where
-        T: Into<ReplyMarkup>,
-    {
-        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<String>,
-    parse_mode: Option<ParseMode>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendPhoto {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, photo: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String>,
-    is_anonymous: Option<bool>,
-    poll_type: Option<PollType>,
-    allows_multiple_answers: Option<bool>,
-    correct_option_id: Option<i32>,
-    explanation: Option<String>,
-    explanation_parse_mode: Option<ParseMode>,
-    open_period: Option<i32>,
-    close_date: Option<i32>,
-    is_closed: Option<bool>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendPoll {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendPoll", &self).await
-    }
-}
-
-impl SendPoll {
-    pub(crate) fn new<C, Q, O>(bot: Bot, chat_id: C, question: Q, options: O) -> Self
-    where
-        C: Into<ChatId>,
-        Q: Into<String>,
-        O: Into<Vec<String>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    /// Poll question, 1-255 characters.
-    pub fn question<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.question = val.into();
-        self
-    }
-
-    /// List of answer options, 2-10 strings 1-100 characters each.
-    pub fn options<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<String>>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<bool>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<bool>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<i32>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<bool>,
-    {
-        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<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendSticker {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, sticker: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<String>,
-    foursquare_type: Option<String>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for SendVenue {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendVenue", &self).await
-    }
-}
-
-impl SendVenue {
-    pub(crate) fn new<C, T, A>(
-        bot: Bot,
-        chat_id: C,
-        latitude: f32,
-        longitude: f32,
-        title: T,
-        address: A,
-    ) -> Self
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-        A: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    /// Address of the venue.
-    pub fn address<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        self.address = val.into();
-        self
-    }
-
-    /// Foursquare identifier of the venue.
-    pub fn foursquare_id<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<i32>,
-    width: Option<i32>,
-    height: Option<i32>,
-    thumb: Option<InputFile>,
-    caption: Option<String>,
-    parse_mode: Option<ParseMode>,
-    supports_streaming: Option<bool>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendVideo {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, video: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<i32>,
-    length: Option<i32>,
-    thumb: Option<InputFile>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendVideoNote {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, video_note: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<String>,
-    parse_mode: Option<ParseMode>,
-    duration: Option<i32>,
-    disable_notification: Option<bool>,
-    reply_to_message_id: Option<i32>,
-    reply_markup: Option<ReplyMarkup>,
-}
-
-#[async_trait::async_trait]
-impl RequestWithFile for SendVoice {
-    type Output = Message;
-
-    async fn send(&self) -> tokio::io::Result<ResponseResult<Message>> {
-        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<C>(bot: Bot, chat_id: C, voice: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        net::request_json(
-            self.bot.client(),
-            self.bot.token(),
-            "setChatAdministratorCustomTitle",
-            &self,
-        )
-        .await
-    }
-}
-
-impl SetChatAdministratorCustomTitle {
-    pub(crate) fn new<C, CT>(bot: Bot, chat_id: C, user_id: i32, custom_title: CT) -> Self
-    where
-        C: Into<ChatId>,
-        CT: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<String>,
-}
-
-#[async_trait::async_trait]
-impl Request for SetChatDescription {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setChatDescription", &self).await
-    }
-}
-
-impl SetChatDescription {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    /// New chat description, 0-255 characters.
-    pub fn description<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "sendChatPermissions", &self).await
-    }
-}
-
-impl SetChatPermissions {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, permissions: ChatPermissions) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setChatPhoto", &self).await
-    }
-}
-
-impl SetChatPhoto {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, photo: InputFile) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setChatStickerSet", &self).await
-    }
-}
-
-impl SetChatStickerSet {
-    pub(crate) fn new<C, S>(bot: Bot, chat_id: C, sticker_set_name: S) -> Self
-    where
-        C: Into<ChatId>,
-        S: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    /// Name of the sticker set to be set as the group sticker set.
-    pub fn sticker_set_name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setChatTitle", &self).await
-    }
-}
-
-impl SetChatTitle {
-    pub(crate) fn new<C, T>(bot: Bot, chat_id: C, title: T) -> Self
-    where
-        C: Into<ChatId>,
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    /// New chat title, 1-255 characters.
-    pub fn title<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<bool>,
-    disable_edit_message: Option<bool>,
-}
-
-#[async_trait::async_trait]
-impl Request for SetGameScore {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "setGameScore", &self).await
-    }
-}
-
-impl SetGameScore {
-    pub(crate) fn new<T>(bot: Bot, target: T, user_id: i32, score: i32) -> Self
-    where
-        T: Into<TargetMessage>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<TargetMessage>,
-    {
-        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<BotCommand>,
-}
-
-#[async_trait::async_trait]
-impl Request for SetMyCommands {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<Self::Output> {
-        net::request_json(self.bot.client(), self.bot.token(), "setMyCommands", &self).await
-    }
-}
-
-impl SetMyCommands {
-    pub(crate) fn new<C>(bot: Bot, commands: C) -> Self
-    where
-        C: Into<Vec<BotCommand>>,
-    {
-        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<C>(mut self, commands: C) -> Self
-    where
-        C: Into<Vec<BotCommand>>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setStickerPositionInSet", &self)
-            .await
-    }
-}
-
-impl SetStickerPositionInSet {
-    pub(crate) fn new<S>(bot: Bot, sticker: S, position: i32) -> Self
-    where
-        S: Into<String>,
-    {
-        let sticker = sticker.into();
-        Self { bot, sticker, position }
-    }
-
-    /// File identifier of the sticker.
-    pub fn sticker<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InputFile>,
-}
-
-#[async_trait::async_trait]
-impl Request for SetStickerSetThumb {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<Self::Output> {
-        net::request_json(self.bot.client(), self.bot.token(), "setStickerSetThumb", &self).await
-    }
-}
-
-impl SetStickerSetThumb {
-    pub(crate) fn new<S>(bot: Bot, name: S, user_id: i32) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { bot, name: name.into(), user_id, thumb: None }
-    }
-
-    /// Sticker set name.
-    pub fn name<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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/<token>`. 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<InputFile>,
-    max_connections: Option<i32>,
-    allowed_updates: Option<Vec<AllowedUpdate>>,
-}
-
-#[async_trait::async_trait]
-impl Request for SetWebhook {
-    type Output = True;
-
-    async fn send(&self) -> ResponseResult<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "setWebhook", &self).await
-    }
-}
-
-impl SetWebhook {
-    pub(crate) fn new<U>(bot: Bot, url: U) -> Self
-    where
-        U: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<AllowedUpdate>>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for StopInlineMessageLiveLocation {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "stopMessageLiveLocation", &self)
-            .await
-    }
-}
-
-impl StopInlineMessageLiveLocation {
-    pub(crate) fn new<I>(bot: Bot, inline_message_id: I) -> Self
-    where
-        I: Into<String>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[async_trait::async_trait]
-impl Request for StopMessageLiveLocation {
-    type Output = Message;
-
-    async fn send(&self) -> ResponseResult<Message> {
-        net::request_json(self.bot.client(), self.bot.token(), "stopMessageLiveLocation", &self)
-            .await
-    }
-}
-
-impl StopMessageLiveLocation {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-#[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<Poll> {
-        net::request_json(self.bot.client(), self.bot.token(), "stopPoll", &self).await
-    }
-}
-impl StopPoll {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, message_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "unbanChatMember", &self).await
-    }
-}
-
-impl UnbanChatMember {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C, user_id: i32) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<True> {
-        net::request_json(self.bot.client(), self.bot.token(), "unpinChatMessage", &self).await
-    }
-}
-
-impl UnpinChatMessage {
-    pub(crate) fn new<C>(bot: Bot, chat_id: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        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<T>(mut self, val: T) -> Self
-    where
-        T: Into<ChatId>,
-    {
-        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<File> {
-        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<Cow<'a, str>>,
-        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<Self>
-    where
-        N: Into<Cow<'a, str>>,
-    {
-        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<Self>
-    where
-        N: Into<Cow<'a, str>>,
-    {
-        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<Cow<'a, str>>,
-    {
-        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<String>;
-}
-
-macro_rules! impl_for_struct {
-    ($($name:ty),*) => {
-        $(
-            impl IntoFormText for $name {
-                fn into_form_text(&self) -> Option<String> {
-                    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<T> IntoFormText for Option<T>
-where
-    T: IntoFormText,
-{
-    fn into_form_text(&self) -> Option<String> {
-        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<InputMedia> {
-    fn into_form_text(&self) -> Option<String> {
-        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<String> {
-        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<String> {
-        Some(self.to_owned())
-    }
-}
-
-impl IntoFormText for ParseMode {
-    fn into_form_text(&self) -> Option<String> {
-        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<String> {
-        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<String> {
-        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<T> = Result<T, crate::RequestError>;
-
-/// A shortcut for `ResponseResult::Ok(val)`.
-pub fn respond<T>(val: T) -> ResponseResult<T> {
-    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<Self::Output>;
-}
-
-/// 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<ResponseResult<Self::Output>>;
-}
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<Option<Self::Item>, 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<Part> {
-    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<PhotoSize>,
-
-    /// An original animation filename as defined by a sender.
-    pub file_name: Option<String>,
-
-    /// A MIME type of the file as defined by a sender.
-    pub mime_type: Option<MimeWrapper>,
-
-    /// A size of a file.
-    pub file_size: Option<u32>,
-}
-
-impl Animation {
-    pub fn new<S1, S2>(
-        file_id: S1,
-        file_unique_id: S2,
-        width: u32,
-        height: u32,
-        duration: u32,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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::<Animation>(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<String>,
-
-    /// A title of the audio as defined by sender or by audio tags.
-    pub title: Option<String>,
-
-    /// A MIME type of the file as defined by a sender.
-    pub mime_type: Option<MimeWrapper>,
-
-    /// A size of a file.
-    pub file_size: Option<u32>,
-
-    /// A thumbnail of the album cover to which the music file belongs.
-    pub thumb: Option<PhotoSize>,
-}
-
-impl Audio {
-    pub fn new<S1, S2>(file_id: S1, file_unique_id: S2, duration: u32) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_unique_id = val.into();
-        self
-    }
-
-    pub fn duration(mut self, val: u32) -> Self {
-        self.duration = val;
-        self
-    }
-
-    pub fn performer<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.performer = Some(val.into());
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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::<Audio>(&json).unwrap();
-        assert_eq!(actual, expected)
-    }
-}
diff --git a/src/types/bot_command.rs b/src/types/bot_command.rs
deleted file mode 100644
index d3116dff..00000000
--- a/src/types/bot_command.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-/// This object represents a bot command.
-///
-/// [The official docs](https://core.telegram.org/bots/api#botcommand).
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct BotCommand {
-    /// Text of the command, 1-32 characters.
-    ///
-    /// Can contain only lowercase English letters, digits and underscores.
-    pub command: String,
-
-    /// Description of the command, 3-256 characters.
-    pub description: String,
-}
-
-impl BotCommand {
-    pub fn new<S1, S2>(command: S1, description: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self { command: command.into(), description: description.into() }
-    }
-
-    pub fn command<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.command = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = val.into();
-        self
-    }
-}
diff --git a/src/types/callback_game.rs b/src/types/callback_game.rs
deleted file mode 100644
index 5b2d6e0f..00000000
--- a/src/types/callback_game.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-/// A placeholder, currently holds no information. Use [@BotFather](https://t.me/botfather) to set up your game.
-///
-/// [The official docs](https://core.telegram.org/bots/api#callbackgame).
-use serde::{Deserialize, Serialize};
-
-/// A placeholder, currently holds no information.
-///
-/// Use [@Botfather] to set up your game.
-///
-/// [@Botfather]:  https://t.me/botfather
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct CallbackGame;
diff --git a/src/types/callback_query.rs b/src/types/callback_query.rs
deleted file mode 100644
index d8c1d07c..00000000
--- a/src/types/callback_query.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::{Message, User};
-
-/// This object represents an incoming callback query from a callback button in
-/// an [inline keyboard].
-///
-/// If the button that originated the query was attached to a message sent by
-/// the bot, the field message will be present. If the button was attached to a
-/// message sent via the bot (in [inline mode]), the field `inline_message_id`
-/// will be present. Exactly one of the fields data or `game_short_name` will be
-/// present.
-///
-/// [The official docs](https://core.telegram.org/bots/api#callbackquery).
-///
-/// [inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-/// [inline mode]: https://core.telegram.org/bots/api#inline-mode
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct CallbackQuery {
-    /// An unique identifier for this query.
-    pub id: String,
-
-    /// A sender.
-    pub from: User,
-
-    /// A message with the callback button that originated the query. Note that
-    /// message content and message date will not be available if the message
-    /// is too old.
-    pub message: Option<Message>,
-
-    /// An identifier of the message sent via the bot in inline mode, that
-    /// originated the query.
-    pub inline_message_id: Option<String>,
-
-    /// A global identifier, uniquely corresponding to the chat to which the
-    /// message with the callback button was sent. Useful for high scores in
-    /// [games].
-    ///
-    /// [games]: https://core.telegram.org/bots/api#games
-    pub chat_instance: String,
-
-    /// A data associated with the callback button. Be aware that a bad client
-    /// can send arbitrary data in this field.
-    pub data: Option<String>,
-
-    /// A short name of a Game to be returned, serves as the unique identifier
-    /// for the game.
-    pub game_short_name: Option<String>,
-}
-
-impl CallbackQuery {
-    pub fn new<S1, S2>(id: S1, from: User, chat_instance: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            id: id.into(),
-            from,
-            message: None,
-            inline_message_id: None,
-            chat_instance: chat_instance.into(),
-            data: None,
-            game_short_name: None,
-        }
-    }
-
-    pub fn id<S>(mut self, id: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = id.into();
-        self
-    }
-
-    pub fn from(mut self, val: User) -> Self {
-        self.from = val;
-        self
-    }
-
-    pub fn message(mut self, val: Message) -> Self {
-        self.message = Some(val);
-        self
-    }
-
-    pub fn inline_message_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.inline_message_id = Some(val.into());
-        self
-    }
-
-    pub fn chat_instance<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.chat_instance = val.into();
-        self
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.data = Some(val.into());
-        self
-    }
-
-    pub fn game_short_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.game_short_name = Some(val.into());
-        self
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn deserialize() {
-        let json = r#"{
-            "id":"id",
-            "from":{
-                "id":12345,
-                "is_bot":false,
-                "first_name":"firstName"
-            },
-            "inline_message_id":"i_m_id",
-            "chat_instance":"123456",
-            "data":"some_data",
-            "game_short_name":"game_name"
-        }"#;
-        let expected = CallbackQuery {
-            id: "id".to_string(),
-            from: User {
-                id: 12345,
-                is_bot: false,
-                first_name: "firstName".to_string(),
-                last_name: None,
-                username: None,
-                language_code: None,
-            },
-            chat_instance: "123456".to_string(),
-            message: None,
-            inline_message_id: Some("i_m_id".to_string()),
-            data: Some("some_data".to_string()),
-            game_short_name: Some("game_name".to_string()),
-        };
-        let actual = serde_json::from_str::<CallbackQuery>(json).unwrap();
-        assert_eq!(actual, expected);
-    }
-}
diff --git a/src/types/chat.rs b/src/types/chat.rs
deleted file mode 100644
index 04c1bd49..00000000
--- a/src/types/chat.rs
+++ /dev/null
@@ -1,353 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::{ChatPermissions, ChatPhoto, Message};
-
-/// This object represents a chat.
-///
-/// [The official docs](https://core.telegram.org/bots/api#chat).
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct Chat {
-    /// A unique identifier for this chat. 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 id: i64,
-
-    #[serde(flatten)]
-    pub kind: ChatKind,
-
-    /// A chat photo. Returned only in [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub photo: Option<ChatPhoto>,
-}
-
-impl Chat {
-    pub fn new(id: i64, kind: ChatKind) -> Self {
-        Self { id, kind, photo: None }
-    }
-
-    pub fn id(mut self, val: i64) -> Self {
-        self.id = val;
-        self
-    }
-
-    pub fn kind(mut self, val: ChatKind) -> Self {
-        self.kind = val;
-        self
-    }
-
-    pub fn photo(mut self, val: ChatPhoto) -> Self {
-        self.photo = Some(val);
-        self
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[serde(untagged)]
-#[non_exhaustive]
-pub enum ChatKind {
-    Public(ChatPublic),
-    Private(ChatPrivate),
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChatPublic {
-    /// A title, for supergroups, channels and group chats.
-    pub title: Option<String>,
-
-    #[serde(flatten)]
-    pub kind: PublicChatKind,
-
-    /// A description, for groups, supergroups and channel chats. Returned
-    /// only in [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub description: Option<String>,
-
-    /// A chat invite link, for groups, supergroups and channel chats. Each
-    /// administrator in a chat generates their own invite links, so the
-    /// bot must first generate the link using
-    /// [`Bot::export_chat_invite_link`]. Returned only in
-    /// [`Bot::get_chat`].
-    ///
-    /// [`Bot::export_chat_invite_link`]:
-    /// crate::Bot::export_chat_invite_link
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub invite_link: Option<String>,
-
-    /// Pinned message, for groups, supergroups and channels. Returned only
-    /// in [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub pinned_message: Option<Box<Message>>,
-}
-
-impl ChatPublic {
-    pub fn new(kind: PublicChatKind) -> Self {
-        Self { title: None, kind, description: None, invite_link: None, pinned_message: None }
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn invite_link<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.invite_link = Some(val.into());
-        self
-    }
-
-    pub fn pinned_message(mut self, val: Message) -> Self {
-        self.pinned_message = Some(Box::new(val));
-        self
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChatPrivate {
-    /// A dummy field. Used to ensure that the `type` field is equal to
-    /// `private`.
-    #[serde(rename = "type")]
-    #[serde(deserialize_with = "assert_private_field")]
-    pub type_: (),
-
-    /// A username, for private chats, supergroups and channels if
-    /// available.
-    pub username: Option<String>,
-
-    /// A first name of the other party in a private chat.
-    pub first_name: Option<String>,
-
-    /// A last name of the other party in a private chat.
-    pub last_name: Option<String>,
-}
-
-impl ChatPrivate {
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    pub fn username<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.username = Some(val.into());
-        self
-    }
-
-    pub fn first_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.first_name = Some(val.into());
-        self
-    }
-
-    pub fn last_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.last_name = Some(val.into());
-        self
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-#[serde(tag = "type")]
-#[non_exhaustive]
-pub enum PublicChatKind {
-    Channel(PublicChatChannel),
-    Group(PublicChatGroup),
-    Supergroup(PublicChatSupergroup),
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Default, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct PublicChatChannel {
-    /// A username, for private chats, supergroups and channels if available.
-    pub username: Option<String>,
-}
-
-impl PublicChatChannel {
-    pub fn new() -> Self {
-        Self::default()
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Default, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct PublicChatGroup {
-    /// A default chat member permissions, for groups and supergroups. Returned
-    /// only from [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub permissions: Option<ChatPermissions>,
-}
-
-impl PublicChatGroup {
-    pub fn new() -> Self {
-        Self::default()
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Default, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct PublicChatSupergroup {
-    /// A username, for private chats, supergroups and channels if
-    /// available.
-    pub username: Option<String>,
-
-    /// For supergroups, name of group sticker set. Returned only from
-    /// [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub sticker_set_name: Option<String>,
-
-    /// `true`, if the bot can change the group sticker set. Returned only
-    /// from [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub can_set_sticker_set: Option<bool>,
-
-    /// A default chat member permissions, for groups and supergroups.
-    /// Returned only from [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub permissions: Option<ChatPermissions>,
-
-    /// The minimum allowed delay between consecutive messages sent by each
-    /// unpriviledged user. Returned only from [`Bot::get_chat`].
-    ///
-    /// [`Bot::get_chat`]: crate::Bot::get_chat
-    pub slow_mode_delay: Option<i32>,
-}
-
-impl PublicChatSupergroup {
-    pub fn new() -> Self {
-        Self::default()
-    }
-}
-
-struct PrivateChatKindVisitor;
-
-impl<'de> serde::de::Visitor<'de> for PrivateChatKindVisitor {
-    type Value = ();
-
-    fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        write!(f, r#"field equal to "private""#)
-    }
-
-    fn visit_borrowed_str<E: serde::de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
-        match v {
-            "private" => Ok(()),
-            _ => Err(E::invalid_value(serde::de::Unexpected::Str(v), &r#""private""#)),
-        }
-    }
-}
-
-fn assert_private_field<'de, D>(des: D) -> Result<(), D::Error>
-where
-    D: serde::Deserializer<'de>,
-{
-    des.deserialize_str(PrivateChatKindVisitor)
-}
-
-impl Chat {
-    pub fn is_private(&self) -> bool {
-        matches!(self.kind, ChatKind::Private(_))
-    }
-    pub fn is_group(&self) -> bool {
-        matches!(self.kind, ChatKind::Public(ChatPublic { kind: PublicChatKind::Group(_), .. }))
-    }
-    pub fn is_supergroup(&self) -> bool {
-        matches!(
-            self.kind,
-            ChatKind::Public(ChatPublic { kind: PublicChatKind::Supergroup(_), .. })
-        )
-    }
-    pub fn is_channel(&self) -> bool {
-        matches!(self.kind, ChatKind::Public(ChatPublic { kind: PublicChatKind::Channel(_), .. }))
-    }
-
-    pub fn is_chat(&self) -> bool {
-        self.is_private() || self.is_group() || self.is_supergroup()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use serde_json::from_str;
-
-    use crate::types::*;
-
-    #[test]
-    fn channel_de() {
-        let expected = Chat {
-            id: -1,
-            kind: ChatKind::Public(ChatPublic {
-                title: None,
-                kind: PublicChatKind::Channel(PublicChatChannel {
-                    username: Some("channelname".into()),
-                }),
-                description: None,
-                invite_link: None,
-                pinned_message: None,
-            }),
-            photo: None,
-        };
-        let actual = from_str(r#"{"id":-1,"type":"channel","username":"channelname"}"#).unwrap();
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn private_chat_de() {
-        assert_eq!(
-            Chat {
-                id: 0,
-                kind: ChatKind::Private(ChatPrivate {
-                    type_: (),
-                    username: Some("username".into()),
-                    first_name: Some("Anon".into()),
-                    last_name: None,
-                }),
-                photo: None,
-            },
-            from_str(r#"{"id":0,"type":"private","username":"username","first_name":"Anon"}"#)
-                .unwrap()
-        );
-    }
-
-    #[test]
-    fn private_chat_de_wrong_type_field() {
-        assert!(from_str::<Chat>(r#"{"id":0,"type":"WRONG"}"#).is_err());
-    }
-}
diff --git a/src/types/chat_action.rs b/src/types/chat_action.rs
deleted file mode 100644
index 9c112a56..00000000
--- a/src/types/chat_action.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-#[non_exhaustive]
-pub enum ChatAction {
-    Typing,
-    UploadPhoto,
-    RecordVideo,
-    UploadVideo,
-    RecordAudio,
-    UploadAudio,
-    UploadDocument,
-    FindLocation,
-    RecordVideoNote,
-    UploadVideoNote,
-}
diff --git a/src/types/chat_id.rs b/src/types/chat_id.rs
deleted file mode 100644
index f5723da0..00000000
--- a/src/types/chat_id.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use derive_more::{Display, From};
-use serde::{Deserialize, Serialize};
-
-/// A unique identifier for the target chat or username of the target channel
-/// (in the format `@channelusername`).
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, Display, From)]
-#[serde(untagged)]
-#[non_exhaustive]
-pub enum ChatId {
-    /// A chat identifier.
-    #[display(fmt = "{}", _0)]
-    Id(i64),
-
-    /// A channel username (in the format @channelusername).
-    #[display(fmt = "{}", _0)]
-    ChannelUsername(String),
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn chat_id_id_serialization() {
-        let expected_json = String::from(r#"123456"#);
-        let actual_json = serde_json::to_string(&ChatId::Id(123_456)).unwrap();
-
-        assert_eq!(expected_json, actual_json)
-    }
-
-    #[test]
-    fn chat_id_channel_username_serialization() {
-        let expected_json = String::from(r#""@username""#);
-        let actual_json =
-            serde_json::to_string(&ChatId::ChannelUsername(String::from("@username"))).unwrap();
-
-        assert_eq!(expected_json, actual_json)
-    }
-}
diff --git a/src/types/chat_member.rs b/src/types/chat_member.rs
deleted file mode 100644
index b8e38321..00000000
--- a/src/types/chat_member.rs
+++ /dev/null
@@ -1,262 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::User;
-
-// TODO: ChatMemberKind?...
-/// This object contains information about one member of the chat.
-///
-/// [The official docs](https://core.telegram.org/bots/api#chatmember).
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChatMember {
-    /// Information about the user.
-    pub user: User,
-
-    /// The member's status in the chat.
-    pub status: ChatMemberStatus,
-
-    /// Owner and administrators only. Custom title for this user
-    pub custom_title: Option<String>,
-
-    /// Restricted and kicked only. Date when restrictions will be lifted for
-    /// this user, unix time.
-    pub until_date: Option<i32>,
-
-    /// Administrators only. `true`, if the bot is allowed to edit
-    /// administrator privileges of that user.
-    pub can_be_edited: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can change the chat
-    /// title, photo and other settings.
-    pub can_change_info: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can post in the
-    /// channel, channels only.
-    pub can_post_messages: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can edit messages of
-    /// other users and can pin messages, channels only.
-    pub can_edit_messages: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can delete messages
-    /// of other users.
-    pub can_delete_messages: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can invite new users
-    /// to the chat.
-    pub can_invite_users: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can restrict,
-    /// ban or unban chat members.
-    pub can_restrict_members: Option<bool>,
-
-    /// Administrators only. `true`, if the administrator can pin messages,
-    /// supergroups only.
-    pub can_pin_messages: Option<bool>,
-
-    /// Administrators only. `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 the user).
-    pub can_promote_members: Option<bool>,
-
-    /// Restricted only. `true`, if the user can send text messages,
-    /// contacts, locations and venues.
-    pub can_send_messages: Option<bool>,
-
-    /// Restricted only. `true`, if the user is allowed to send audios,
-    /// documents, photos, videos, video notes and voice notes.
-    pub can_send_media_messages: Option<bool>,
-
-    /// Restricted only. `true`, if the user is allowed to send animations,
-    /// games, stickers and use inline bots.
-    pub can_send_other_messages: Option<bool>,
-
-    /// Restricted only. `true`, if the user is allowed to add web page
-    /// previews to their messages.
-    pub can_add_web_page_previews: Option<bool>,
-}
-
-impl ChatMember {
-    pub fn new(user: User, status: ChatMemberStatus) -> Self {
-        Self {
-            user,
-            status,
-            custom_title: None,
-            until_date: None,
-            can_be_edited: None,
-            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,
-            can_send_messages: None,
-            can_send_media_messages: None,
-            can_send_other_messages: None,
-            can_add_web_page_previews: None,
-        }
-    }
-
-    pub fn user(mut self, val: User) -> Self {
-        self.user = val;
-        self
-    }
-
-    pub fn status(mut self, val: ChatMemberStatus) -> Self {
-        self.status = val;
-        self
-    }
-
-    pub fn custom_title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.custom_title = Some(val.into());
-        self
-    }
-
-    pub fn until_date(mut self, val: i32) -> Self {
-        self.until_date = Some(val);
-        self
-    }
-
-    pub fn can_be_edited(mut self, val: bool) -> Self {
-        self.can_be_edited = Some(val);
-        self
-    }
-
-    pub fn can_change_info(mut self, val: bool) -> Self {
-        self.can_change_info = Some(val);
-        self
-    }
-
-    pub fn can_post_messages(mut self, val: bool) -> Self {
-        self.can_post_messages = Some(val);
-        self
-    }
-
-    pub fn can_edit_messages(mut self, val: bool) -> Self {
-        self.can_edit_messages = Some(val);
-        self
-    }
-
-    pub fn can_delete_messages(mut self, val: bool) -> Self {
-        self.can_delete_messages = Some(val);
-        self
-    }
-
-    pub fn can_invite_users(mut self, val: bool) -> Self {
-        self.can_invite_users = Some(val);
-        self
-    }
-
-    pub fn can_restrict_members(mut self, val: bool) -> Self {
-        self.can_restrict_members = Some(val);
-        self
-    }
-
-    pub fn can_pin_messages(mut self, val: bool) -> Self {
-        self.can_pin_messages = Some(val);
-        self
-    }
-
-    pub fn can_promote_members(mut self, val: bool) -> Self {
-        self.can_promote_members = Some(val);
-        self
-    }
-
-    pub fn can_send_messages(mut self, val: bool) -> Self {
-        self.can_send_messages = Some(val);
-        self
-    }
-
-    pub fn can_send_media_messages(mut self, val: bool) -> Self {
-        self.can_send_media_messages = Some(val);
-        self
-    }
-
-    pub fn can_send_other_messages(mut self, val: bool) -> Self {
-        self.can_send_other_messages = Some(val);
-        self
-    }
-
-    pub fn can_add_web_page_previews(mut self, val: bool) -> Self {
-        self.can_add_web_page_previews = Some(val);
-        self
-    }
-}
-
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub enum ChatMemberStatus {
-    Creator,
-    Administrator,
-    Member,
-    Restricted,
-    Left,
-    Kicked,
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn deserialize() {
-        let json = r#"{
-            "user":{
-                "id":12345,
-                "is_bot":false,
-                "first_name":"firstName"
-            },
-            "status":"creator",
-            "until_date":123456,
-            "can_be_edited":true,
-            "can_post_messages":true,
-            "can_edit_messages":true,
-            "can_delete_messages":true,
-            "can_restrict_members":true,
-            "can_promote_members":true,
-            "can_change_info":true,
-            "can_invite_users":true,
-            "can_pin_messages":true,
-            "is_member":true,
-            "can_send_messages":true,
-            "can_send_media_messages":true,
-            "can_send_polls":true,
-            "can_send_other_messages":true,
-            "can_add_web_page_previews":true
-        }"#;
-        let expected = ChatMember {
-            user: User {
-                id: 12345,
-                is_bot: false,
-                first_name: "firstName".to_string(),
-                last_name: None,
-                username: None,
-                language_code: None,
-            },
-            status: ChatMemberStatus::Creator,
-            custom_title: None,
-            until_date: Some(123_456),
-            can_be_edited: Some(true),
-            can_change_info: Some(true),
-            can_post_messages: Some(true),
-            can_edit_messages: Some(true),
-            can_delete_messages: Some(true),
-            can_invite_users: Some(true),
-            can_restrict_members: Some(true),
-            can_pin_messages: Some(true),
-            can_promote_members: Some(true),
-            can_send_messages: Some(true),
-            can_send_media_messages: Some(true),
-            can_send_other_messages: Some(true),
-            can_add_web_page_previews: Some(true),
-        };
-        let actual = serde_json::from_str::<ChatMember>(&json).unwrap();
-        assert_eq!(actual, expected)
-    }
-}
diff --git a/src/types/chat_permissions.rs b/src/types/chat_permissions.rs
deleted file mode 100644
index d6db3b6a..00000000
--- a/src/types/chat_permissions.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-/// Describes actions that a non-administrator user is allowed to take in a
-/// chat.
-///
-/// [The official docs](https://core.telegram.org/bots/api#chatpermissions).
-#[serde_with_macros::skip_serializing_none]
-#[derive(Copy, Clone, Default, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChatPermissions {
-    /// `true`, if the user is allowed to send text messages, contacts,
-    /// locations and venues.
-    pub can_send_messages: Option<bool>,
-
-    /// `true`, if the user is allowed to send audios, documents,
-    /// photos, videos, video notes and voice notes, implies
-    /// `can_send_messages`.
-    pub can_send_media_messages: Option<bool>,
-
-    /// `true`, if the user is allowed to send polls, implies
-    /// `can_send_messages`.
-    pub can_send_polls: Option<bool>,
-
-    /// `true`, if the user is allowed to send animations, games, stickers and
-    /// use inline bots, implies `can_send_media_messages`.
-    pub can_send_other_messages: Option<bool>,
-
-    /// `true`, if the user is allowed to add web page previews to
-    /// their messages, implies `can_send_media_messages`.
-    pub can_add_web_page_previews: Option<bool>,
-
-    /// `true`, if the user is allowed to change the chat title, photo and
-    /// other settings. Ignored in public supergroups.
-    pub can_change_info: Option<bool>,
-
-    /// `true`, if the user is allowed to invite new users to the chat.
-    pub can_invite_users: Option<bool>,
-
-    /// `true`, if the user is allowed to pin messages. Ignored in public
-    /// supergroups.
-    pub can_pin_messages: Option<bool>,
-}
-
-impl ChatPermissions {
-    pub fn new() -> Self {
-        Self::default()
-    }
-}
diff --git a/src/types/chat_photo.rs b/src/types/chat_photo.rs
deleted file mode 100644
index 7f5ed87d..00000000
--- a/src/types/chat_photo.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-/// This object represents a chat photo.
-///
-/// [The official docs](https://core.telegram.org/bots/api#chatphoto).
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChatPhoto {
-    /// A file identifier of small (160x160) chat photo. This file_id can be
-    /// used only for photo download and only for as long as the photo is
-    /// not changed.
-    pub small_file_id: String,
-
-    /// Unique file identifier of small (160x160) chat photo, which is supposed
-    /// to be the same over time and for different bots. Can't be used to
-    /// download or reuse the file.
-    pub small_file_unique_id: String,
-
-    /// A file identifier of big (640x640) chat photo. This file_id can be used
-    /// only for photo download and only for as long as the photo is not
-    /// changed.
-    pub big_file_id: String,
-
-    /// Unique file identifier of big (640x640) chat photo, which is supposed
-    /// to be the same over time and for different bots. Can't be used to
-    /// download or reuse the file.
-    pub big_file_unique_id: String,
-}
-
-impl ChatPhoto {
-    pub fn new<S1, S2, S3, S4>(
-        small_file_id: S1,
-        small_file_unique_id: S2,
-        big_file_id: S3,
-        big_file_unique_id: S4,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-        S4: Into<String>,
-    {
-        Self {
-            small_file_id: small_file_id.into(),
-            small_file_unique_id: small_file_unique_id.into(),
-            big_file_id: big_file_id.into(),
-            big_file_unique_id: big_file_unique_id.into(),
-        }
-    }
-
-    pub fn small_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.small_file_id = val.into();
-        self
-    }
-
-    pub fn small_file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.small_file_unique_id = val.into();
-        self
-    }
-
-    pub fn big_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.big_file_id = val.into();
-        self
-    }
-
-    pub fn big_file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.big_file_unique_id = val.into();
-        self
-    }
-}
diff --git a/src/types/chosen_inline_result.rs b/src/types/chosen_inline_result.rs
deleted file mode 100644
index 18139ff0..00000000
--- a/src/types/chosen_inline_result.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::{Location, User};
-
-/// Represents a [result] of an inline query that was chosen by the user and
-/// sent to their chat partner.
-///
-/// [The official docs](https://core.telegram.org/bots/api#choseninlineresult).
-///
-/// [result]: https://core.telegram.org/bots/api#inlinequeryresult
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct ChosenInlineResult {
-    /// The unique identifier for the result that was chosen.
-    pub result_id: String,
-
-    /// The user that chose the result.
-    pub from: User,
-
-    ///  A sender location, only for bots that require user location.
-    pub location: Option<Location>,
-
-    /// An identifier of the sent inline message. Available only if
-    /// there is an [inline keyboard] attached to the message. Will be also
-    /// received in [callback queries] and can be used to [edit] the message.
-    ///
-    /// [inline keyboard]: https://core.telegram.org/bots/api#inlinekeyboardmarkup
-    /// [callback queries]: https://core.telegram.org/bots/api#callbackquery
-    /// [edit]: https://core.telegram.org/bots/api#updating-messages
-    pub inline_message_id: Option<String>,
-
-    /// The query that was used to obtain the result.
-    pub query: String,
-}
-
-impl ChosenInlineResult {
-    pub fn new<S1, S2>(result_id: S1, from: User, query: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            result_id: result_id.into(),
-            from,
-            location: None,
-            inline_message_id: None,
-            query: query.into(),
-        }
-    }
-
-    pub fn result_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.result_id = val.into();
-        self
-    }
-
-    pub fn from(mut self, val: User) -> Self {
-        self.from = val;
-        self
-    }
-
-    pub fn location<S>(mut self, val: Location) -> Self {
-        self.location = val.into();
-        self
-    }
-
-    pub fn inline_message_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.inline_message_id = Some(val.into());
-        self
-    }
-
-    pub fn query<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.query = val.into();
-        self
-    }
-}
diff --git a/src/types/contact.rs b/src/types/contact.rs
deleted file mode 100644
index 68a31b38..00000000
--- a/src/types/contact.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-/// This object represents a phone contact.
-///
-/// [The official docs](https://core.telegram.org/bots/api#contact).
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct Contact {
-    /// A contact's phone number.
-    pub phone_number: String,
-
-    /// A contact's first name.
-    pub first_name: String,
-
-    /// A contact's last name.
-    pub last_name: Option<String>,
-
-    /// A contact's user identifier in Telegram.
-    pub user_id: Option<i32>,
-
-    /// Additional data about the contact in the form of a [vCard].
-    ///
-    /// [vCard]: https://en.wikipedia.org/wiki/VCard
-    pub vcard: Option<String>,
-}
-
-impl Contact {
-    pub fn new<S1, S2>(phone_number: S1, first_name: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            phone_number: phone_number.into(),
-            first_name: first_name.into(),
-            last_name: None,
-            user_id: None,
-            vcard: None,
-        }
-    }
-
-    pub fn phone_number<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.phone_number = val.into();
-        self
-    }
-
-    pub fn first_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.first_name = val.into();
-        self
-    }
-
-    pub fn last_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.last_name = Some(val.into());
-        self
-    }
-
-    pub fn user_id(mut self, val: i32) -> Self {
-        self.user_id = Some(val);
-        self
-    }
-
-    pub fn vcard<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.vcard = Some(val.into());
-        self
-    }
-}
diff --git a/src/types/dice.rs b/src/types/dice.rs
deleted file mode 100644
index 1c221166..00000000
--- a/src/types/dice.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::DiceEmoji;
-
-/// This object represents an animated emoji that displays a random value.
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct Dice {
-    /// Emoji on which the dice throw animation is based.
-    emoji: DiceEmoji,
-
-    /// Value of the dice.
-    ///
-    /// 1-6 for [`DiceEmoji::Dice`] and [`DiceEmoji::Darts`], 1-5 for
-    /// [`DiceEmoji::Basketball`].
-    ///
-    /// [`DiceEmoji::Dice`]: crate::types::DiceEmoji::Dice
-    /// [`DiceEmoji::Darts`]:crate::types::DiceEmoji::Darts
-    /// [`DiceEmoji::Basketball`]:crate::types::DiceEmoji::Basketball
-    value: i32,
-}
-
-impl Dice {
-    pub fn new(emoji: DiceEmoji, value: i32) -> Self {
-        Self { emoji, value }
-    }
-
-    pub fn emoji(mut self, val: DiceEmoji) -> Self {
-        self.emoji = val;
-        self
-    }
-
-    pub fn value<S>(mut self, val: i32) -> Self {
-        self.value = val;
-        self
-    }
-}
diff --git a/src/types/dice_emoji.rs b/src/types/dice_emoji.rs
deleted file mode 100644
index e503c7fa..00000000
--- a/src/types/dice_emoji.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
-pub enum DiceEmoji {
-    /// Values from 1-6. Defaults to this variant.
-    #[serde(rename = "🎲")]
-    Dice,
-
-    /// Values from 1-6.
-    #[serde(rename = "🎯")]
-    Darts,
-
-    /// Values from 1-5.
-    #[serde(rename = "🏀")]
-    Basketball,
-}
diff --git a/src/types/document.rs b/src/types/document.rs
deleted file mode 100644
index 8a409704..00000000
--- a/src/types/document.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use crate::types::{MimeWrapper, PhotoSize};
-
-/// This object represents a general file (as opposed to [photos], [voice
-/// messages] and [audio files]).
-///
-/// [The official docs](https://core.telegram.org/bots/api#document).
-///
-/// [photos]: https://core.telegram.org/bots/api#photosize
-/// [voice messages]: https://core.telegram.org/bots/api#voice
-/// [audio files]: 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 Document {
-    /// 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 document thumbnail as defined by a sender.
-    pub thumb: Option<PhotoSize>,
-
-    /// An original filename as defined by a sender.
-    pub file_name: Option<String>,
-
-    /// A MIME type of the file as defined by a sender.
-    pub mime_type: Option<MimeWrapper>,
-
-    /// A size of a file.
-    pub file_size: Option<u32>,
-}
-
-impl Document {
-    pub fn new<S1, S2>(file_id: S1, file_unique_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            thumb: None,
-            file_name: None,
-            mime_type: None,
-            file_size: None,
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_unique_id = val.into();
-        self
-    }
-
-    pub fn thumb(mut self, val: PhotoSize) -> Self {
-        self.thumb = Some(val);
-        self
-    }
-
-    pub fn file_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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
-    }
-}
diff --git a/src/types/encrypted_credentials.rs b/src/types/encrypted_credentials.rs
deleted file mode 100644
index 543e251c..00000000
--- a/src/types/encrypted_credentials.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-/// Contains data required for decrypting and authenticating
-/// [`EncryptedPassportElement`].
-///
-/// See the [Telegram Passport Documentation] for a complete description of the
-/// data decryption and authentication processes.
-///
-/// [The official docs](https://core.telegram.org/bots/api#encryptedcredentials).
-///
-/// [`EncryptedPassportElement`]:
-/// crate::types::EncryptedPassportElement
-/// [Telegram Passport Documentation]: https://core.telegram.org/passport#receiving-information
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct EncryptedCredentials {
-    /// Base64-encoded encrypted JSON-serialized data with unique user's
-    /// payload, data hashes and secrets required for
-    /// [`EncryptedPassportElement`] decryption and authentication.
-    ///
-    /// [`EncryptedPassportElement`]:
-    /// crate::types::EncryptedPassportElement
-    pub data: String, // TODO: check base64 type
-
-    /// Base64-encoded data hash for data authentication.
-    pub hash: String,
-
-    /// A base64-encoded secret, encrypted with the bot's public RSA key,
-    /// required for data decryption.
-    pub secret: String,
-}
-
-impl EncryptedCredentials {
-    pub fn new<S1, S2, S3>(data: S1, hash: S2, secret: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        Self { data: data.into(), hash: hash.into(), secret: secret.into() }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.data = val.into();
-        self
-    }
-
-    pub fn hash<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.hash = val.into();
-        self
-    }
-
-    pub fn secret<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.secret = val.into();
-        self
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn must_serialize_encrypted_credentials_to_json() {
-        // given
-        let expected_json = r#"
-        {
-            "data":"someData",
-            "hash":"1122",
-            "secret":"secret"
-        }"#
-        .replace("\n", "")
-        .replace(" ", "");
-        let encrypted_credentials = EncryptedCredentials {
-            data: "someData".to_string(),
-            hash: "1122".to_string(),
-            secret: "secret".to_string(),
-        };
-        // when
-        let actual_json = serde_json::to_string(&encrypted_credentials).unwrap();
-        //then
-        assert_eq!(actual_json, expected_json)
-    }
-}
diff --git a/src/types/encrypted_passport_element.rs b/src/types/encrypted_passport_element.rs
deleted file mode 100644
index 72c0884a..00000000
--- a/src/types/encrypted_passport_element.rs
+++ /dev/null
@@ -1,794 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-use super::PassportFile;
-
-/// Contains information about documents or other Telegram Passport elements
-/// shared with the bot by the user.
-///
-/// [The official docs](https://core.telegram.org/bots/api#encryptedpassportelement).
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct EncryptedPassportElement {
-    /// Base64-encoded element hash for using in
-    /// [`PassportElementErrorKind::Unspecified`].
-    ///
-    /// [`PassportElementErrorKind::Unspecified`]:
-    /// crate::types::PassportElementErrorKind::Unspecified
-    pub hash: String,
-
-    #[serde(flatten)]
-    pub kind: EncryptedPassportElementKind,
-}
-
-impl EncryptedPassportElement {
-    pub fn new<S>(hash: S, kind: EncryptedPassportElementKind) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { hash: hash.into(), kind }
-    }
-
-    pub fn hash<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.hash = val.into();
-        self
-    }
-
-    pub fn kind(mut self, val: EncryptedPassportElementKind) -> Self {
-        self.kind = val;
-        self
-    }
-}
-
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-#[allow(clippy::large_enum_variant)]
-#[non_exhaustive]
-pub enum EncryptedPassportElementKind {
-    PersonalDetails(EncryptedPassportElementPersonalDetails),
-    Passport(EncryptedPassportElementPassport),
-    DriverLicense(EncryptedPassportElementDriverLicense),
-    IdentityCard(EncryptedPassportElementIdentityCard),
-    InternalPassport(EncryptedPassportElementInternalPassport),
-    Address(EncryptedPassportElementAddress),
-    UtilityBill(EncryptedPassportElementUtilityBill),
-    BankStatement(EncryptedPassportElementBankStatement),
-    RentalAgreement(EncryptedPassportElementRentalAgreement),
-    PassportRegistration(EncryptedPassportElementPassportRegistration),
-    EncryptedPassportElement(EncryptedPassportElementTemporaryRegistration),
-    PhoneNumber(EncryptedPassportElementPhoneNumber),
-    Email(EncryptedPassportElementEmail),
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct EncryptedPassportElementPersonalDetails {
-    ///  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 EncryptedPassportElementPersonalDetails {
-    pub fn new<S>(data: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into() }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.data = val.into();
-        self
-    }
-}
-
-#[serde_with_macros::skip_serializing_none]
-#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
-#[non_exhaustive]
-pub struct EncryptedPassportElementPassport {
-    ///  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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementPassport {
-    pub fn new<S>(data: S, front_side: PassportFile, selfie: PassportFile) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into(), front_side, selfie, translation: None }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementDriverLicense {
-    pub fn new<S>(
-        data: S,
-        front_side: PassportFile,
-        reverse_side: PassportFile,
-        selfie: PassportFile,
-    ) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into(), front_side, reverse_side, selfie, translation: None }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementIdentityCard {
-    pub fn new<S>(
-        data: S,
-        front_side: PassportFile,
-        reverse_side: PassportFile,
-        selfie: PassportFile,
-    ) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into(), front_side, reverse_side, selfie, translation: None }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementInternalPassport {
-    pub fn new<S>(data: S, front_side: PassportFile, selfie: PassportFile) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into(), front_side, selfie, translation: None }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<S>(data: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { data: data.into() }
-    }
-
-    pub fn data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementUtilityBill {
-    pub fn new<F>(files: F) -> Self
-    where
-        F: Into<Vec<PassportFile>>,
-    {
-        Self { files: files.into(), translation: None }
-    }
-
-    pub fn files<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        self.files = val.into();
-        self
-    }
-
-    pub fn translation<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementBankStatement {
-    pub fn new<F>(files: F) -> Self
-    where
-        F: Into<Vec<PassportFile>>,
-    {
-        Self { files: files.into(), translation: None }
-    }
-
-    pub fn files<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        self.files = val.into();
-        self
-    }
-
-    pub fn translation<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementRentalAgreement {
-    pub fn new<F>(files: F) -> Self
-    where
-        F: Into<Vec<PassportFile>>,
-    {
-        Self { files: files.into(), translation: None }
-    }
-
-    pub fn files<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        self.files = val.into();
-        self
-    }
-
-    pub fn translation<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementPassportRegistration {
-    pub fn new<F>(files: F) -> Self
-    where
-        F: Into<Vec<PassportFile>>,
-    {
-        Self { files: files.into(), translation: None }
-    }
-
-    pub fn files<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        self.files = val.into();
-        self
-    }
-
-    pub fn translation<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<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<Vec<PassportFile>>,
-}
-
-impl EncryptedPassportElementTemporaryRegistration {
-    pub fn new<F>(files: F) -> Self
-    where
-        F: Into<Vec<PassportFile>>,
-    {
-        Self { files: files.into(), translation: None }
-    }
-
-    pub fn files<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        self.files = val.into();
-        self
-    }
-
-    pub fn translation<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PassportFile>>,
-    {
-        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<S>(phone_number: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { phone_number: phone_number.into() }
-    }
-
-    pub fn phone_number<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(email: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { email: email.into() }
-    }
-
-    pub fn email<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<token>/<file_path>`.
-/// 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<token>/<file_path>`
-    /// to get the file.
-    pub file_path: String,
-}
-
-impl File {
-    pub fn new<S1, S2, S3>(file_id: S1, file_unique_id: S2, file_size: u32, file_path: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            file_size,
-            file_path: file_path.into(),
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<bool>,
-}
-
-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<PhotoSize>,
-
-    /// 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<String>,
-
-    /// Special entities that appear in text, such as usernames, URLs, bot
-    /// commands, etc.
-    pub text_entities: Option<Vec<MessageEntity>>,
-
-    /// Animation that will be displayed in the game message in chats. Upload
-    /// via [@Botfather].
-    ///
-    /// [@Botfather]: https://t.me/botfather
-    pub animation: Option<Animation>,
-}
-
-impl Game {
-    pub fn new<S1, S2, P>(title: S1, description: S2, photo: P) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        P: Into<Vec<PhotoSize>>,
-    {
-        Self {
-            title: title.into(),
-            description: description.into(),
-            photo: photo.into(),
-            text: None,
-            text_entities: None,
-            animation: None,
-        }
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = val.into();
-        self
-    }
-
-    pub fn photo<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PhotoSize>>,
-    {
-        self.photo = val.into();
-        self
-    }
-
-    pub fn text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.text = Some(val.into());
-        self
-    }
-
-    pub fn text_entities<T>(mut self, val: T) -> Self
-    where
-        T: Into<Vec<MessageEntity>>,
-    {
-        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<S>(text: S, kind: InlineKeyboardButtonKind) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { text: text.into(), kind }
-    }
-
-    pub fn text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<Vec<InlineKeyboardButton>>,
-}
-
-/// 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<I1, I2>(inline_keyboard: I1) -> Self
-    where
-        I1: Into<Vec<I2>>,
-        I2: Into<Vec<InlineKeyboardButton>>,
-    {
-        Self { inline_keyboard: inline_keyboard.into().into_iter().map(Into::into).collect() }
-    }
-
-    pub fn inline_keyboard<I1, I2>(mut self, val: I1) -> Self
-    where
-        I1: Into<Vec<I2>>,
-        I2: Into<Vec<InlineKeyboardButton>>,
-    {
-        self.inline_keyboard = val.into().into_iter().map(Into::into).collect();
-        self
-    }
-
-    pub fn append_row(mut self, buttons: Vec<InlineKeyboardButton>) -> 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<Location>,
-
-    /// 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<S1, S2, S3>(id: S1, from: User, query: S2, offset: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        Self { id: id.into(), from, location: None, query: query.into(), offset: offset.into() }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.query = val.into();
-        self
-    }
-
-    pub fn offset<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-
-    /// URL of the result.
-    pub url: Option<String>,
-
-    /// Pass `true`, if you don't want the URL to be shown in the
-    /// message.
-    pub hide_url: Option<bool>,
-
-    /// Short description of the result.
-    pub description: Option<String>,
-
-    /// Url of the thumbnail for the result.
-    pub thumb_url: Option<String>,
-
-    /// Thumbnail width.
-    pub thumb_width: Option<i32>,
-
-    /// Thumbnail height.
-    pub thumb_height: Option<i32>,
-}
-
-impl InlineQueryResultArticle {
-    pub fn new<S1, S2>(id: S1, title: S2, input_message_content: InputMessageContent) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.url = Some(val.into());
-        self
-    }
-
-    pub fn hide_url(mut self, val: bool) -> Self {
-        self.hide_url = Some(val);
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn thumb_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<ParseMode>,
-
-    /// Performer.
-    pub performer: Option<String>,
-
-    /// Audio duration in seconds.
-    pub audio_duration: Option<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<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the audio.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultAudio {
-    pub fn new<S1, S2, S3>(id: S1, audio_url: S2, title: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn audio_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.audio_url = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode(mut self, val: ParseMode) -> Self {
-        self.parse_mode = Some(val);
-        self
-    }
-
-    pub fn performer<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.performer = Some(val.into());
-        self
-    }
-
-    pub fn audio_duration<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the audio.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedAudio {
-    pub fn new<S1, S2>(id: S1, audio_file_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn audio_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.audio_file_id = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-
-    /// Caption of the document to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the file.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedDocument {
-    pub fn new<S1, S2, S3>(id: S1, title: S2, document_file_id: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn document_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.document_file_id = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<String>,
-
-    /// Caption of the GIF file to be sent, 0-1024 characters.
-    pub caption: Option<String>,
-
-    /// 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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the GIF animation.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedGif {
-    pub fn new<S1, S2>(id: S1, gif_file_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn gif_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.gif_file_id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-
-    /// Caption of the MPEG-4 file to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the video animation.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedMpeg4Gif {
-    pub fn new<S1, S2>(id: S1, mpeg4_file_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<String>,
-
-    /// Short description of the result.
-    pub description: Option<String>,
-
-    /// Caption of the photo to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the photo.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedPhoto {
-    pub fn new<S1, S2>(id: S1, photo_file_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn photo_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.photo_file_id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the sticker.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedSticker {
-    pub fn new<S1, S2>(id: S1, sticker_file_id: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            id: id.into(),
-            sticker_file_id: sticker_file_id.into(),
-            reply_markup: None,
-            input_message_content: None,
-        }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn sticker_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-
-    /// Caption of the video to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the video.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedVideo {
-    pub fn new<S1, S2, S3>(id: S1, video_file_id: S2, title: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn video_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.video_file_id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the voice message.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultCachedVoice {
-    pub fn new<S1, S2, S3>(id: S1, voice_file_id: S2, title: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn voice_file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.voice_file_id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<String>,
-
-    /// Additional data about the contact in the form of a [vCard], 0-2048
-    /// bytes.
-    ///
-    /// [VCard]: https://en.wikipedia.org/wiki/VCard
-    pub vcard: Option<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<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the contact.
-    pub input_message_content: Option<InputMessageContent>,
-
-    /// Url of the thumbnail for the result.
-    pub thumb_url: Option<String>,
-
-    /// Thumbnail width.
-    pub thumb_width: Option<i32>,
-
-    /// Thumbnail height.
-    pub thumb_height: Option<i32>,
-}
-
-impl InlineQueryResultContact {
-    pub fn new<S1, S2, S3>(id: S1, phone_number: S2, first_name: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn phone_number<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.phone_number = val.into();
-        self
-    }
-
-    pub fn first_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.first_name = val.into();
-        self
-    }
-
-    pub fn last_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.last_name = Some(val.into());
-        self
-    }
-
-    pub fn vcard<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<ParseMode>,
-
-    /// 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<String>,
-
-    /// Inline keyboard attached to the message.
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the file.
-    pub input_message_content: Option<InputMessageContent>,
-
-    /// URL of the thumbnail (jpeg only) for the file.
-    pub thumb_url: Option<String>,
-
-    /// Thumbnail width.
-    pub thumb_width: Option<i32>,
-
-    /// Thumbnail height.
-    pub thumb_height: Option<i32>,
-}
-
-impl InlineQueryResultDocument {
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(mut self, val: ParseMode) -> Self {
-        self.parse_mode = Some(val);
-        self
-    }
-
-    pub fn document_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.document_url = val.into();
-        self
-    }
-
-    pub fn mime_type(mut self, val: MimeWrapper) -> Self {
-        self.mime_type = val;
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InlineKeyboardMarkup>,
-}
-
-impl InlineQueryResultGame {
-    pub fn new<S1, S2>(id: S1, game_short_name: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self { id: id.into(), game_short_name: game_short_name.into(), reply_markup: None }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn game_short_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<i32>,
-
-    /// Height of the GIFv.
-    pub gif_height: Option<i32>,
-
-    /// Duration of the GIF.
-    pub gif_duration: Option<i32>,
-
-    /// URL of the static thumbnail for the result (jpeg or gif).
-    pub thumb_url: String,
-
-    /// Title for the result.
-    pub title: Option<String>,
-
-    /// Caption of the GIF file to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the GIF animation.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultGif {
-    pub fn new<S1, S2, S3>(id: S1, gif_url: S2, thumb_url: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn gif_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.thumb_url = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<i32>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the location.
-    pub input_message_content: Option<InputMessageContent>,
-
-    /// Url of the thumbnail for the result.
-    pub thumb_url: Option<String>,
-
-    /// Thumbnail width.
-    pub thumb_width: Option<i32>,
-
-    /// Thumbnail height.
-    pub thumb_height: Option<i32>,
-}
-
-impl InlineQueryResultLocation {
-    pub fn new<S1, S2>(id: S1, title: S2, latitude: f64, longitude: f64) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<i32>,
-
-    /// Video height.
-    pub mpeg4_height: Option<i32>,
-
-    /// Video duration.
-    pub mpeg4_duration: Option<i32>,
-
-    /// URL of the static thumbnail (jpeg or gif) for the result.
-    pub thumb_url: String,
-
-    /// Title for the result.
-    pub title: Option<String>,
-
-    /// Caption of the MPEG-4 file to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the video animation.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultMpeg4Gif {
-    pub fn new<S1, S2, S3>(id: S1, mpeg4_url: S2, thumb_url: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn mpeg4_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.thumb_url = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<i32>,
-
-    /// Height of the photo.
-    pub photo_height: Option<i32>,
-
-    /// Title for the result.
-    pub title: Option<String>,
-
-    /// Short description of the result.
-    pub description: Option<String>,
-
-    /// Caption of the photo to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the photo.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultPhoto {
-    pub fn new<S1, S2, S3>(id: S1, photo_url: S2, thumb_url: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn photo_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.photo_url = val.into();
-        self
-    }
-
-    pub fn thumb_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.thumb_url = val.into();
-        self
-    }
-
-    pub fn photo_width<S>(mut self, val: i32) -> Self {
-        self.photo_width = Some(val);
-        self
-    }
-
-    pub fn photo_height<S>(mut self, val: i32) -> Self {
-        self.photo_height = Some(val);
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = Some(val.into());
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = Some(val.into());
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn parse_mode<S>(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<String>,
-
-    /// Foursquare type of the venue, if known. (For example,
-    /// `arts_entertainment/default`, `arts_entertainment/aquarium` or
-    /// `food/icecream`.)
-    pub foursquare_type: Option<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<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the venue.
-    pub input_message_content: Option<InputMessageContent>,
-
-    /// Url of the thumbnail for the result.
-    pub thumb_url: Option<String>,
-
-    /// Thumbnail width.
-    pub thumb_width: Option<i32>,
-
-    /// Thumbnail height.
-    pub thumb_height: Option<i32>,
-}
-
-impl InlineQueryResultVenue {
-    pub fn new<S1, S2, S3>(id: S1, latitude: f64, longitude: f64, title: S2, address: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn address<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.address = val.into();
-        self
-    }
-
-    pub fn foursquare_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.foursquare_id = Some(val.into());
-        self
-    }
-
-    pub fn foursquare_type<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<ParseMode>,
-
-    /// Video width.
-    pub video_width: Option<i32>,
-
-    /// Video height.
-    pub video_height: Option<i32>,
-
-    /// Video duration in seconds.
-    pub video_duration: Option<i32>,
-
-    /// Short description of the result.
-    pub description: Option<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<InlineKeyboardMarkup>,
-
-    /// 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<InputMessageContent>,
-}
-
-impl InlineQueryResultVideo {
-    pub fn new<S1, S2, S3, S4>(
-        id: S1,
-        video_url: S2,
-        mime_type: MimeWrapper,
-        thumb_url: S3,
-        title: S4,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-        S4: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn video_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.video_url = val.into();
-        self
-    }
-
-    pub fn mime_type(mut self, val: MimeWrapper) -> Self {
-        self.mime_type = val;
-        self
-    }
-
-    pub fn thumb_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.thumb_url = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<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<ParseMode>,
-
-    /// Recording duration in seconds.
-    pub voice_duration: Option<i32>,
-
-    /// [Inline keyboard] attached to the message.
-    ///
-    /// [Inline keyboard]: https://core.telegram.org/bots#inline-keyboards-and-on-the-fly-updating
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-
-    /// Content of the message to be sent instead of the voice recording.
-    pub input_message_content: Option<InputMessageContent>,
-}
-
-impl InlineQueryResultVoice {
-    pub fn new<S1, S2, S3>(id: S1, voice_url: S2, title: S3) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn voice_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.voice_url = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<P>(path: P) -> Self
-    where
-        P: Into<PathBuf>,
-    {
-        Self::File(path.into())
-    }
-
-    pub fn memory<S, D>(file_name: S, data: D) -> Self
-    where
-        S: Into<String>,
-        D: Into<Cow<'static, [u8]>>,
-    {
-        Self::Memory { file_name: file_name.into(), data: data.into() }
-    }
-
-    pub fn url<T>(url: T) -> Self
-    where
-        T: Into<String>,
-    {
-        Self::Url(url.into())
-    }
-
-    pub fn file_id<T>(file_id: T) -> Self
-    where
-        T: Into<String>,
-    {
-        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<InputFile> for Option<PathBuf> {
-    fn from(file: InputFile) -> Self {
-        match file {
-            InputFile::File(path) => Some(path),
-            _ => None,
-        }
-    }
-}
-
-impl Serialize for InputFile {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    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<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<ParseMode>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InputFile>,
-
-    /// Caption of the video to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// Video width.
-    pub width: Option<u16>,
-
-    /// Video height.
-    pub height: Option<u16>,
-
-    /// Video duration.
-    pub duration: Option<u16>,
-
-    /// Pass `true`, if the uploaded video is suitable for streaming.
-    pub supports_streaming: Option<bool>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InputFile>,
-
-    /// Caption of the animation to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// Animation width.
-    pub width: Option<u16>,
-
-    /// Animation height.
-    pub height: Option<u16>,
-
-    /// Animation duration.
-    pub duration: Option<u16>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InputFile>,
-
-    /// Caption of the audio to be sent, 0-1024 characters.
-    pub caption: Option<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<ParseMode>,
-
-    /// Duration of the audio in seconds.
-    pub duration: Option<u16>,
-
-    /// Performer of the audio.
-    pub performer: Option<String>,
-
-    /// Title of the audio.
-    pub title: Option<String>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.performer = Some(val.into());
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InputFile>,
-
-    /// Caption of the document to be sent, 0-1024 charactersю
-    pub caption: Option<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<ParseMode>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<InputMedia> 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<ParseMode>,
-
-    /// Disables link previews for links in the sent message.
-    pub disable_web_page_preview: Option<bool>,
-}
-
-impl InputMessageContentText {
-    pub fn new<S>(message_text: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { message_text: message_text.into(), parse_mode: None, disable_web_page_preview: None }
-    }
-
-    pub fn message_text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<u32>,
-}
-
-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<String>,
-
-    /// Foursquare type of the venue, if known. (For example,
-    /// `arts_entertainment/default`, `arts_entertainment/aquarium`
-    /// or `food/icecream`.)
-    pub foursquare_type: Option<String>,
-}
-
-impl InputMessageContentVenue {
-    pub fn new<S1, S2>(latitude: f64, longitude: f64, title: S1, address: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn address<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.address = val.into();
-        self
-    }
-
-    pub fn foursquare_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.foursquare_id = Some(val.into());
-        self
-    }
-
-    pub fn foursquare_type<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-
-    /// Additional data about the contact in the form of a [vCard], 0-2048
-    /// bytes.
-    ///
-    /// [vCard]: https://en.wikipedia.org/wiki/VCard
-    pub vcard: Option<String>,
-}
-
-impl InputMessageContentContact {
-    pub fn new<S1, S2>(phone_number: S1, first_name: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            phone_number: phone_number.into(),
-            first_name: first_name.into(),
-            last_name: None,
-            vcard: None,
-        }
-    }
-
-    pub fn phone_number<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.phone_number = val.into();
-        self
-    }
-
-    pub fn first_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.first_name = val.into();
-        self
-    }
-
-    pub fn last_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.last_name = Some(val.into());
-        self
-    }
-
-    pub fn vcard<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S1, S2, S3, S4>(
-        title: S1,
-        description: S2,
-        start_parameter: S3,
-        currency: S4,
-        total_amount: i32,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-        S4: Into<String>,
-    {
-        Self {
-            title: title.into(),
-            description: description.into(),
-            start_parameter: start_parameter.into(),
-            currency: currency.into(),
-            total_amount,
-        }
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = val.into();
-        self
-    }
-
-    pub fn start_parameter<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.start_parameter = val.into();
-        self
-    }
-
-    pub fn currency<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<ButtonRequest>,
-}
-
-impl KeyboardButton {
-    pub fn new<T>(text: T) -> Self
-    where
-        T: Into<String>,
-    {
-        Self { text: text.into(), request: None }
-    }
-
-    pub fn request<T>(mut self, val: T) -> Self
-    where
-        T: Into<Option<ButtonRequest>>,
-    {
-        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<True>,
-
-    /// 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<True>,
-
-    /// 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<KeyboardButtonPollType>,
-}
-
-impl<'de> Deserialize<'de> for ButtonRequest {
-    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-    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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    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<S>(poll_type: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { poll_type: poll_type.into() }
-    }
-
-    pub fn poll_type<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(label: S, amount: i32) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { label: label.into(), amount }
-    }
-
-    pub fn label<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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:
-///
-/// <div align="center">
-///     <img src="https://core.telegram.org/file/811140015/1734/8VZFkwWXalM.97872/6127fa62d8a0bf2b3c" width=300 />
-/// </div>
-///
-/// [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<String>,
-    pub bot_username: Option<String>,
-    pub request_write_access: Option<bool>,
-}
-
-impl LoginUrl {
-    pub fn new<S>(url: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { url: url.into(), forward_text: None, bot_username: None, request_write_access: None }
-    }
-
-    pub fn url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.url = val.into();
-        self
-    }
-
-    pub fn forward_text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.forward_text = Some(val.into());
-        self
-    }
-
-    pub fn bot_username<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.bot_username = Some(val.into());
-        self
-    }
-
-    pub fn request_write_access<S>(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<S>(point: S, x_shift: f64, y_shift: f64, scale: f64) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { point: point.into(), x_shift, y_shift, scale }
-    }
-
-    pub fn point<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: bool) -> Self {
-        self.can_join_groups = val;
-        self
-    }
-
-    #[warn(clippy::wrong_self_convention)]
-    pub fn can_read_all_group_messages<S>(mut self, val: bool) -> Self {
-        self.can_read_all_group_messages = val;
-        self
-    }
-
-    #[warn(clippy::wrong_self_convention)]
-    pub fn supports_inline_queries<S>(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<User>,
-
-    #[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<User>,
-
-    #[serde(flatten)]
-    pub forward_kind: ForwardKind,
-
-    /// Date the message was last edited in Unix time.
-    pub edit_date: Option<i32>,
-
-    #[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<InlineKeyboardMarkup>,
-}
-
-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<User>,
-}
-
-impl MessageNewChatMembers {
-    pub fn new<N>(new_chat_members: N) -> Self
-    where
-        N: Into<Vec<User>>,
-    {
-        Self { new_chat_members: new_chat_members.into() }
-    }
-
-    pub fn new_chat_members<N>(mut self, val: N) -> Self
-    where
-        N: Into<Vec<User>>,
-    {
-        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<N>(left_chat_member: N) -> Self
-    where
-        N: Into<User>,
-    {
-        Self { left_chat_member: left_chat_member.into() }
-    }
-
-    pub fn left_chat_member<N>(mut self, val: N) -> Self
-    where
-        N: Into<User>,
-    {
-        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<N>(new_chat_title: N) -> Self
-    where
-        N: Into<String>,
-    {
-        Self { new_chat_title: new_chat_title.into() }
-    }
-
-    pub fn new_chat_title<N>(mut self, val: N) -> Self
-    where
-        N: Into<String>,
-    {
-        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<PhotoSize>,
-}
-
-impl MessageNewChatPhoto {
-    pub fn new<N>(new_chat_photo: N) -> Self
-    where
-        N: Into<Vec<PhotoSize>>,
-    {
-        Self { new_chat_photo: new_chat_photo.into() }
-    }
-
-    pub fn new_chat_photo<N>(mut self, val: N) -> Self
-    where
-        N: Into<Vec<PhotoSize>>,
-    {
-        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<Message>,
-}
-
-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<S>(connected_website: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { connected_website: connected_website.into() }
-    }
-
-    pub fn connected_website<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-}
-
-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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<Box<Message>>,
-}
-
-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<String>,
-
-    /// 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<MessageEntity>,
-}
-
-impl MediaAnimation {
-    pub fn new<CE>(animation: Animation, caption_entities: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<String>,
-
-    /// 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<MessageEntity>,
-}
-
-impl MediaAudio {
-    pub fn new<CE>(audio: Audio, caption_entities: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        Self { audio, caption: None, caption_entities: caption_entities.into() }
-    }
-
-    pub fn audio(mut self, val: Audio) -> Self {
-        self.audio = val;
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<String>,
-
-    /// 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<MessageEntity>,
-}
-
-impl MediaDocument {
-    pub fn new<CE>(document: Document, caption_entities: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        Self { document, caption: None, caption_entities: caption_entities.into() }
-    }
-
-    pub fn document(mut self, val: Document) -> Self {
-        self.document = val;
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<PhotoSize>,
-
-    /// Caption for the photo, 0-1024 characters.
-    pub caption: Option<String>,
-
-    /// 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<MessageEntity>,
-
-    /// The unique identifier of a media message group this message belongs
-    /// to.
-    pub media_group_id: Option<String>,
-}
-
-impl MediaPhoto {
-    pub fn new<P, CE>(photo: P, caption_entities: CE) -> Self
-    where
-        P: Into<Vec<PhotoSize>>,
-        CE: Into<Vec<MessageEntity>>,
-    {
-        Self {
-            photo: photo.into(),
-            caption: None,
-            caption_entities: caption_entities.into(),
-            media_group_id: None,
-        }
-    }
-
-    pub fn photo<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PhotoSize>>,
-    {
-        self.photo = val.into();
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        self.caption_entities = val.into();
-        self
-    }
-
-    pub fn media_group_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<MessageEntity>,
-}
-
-impl MediaText {
-    pub fn new<S, E>(text: S, entities: E) -> Self
-    where
-        S: Into<String>,
-        E: Into<Vec<MessageEntity>>,
-    {
-        Self { text: text.into(), entities: entities.into() }
-    }
-
-    pub fn text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.text = val.into();
-        self
-    }
-
-    pub fn entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<String>,
-
-    /// 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<MessageEntity>,
-
-    /// The unique identifier of a media message group this message belongs
-    /// to.
-    pub media_group_id: Option<String>,
-}
-
-impl MediaVideo {
-    pub fn new<CE>(video: Video, caption_entities: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        self.caption_entities = val.into();
-        self
-    }
-
-    pub fn media_group_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-
-    /// 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<MessageEntity>,
-}
-
-impl MediaVoice {
-    pub fn new<CE>(voice: Voice, caption_entities: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        Self { voice, caption: None, caption_entities: caption_entities.into() }
-    }
-
-    pub fn voice(mut self, val: Voice) -> Self {
-        self.voice = val;
-        self
-    }
-
-    pub fn caption<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.caption = Some(val.into());
-        self
-    }
-
-    pub fn caption_entities<CE>(mut self, val: CE) -> Self
-    where
-        CE: Into<Vec<MessageEntity>>,
-    {
-        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<String> {
-            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<True>` is weird, can we do something with it?
-        //       mb smt like `is_delete_chat_photo(&self) -> bool`?
-        pub fn delete_chat_photo(&self) -> Option<True> {
-            match &self.kind {
-                DeleteChatPhoto(MessageDeleteChatPhoto { delete_chat_photo }) => {
-                    Some(*delete_chat_photo)
-                }
-                _ => None,
-            }
-        }
-
-        pub fn group_chat_created(&self) -> Option<True> {
-            match &self.kind {
-                GroupChatCreated(MessageGroupChatCreated { group_chat_created }) => {
-                    Some(*group_chat_created)
-                }
-                _ => None,
-            }
-        }
-
-        pub fn super_group_chat_created(&self) -> Option<True> {
-            match &self.kind {
-                SupergroupChatCreated(MessageSupergroupChatCreated { supergroup_chat_created }) => {
-                    Some(*supergroup_chat_created)
-                }
-                _ => None,
-            }
-        }
-
-        pub fn channel_chat_created(&self) -> Option<True> {
-            match &self.kind {
-                ChannelChatCreated(MessageChannelChatCreated { channel_chat_created }) => {
-                    Some(*channel_chat_created)
-                }
-                _ => None,
-            }
-        }
-
-        pub fn migrate_to_chat_id(&self) -> Option<i64> {
-            match &self.kind {
-                Migrate(MessageMigrate { migrate_to_chat_id, .. }) => Some(*migrate_to_chat_id),
-                _ => None,
-            }
-        }
-
-        pub fn migrate_from_chat_id(&self) -> Option<i64> {
-            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<reqwest::Url> {
-        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::<Message>(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::<Message>(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::<Message>(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::<Message>(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::<Message>(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<String> },
-    TextLink { url: String },
-    TextMention { user: User },
-    Underline,
-    Strikethrough,
-}
-
-impl MessageEntity {
-    pub fn text_from(&self, message: &Message) -> Option<String> {
-        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::<MessageEntity>(
-                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::<MessageEntity>(
-                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<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::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<E>(self, v: &str) -> Result<Self::Value, E>
-    where
-        E: serde::de::Error,
-    {
-        match v.parse::<Mime>() {
-            Ok(mime_type) => Ok(MimeWrapper(mime_type)),
-            Err(e) => Err(E::custom(e)),
-        }
-    }
-}
-
-impl<'de> Deserialize<'de> for MimeWrapper {
-    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::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<S1, S2, S3>(
-        name: S1,
-        phone_number: S2,
-        email: S3,
-        shipping_address: ShippingAddress,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        Self {
-            name: name.into(),
-            phone_number: phone_number.into(),
-            email: email.into(),
-            shipping_address,
-        }
-    }
-
-    pub fn name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.name = val.into();
-        self
-    }
-
-    pub fn phone_number<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.phone_number = val.into();
-        self
-    }
-
-    pub fn email<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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=<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
-/// <b>bold</b>, <strong>bold</strong>
-/// <i>italic</i>, <em>italic</em>
-/// <u>underline</u>, <ins>underline</ins>
-/// <s>strikethrough</s>, <strike>strikethrough</strike>,
-/// <del>strikethrough</del> <b>bold <i>italic bold <s>italic bold
-/// strikethrough</s> <u>underline italic bold</u></i> bold</b> <a href="http:// www.example.com/">inline URL</a>
-/// <a href="tg:// user?id=123456789">inline mention of a user</a>
-/// <code>inline fixed-width code</code>
-/// <pre>pre-formatted fixed-width code block</pre>
-/// <pre><code class="language-rust">pre-formatted fixed-width code block
-/// written in the Rust programming language</code></pre> ````
-///
-/// 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
-///   `&lt;`, `>` with `&gt;` and `&` with `&amp;`).
-/// - All numerical HTML entities are supported.
-/// - The API currently supports only the following named HTML entities: `&lt;`,
-///   `&gt;`, `&amp;` and `&quot;`.
-/// - 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<Self, Self::Error> {
-        let normalized = value.to_lowercase();
-        match normalized.as_ref() {
-            "html" => Ok(ParseMode::HTML),
-            "markdown" => Ok(ParseMode::Markdown),
-            "markdownv2" => Ok(ParseMode::MarkdownV2),
-            _ => Err(()),
-        }
-    }
-}
-
-impl TryFrom<String> for ParseMode {
-    type Error = ();
-
-    fn try_from(value: String) -> Result<Self, Self::Error> {
-        value.as_str().try_into()
-    }
-}
-
-impl FromStr for ParseMode {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        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<EncryptedPassportElement>,
-
-    /// Encrypted credentials required to decrypt the data.
-    pub credentials: EncryptedCredentials,
-}
-
-impl PassportData {
-    pub fn new<E>(data: E, credentials: EncryptedCredentials) -> Self
-    where
-        E: Into<Vec<EncryptedPassportElement>>,
-    {
-        Self { data: data.into(), credentials }
-    }
-
-    pub fn data<E>(mut self, val: E) -> Self
-    where
-        E: Into<Vec<EncryptedPassportElement>>,
-    {
-        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<S>(message: S, kind: PassportElementErrorKind) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { message: message.into(), kind }
-    }
-
-    pub fn message<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S1, S2>(
-        r#type: PassportElementErrorDataFieldType,
-        field_name: S1,
-        data_hash: S2,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.field_name = val.into();
-        self
-    }
-
-    pub fn data_hash<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(r#type: PassportElementErrorFrontSideType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(r#type: PassportElementErrorReverseSideType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(r#type: PassportElementErrorSelfieType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(r#type: PassportElementErrorFileType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-}
-
-impl PassportElementErrorFiles {
-    pub fn new<S>(r#type: PassportElementErrorFilesType, file_hashes: S) -> Self
-    where
-        S: Into<Vec<String>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<Vec<String>>,
-    {
-        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<S>(r#type: PassportElementErrorTranslationFileType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String>,
-}
-
-impl PassportElementErrorTranslationFiles {
-    pub fn new<S>(r#type: PassportElementErrorTranslationFilesType, file_hashes: S) -> Self
-    where
-        S: Into<Vec<String>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<Vec<String>>,
-    {
-        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<S>(r#type: PassportElementErrorUnspecifiedType, file_hash: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S1, S2>(file_id: S1, file_unique_id: S2, file_size: u64, file_date: u64) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            file_size,
-            file_date,
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<u32>,
-}
-
-impl PhotoSize {
-    pub fn new<S1, S2>(file_id: S1, file_unique_id: S2, width: i32, height: i32) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            width,
-            height,
-            file_size: None,
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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::<PhotoSize>(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<PollOption>,
-
-    /// `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<i32>,
-
-    /// 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<String>,
-
-    /// Special entities like usernames, URLs, bot commands, etc. that appear in
-    /// the explanation.
-    pub explanation_entities: Option<Vec<MessageEntity>>,
-
-    /// Amount of time in seconds the poll will be active after creation.
-    open_period: Option<i32>,
-
-    /// Point in time (Unix timestamp) when the poll will be automatically
-    /// closed.
-    close_date: Option<i32>,
-}
-
-impl Poll {
-    #[allow(clippy::too_many_arguments)]
-    pub fn new<S1, S2, O>(
-        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<String>,
-        S2: Into<String>,
-        O: Into<Vec<PollOption>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn question<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.question = val.into();
-        self
-    }
-
-    pub fn options<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<PollOption>>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.explanation = Some(val.into());
-        self
-    }
-
-    pub fn explanation_entities<S>(mut self, val: S) -> Self
-    where
-        S: Into<Vec<MessageEntity>>,
-    {
-        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<S>(text: S, voter_count: i32) -> Self
-    where
-        S: Into<String>,
-    {
-        Self { text: text.into(), voter_count }
-    }
-
-    pub fn text<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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::<Poll>(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<i32>,
-}
-
-impl PollAnswer {
-    pub fn new<S, O>(poll_id: S, user: User, option_ids: O) -> Self
-    where
-        S: Into<String>,
-        O: Into<Vec<i32>>,
-    {
-        Self { poll_id: poll_id.into(), user, option_ids: option_ids.into() }
-    }
-
-    pub fn poll_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.poll_id = val.into();
-        self
-    }
-
-    pub fn user(mut self, val: User) -> Self {
-        self.user = val;
-        self
-    }
-
-    pub fn option_ids<S>(mut self, val: S) -> Self
-    where
-        S: Into<Vec<i32>>,
-    {
-        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<String>,
-
-    /// Order info provided by the user.
-    pub order_info: Option<OrderInfo>,
-}
-
-impl PreCheckoutQuery {
-    pub fn new<S1, S2>(
-        id: S1,
-        from: User,
-        currency: Currency,
-        total_amount: i32,
-        invoice_payload: S2,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            id: id.into(),
-            from,
-            currency,
-            total_amount,
-            invoice_payload: invoice_payload.into(),
-            shipping_option_id: None,
-            order_info: None,
-        }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn from(mut self, val: User) -> Self {
-        self.from = val;
-        self
-    }
-
-    pub fn currency<S>(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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.invoice_payload = val.into();
-        self
-    }
-
-    pub fn shipping_option_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<Vec<KeyboardButton>>,
-
-    /// 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<bool>,
-
-    /// 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<bool>,
-
-    /// 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<bool>,
-}
-
-impl ReplyKeyboardMarkup {
-    pub fn new<K1, K2>(keyboard: K1) -> Self
-    where
-        K1: Into<Vec<K2>>,
-        K2: Into<Vec<KeyboardButton>>,
-    {
-        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<KeyboardButton>) -> 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<T>(mut self, val: T) -> Self
-    where
-        T: Into<Option<bool>>,
-    {
-        self.resize_keyboard = val.into();
-        self
-    }
-
-    pub fn one_time_keyboard<T>(mut self, val: T) -> Self
-    where
-        T: Into<Option<bool>>,
-    {
-        self.one_time_keyboard = val.into();
-        self
-    }
-
-    pub fn selective<T>(mut self, val: T) -> Self
-    where
-        T: Into<Option<bool>>,
-    {
-        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<bool>,
-}
-
-impl ReplyKeyboardRemove {
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    pub fn selective<T>(mut self, val: T) -> Self
-    where
-        T: Into<bool>,
-    {
-        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<LabeledPrice>,
-    pub provider_data: Option<String>,
-    pub photo_url: Option<String>,
-    pub photo_size: Option<i32>,
-    pub photo_width: Option<i32>,
-    pub photo_height: Option<i32>,
-    pub need_name: Option<bool>,
-    pub need_phone_number: Option<bool>,
-    pub need_email: Option<bool>,
-    pub need_shipping_address: Option<bool>,
-    pub send_phone_number_to_provider: Option<bool>,
-    pub send_email_to_provider: Option<bool>,
-    pub is_flexible: Option<bool>,
-    pub disable_notification: Option<bool>,
-    pub reply_to_message_id: Option<i32>,
-    pub reply_markup: Option<InlineKeyboardMarkup>,
-}
-
-impl SendInvoice {
-    #[allow(clippy::too_many_arguments)]
-    pub fn new<C, S1, S2, S3, S4, S5, S6, P>(
-        chat_id: C,
-        title: S1,
-        description: S2,
-        payload: S3,
-        provider_token: S4,
-        start_parameter: S5,
-        currency: S6,
-        prices: P,
-    ) -> Self
-    where
-        C: Into<ChatId>,
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-        S4: Into<String>,
-        S5: Into<String>,
-        S6: Into<String>,
-        P: Into<Vec<LabeledPrice>>,
-    {
-        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<C>(mut self, val: C) -> Self
-    where
-        C: Into<ChatId>,
-    {
-        self.chat_id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn description<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.description = val.into();
-        self
-    }
-
-    pub fn payload<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.payload = val.into();
-        self
-    }
-
-    pub fn provider_token<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.provider_token = val.into();
-        self
-    }
-
-    pub fn start_parameter<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.start_parameter = val.into();
-        self
-    }
-
-    pub fn currency<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.currency = val.into();
-        self
-    }
-
-    pub fn prices<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<LabeledPrice>>,
-    {
-        self.prices = val.into();
-        self
-    }
-
-    pub fn provider_data<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.provider_data = Some(val.into());
-        self
-    }
-
-    pub fn photo_url<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S1, S2, S3, S4, S5>(
-        country_code: CountryCode,
-
-        state: S1,
-        city: S2,
-        street_line1: S3,
-        street_line2: S4,
-        post_code: S5,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-        S4: Into<String>,
-        S5: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.state = val.into();
-        self
-    }
-
-    pub fn city<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.city = val.into();
-        self
-    }
-
-    pub fn street_line1<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.street_line1 = val.into();
-        self
-    }
-
-    pub fn street_line2<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.street_line2 = val.into();
-        self
-    }
-
-    pub fn post_code<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<LabeledPrice>,
-}
-
-impl ShippingOption {
-    pub fn new<S1, S2, P>(id: S1, title: S2, prices: P) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        P: Into<Vec<LabeledPrice>>,
-    {
-        Self { id: id.into(), title: title.into(), prices: prices.into() }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn prices<P>(mut self, val: P) -> Self
-    where
-        P: Into<Vec<LabeledPrice>>,
-    {
-        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<S1, S2>(
-        id: S1,
-        from: User,
-        invoice_payload: S2,
-        shipping_address: ShippingAddress,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self { id: id.into(), from, invoice_payload: invoice_payload.into(), shipping_address }
-    }
-
-    pub fn id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.id = val.into();
-        self
-    }
-
-    pub fn from<S>(mut self, val: User) -> Self {
-        self.from = val;
-        self
-    }
-
-    pub fn invoice_payload<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.invoice_payload = val.into();
-        self
-    }
-
-    pub fn shipping_address<S>(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<PhotoSize>,
-
-    /// Emoji associated with the sticker.
-    pub emoji: Option<String>,
-
-    /// Name of the sticker set to which the sticker belongs.
-    pub set_name: Option<String>,
-
-    /// For mask stickers, the position where the mask should be placed.
-    pub mask_position: Option<MaskPosition>,
-
-    /// File size.
-    pub file_size: Option<u32>,
-}
-
-impl Sticker {
-    pub fn new<S1, S2>(
-        file_id: S1,
-        file_unique_id: S2,
-        width: u16,
-        height: u16,
-        is_animated: bool,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.emoji = Some(val.into());
-        self
-    }
-
-    pub fn set_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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>,
-
-    /// Sticker set thumbnail in the .WEBP or .TGS format.
-    thumb: Option<PhotoSize>,
-}
-
-impl StickerSet {
-    pub fn new<S1, S2, St>(
-        name: S1,
-        title: S2,
-        is_animated: bool,
-        contains_masks: bool,
-        stickers: St,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        St: Into<Vec<Sticker>>,
-    {
-        Self {
-            name: name.into(),
-            title: title.into(),
-            is_animated,
-            contains_masks,
-            stickers: stickers.into(),
-            thumb: None,
-        }
-    }
-
-    pub fn name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.name = val.into();
-        self
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<Vec<Sticker>>,
-    {
-        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<String>,
-
-    /// Order info provided by the user.
-    pub order_info: Option<OrderInfo>,
-
-    /// Telegram payment identifier.
-    pub telegram_payment_charge_id: String,
-
-    /// Provider payment identifier.
-    pub provider_payment_charge_id: String,
-}
-
-impl SuccessfulPayment {
-    pub fn new<S1, S2, S3>(
-        currency: Currency,
-        total_amount: i32,
-        invoice_payload: S1,
-        telegram_payment_charge_id: S2,
-        provider_payment_charge_id: S3,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-        S3: Into<String>,
-    {
-        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<S>(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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.invoice_payload = val.into();
-        self
-    }
-
-    pub fn shipping_option_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.telegram_payment_charge_id = val.into();
-        self
-    }
-
-    pub fn provider_payment_charge_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String> 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<bool> for False {
-    type Error = ();
-
-    fn try_from(value: bool) -> Result<Self, Self::Error> {
-        match value {
-            true => Err(()),
-            false => Ok(False),
-        }
-    }
-}
-
-impl<'de> Deserialize<'de> for False {
-    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-    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<E>(self, value: bool) -> Result<Self::Value, E>
-    where
-        E: serde::de::Error,
-    {
-        match value {
-            true => Err(E::custom("expected `false`, found `true`")),
-            false => Ok(False),
-        }
-    }
-}
-
-impl Serialize for False {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    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<bool> for True {
-    type Error = ();
-
-    fn try_from(value: bool) -> Result<Self, Self::Error> {
-        match value {
-            true => Ok(True),
-            false => Err(()),
-        }
-    }
-}
-
-impl<'de> Deserialize<'de> for True {
-    fn deserialize<D>(des: D) -> Result<Self, D::Error>
-    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<E>(self, value: bool) -> Result<Self::Value, E>
-    where
-        E: de::Error,
-    {
-        match value {
-            true => Ok(True),
-            false => Err(E::custom("expected `true`, found `false`")),
-        }
-    }
-}
-
-impl Serialize for True {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    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<S>(mut self, val: i32) -> Self {
-        self.id = val;
-        self
-    }
-
-    pub fn kind<S>(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<Self, serde_json::Error> {
-        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::<Update>(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::<Update>(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::<Update>(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::<Update>(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<String>,
-
-    /// User‘s or bot’s username.
-    pub username: Option<String>,
-
-    /// [IETF language tag] of the user's language.
-    ///
-    /// [IETF language tag]: https://en.wikipedia.org/wiki/IETF_language_tag
-    pub language_code: Option<String>,
-}
-
-impl User {
-    pub fn new<S>(id: i32, is_bot: bool, first_name: S) -> Self
-    where
-        S: Into<String>,
-    {
-        Self {
-            id,
-            is_bot,
-            first_name: first_name.into(),
-            last_name: None,
-            username: None,
-            language_code: None,
-        }
-    }
-
-    pub fn id<S>(mut self, val: i32) -> Self {
-        self.id = val;
-        self
-    }
-
-    #[allow(clippy::wrong_self_convention)]
-    pub fn is_bot<S>(mut self, val: bool) -> Self {
-        self.is_bot = val;
-        self
-    }
-
-    pub fn first_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.first_name = val.into();
-        self
-    }
-
-    pub fn last_name<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.last_name = Some(val.into());
-        self
-    }
-
-    pub fn username<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.username = Some(val.into());
-        self
-    }
-
-    pub fn language_code<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<String> {
-        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::<User>(&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<Vec<PhotoSize>>,
-}
-
-impl UserProfilePhotos {
-    pub fn new<P1, P2>(total_count: u32, photos: P1) -> Self
-    where
-        P1: Into<Vec<P2>>,
-        P2: Into<Vec<PhotoSize>>,
-    {
-        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<P1, P2>(mut self, val: P1) -> Self
-    where
-        P1: Into<Vec<P2>>,
-        P2: Into<Vec<PhotoSize>>,
-    {
-        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<String>,
-
-    /// Foursquare type of the venue. (For example,
-    /// `arts_entertainment/default`, `arts_entertainment/aquarium` or
-    /// `food/icecream`.)
-    pub foursquare_type: Option<String>,
-}
-
-impl Venue {
-    pub fn new<S1, S2>(location: Location, title: S1, address: S2) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            location,
-            title: title.into(),
-            address: address.into(),
-            foursquare_id: None,
-            foursquare_type: None,
-        }
-    }
-
-    pub fn title<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.title = val.into();
-        self
-    }
-
-    pub fn address<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.address = val.into();
-        self
-    }
-
-    pub fn foursquare_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.foursquare_id = Some(val.into());
-        self
-    }
-
-    pub fn foursquare_type<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<PhotoSize>,
-
-    /// Mime type of a file as defined by sender.
-    pub mime_type: Option<MimeWrapper>,
-
-    /// File size.
-    pub file_size: Option<u32>,
-}
-
-impl Video {
-    pub fn new<S1, S2>(
-        file_id: S1,
-        file_unique_id: S2,
-        width: u32,
-        height: u32,
-        duration: u32,
-    ) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<PhotoSize>,
-
-    /// File size.
-    pub file_size: Option<u32>,
-}
-
-impl VideoNote {
-    pub fn new<S1, S2>(file_id: S1, file_unique_id: S2, length: u32, duration: u32) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            length,
-            duration,
-            thumb: None,
-            file_size: None,
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<MimeWrapper>,
-
-    /// File size.
-    pub file_size: Option<u64>,
-}
-
-impl Voice {
-    pub fn new<S1, S2>(file_id: S1, file_unique_id: S2, duration: u32) -> Self
-    where
-        S1: Into<String>,
-        S2: Into<String>,
-    {
-        Self {
-            file_id: file_id.into(),
-            file_unique_id: file_unique_id.into(),
-            duration,
-            mime_type: None,
-            file_size: None,
-        }
-    }
-
-    pub fn file_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        self.file_id = val.into();
-        self
-    }
-
-    pub fn file_unique_id<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<u64>,
-
-    /// 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<String>,
-
-    /// Maximum allowed number of simultaneous HTTPS connections to the webhook
-    /// for update delivery.
-    pub max_connections: Option<u32>,
-
-    /// A list of update types the bot is subscribed to. Defaults to all update
-    /// types.
-    pub allowed_updates: Option<Vec<String>>,
-}
-
-impl WebhookInfo {
-    pub fn new<S>(url: S, has_custom_certificate: bool, pending_update_count: u32) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<S>(mut self, val: S) -> Self
-    where
-        S: Into<String>,
-    {
-        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<A, S>(mut self, val: A) -> Self
-    where
-        A: Into<Vec<S>>,
-        S: Into<String>,
-    {
-        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 <https://github.com/teloxide/teloxide/pull/305#issuecomment-716172103>