diff --git a/crates/teloxide-core/src/errors.rs b/crates/teloxide-core/src/errors.rs index b389f847..5fc05ad5 100644 --- a/crates/teloxide-core/src/errors.rs +++ b/crates/teloxide-core/src/errors.rs @@ -111,48 +111,46 @@ macro_rules! impl_api_error { $( #[$var_meta:meta] )* $var_name:ident $( ($var_inner:ty) )? = $var_string:literal $(with $var_parser: block)? ),* - } + } ) => { $(#[$meta])* #[derive(Error)] $vis enum $ident { $( - $(#[$var_meta])* #[error($var_string)] $var_name $(($var_inner))*, - )* } const _: () = { - struct Visitor; + struct Visitor; - impl<'de> ::serde::de::Visitor<'de> for Visitor { - type Value = $ident; + impl<'de> ::serde::de::Visitor<'de> for Visitor { + type Value = $ident; - fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { - formatter.write_str("telegram api error string") + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("telegram api error string") + } + + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + $(impl_api_error!(@de v, $var_name, $var_string $(, $var_parser)*);)* + Err(E::unknown_variant(v, &[])) + } } - fn visit_str(self, v: &str) -> Result - where - E: ::serde::de::Error, - { - $(impl_api_error!(@de v, $var_name, $var_string $(, $var_parser)*);)* - Err(E::unknown_variant(v, &[])) + impl<'de> ::serde::de::Deserialize<'de> for $ident { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::de::Deserializer<'de>, + { + deserializer.deserialize_str(Visitor) + } } - } - - impl<'de> ::serde::de::Deserialize<'de> for $ident { - fn deserialize(deserializer: D) -> Result - where - D: ::serde::de::Deserializer<'de>, - { - deserializer.deserialize_str(Visitor) - } - } }; }; (@de $value: ident, $variant: ident, $val: literal) => { @@ -169,546 +167,546 @@ macro_rules! impl_api_error { } impl_api_error! { -/// A kind of an API error. -#[derive(Debug, PartialEq, Hash, Eq, Clone)] -#[non_exhaustive] -pub enum ApiError { - /// Occurs when the bot tries to send message to user who blocked the bot. - BotBlocked = "Forbidden: bot was blocked by the user", - - /// Occurs when the bot token is incorrect. - // FIXME: rename this to something akin "InvalidToken" - NotFound = "Unauthorized", - - /// Occurs when bot tries to modify a message without modification content. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::payloads::EditMessageText - MessageNotModified = "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", - - /// Occurs when bot tries to forward or delete a message which was deleted. - /// - /// May happen in methods: - /// 1. [`ForwardMessage`] - /// 2. [`DeleteMessage`] - /// - /// [`ForwardMessage`]: crate::payloads::ForwardMessage - /// [`DeleteMessage`]: crate::payloads::DeleteMessage - MessageIdInvalid = "Bad Request: MESSAGE_ID_INVALID", - - /// Occurs when bot tries to forward a message which does not exists. - /// - /// May happen in methods: - /// 1. [`ForwardMessage`] - /// - /// [`ForwardMessage`]: crate::payloads::ForwardMessage - MessageToForwardNotFound = "Bad Request: message to forward not found", - - /// Occurs when bot tries to delete a message which does not exists. - /// - /// May happen in methods: - /// 1. [`DeleteMessage`] - /// - /// [`DeleteMessage`]: crate::payloads::DeleteMessage - MessageToDeleteNotFound = "Bad Request: message to delete not found", - - /// Occurs when bot tries to send a text message without text. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - MessageTextIsEmpty = "Bad Request: message text is empty", - - /// Occurs when bot tries to edit a message after long time. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::payloads::EditMessageText - MessageCantBeEdited = "Bad Request: message can't be edited", - - /// 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::payloads::DeleteMessage - MessageCantBeDeleted = "Bad Request: message can't be deleted", - - /// Occurs when bot tries to edit a message which does not exists. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// - /// [`EditMessageText`]: crate::payloads::EditMessageText - MessageToEditNotFound = "Bad Request: message to edit not found", - - /// Occurs when bot tries to reply to a message which does not exists. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - MessageToReplyNotFound = "Bad Request: reply message not found", - - /// Occurs when bot tries to - MessageIdentifierNotSpecified = "Bad Request: message identifier is not specified", - - /// Occurs when bot tries to send a message with text size greater then - /// 4096 symbols. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - MessageIsTooLong = "Bad Request: message is too long", - - /// Occurs when bot tries to edit a message with text size greater then - /// 4096 symbols. - /// - /// May happen in methods: - /// 1. [`EditMessageText`] - /// 2. [`EditMessageTextInline`] - /// 3. [`EditMessageCaption`] - /// 4. [`EditMessageCaptionInline`] - /// - /// [`EditMessageText`]: crate::payloads::EditMessageText - /// [`EditMessageTextInline`]: crate::payloads::EditMessageTextInline - /// [`EditMessageCaption`]: crate::payloads::EditMessageCaption - /// [`EditMessageCaptionInline`]: crate::payloads::EditMessageCaptionInline - EditedMessageIsTooLong = "Bad Request: MESSAGE_TOO_LONG", - - /// Occurs when bot tries to send media group with more than 10 items. - /// - /// May happen in methods: - /// 1. [`SendMediaGroup`] - /// - /// [`SendMediaGroup`]: crate::payloads::SendMediaGroup - ToMuchMessages = "Bad Request: Too much messages to send as an album", - - /// Occurs when bot tries to answer an inline query with more than 50 - /// results. - /// - /// Consider using offsets to paginate results. - /// - /// May happen in methods: - /// 1. [`AnswerInlineQuery`] - /// - /// [`AnswerInlineQuery`]: crate::payloads::AnswerInlineQuery - TooMuchInlineQueryResults = "Bad Request: RESULTS_TOO_MUCH", - - /// Occurs when bot tries to stop poll that has already been stopped. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollHasAlreadyClosed = "Bad Request: poll has already been closed", - - /// Occurs when bot tries to send poll with less than 2 options. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollMustHaveMoreOptions = "Bad Request: poll must have at least 2 option", - - /// Occurs when bot tries to send poll with more than 10 options. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollCantHaveMoreOptions = "Bad Request: poll can't have more than 10 options", - - /// Occurs when bot tries to send poll with empty option (without text). - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollOptionsMustBeNonEmpty = "Bad Request: poll options must be non-empty", - - /// Occurs when bot tries to send poll with empty question (without text). - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollQuestionMustBeNonEmpty = "Bad Request: poll question must be non-empty", - - /// Occurs when bot tries to send poll with total size of options more than - /// 100 symbols. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollOptionsLengthTooLong = "Bad Request: poll options length must not exceed 100", - - /// Occurs when bot tries to send poll with question size more than 255 - /// symbols. - /// - /// May happen in methods: - /// 1. [`SendPoll`] - /// - /// [`SendPoll`]: crate::payloads::SendPoll - PollQuestionLengthTooLong = "Bad Request: poll question length must not exceed 255", - - /// Occurs when bot tries to stop poll with message without poll. - /// - /// May happen in methods: - /// 1. [`StopPoll`] - /// - /// [`StopPoll`]: crate::payloads::StopPoll - MessageWithPollNotFound = "Bad Request: message with poll to stop not found", - - /// Occurs when bot tries to stop poll with message without poll. - /// - /// May happen in methods: - /// 1. [`StopPoll`] - /// - /// [`StopPoll`]: crate::payloads::StopPoll - MessageIsNotAPoll = "Bad Request: message is not a poll", - - /// 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::payloads::SendMessage - ChatNotFound = "Bad Request: chat not found", - - /// Occurs when bot tries to send method with unknown user_id. - /// - /// May happen in methods: - /// 1. [`getUserProfilePhotos`] - /// - /// [`getUserProfilePhotos`]: - /// crate::payloads::GetUserProfilePhotos - UserNotFound = "Bad Request: user not found", - - /// Occurs when bot tries to send [`SetChatDescription`] with same text as - /// in the current description. - /// - /// May happen in methods: - /// 1. [`SetChatDescription`] - /// - /// [`SetChatDescription`]: crate::payloads::SetChatDescription - ChatDescriptionIsNotModified = "Bad Request: chat description is not modified", - - /// Occurs when bot tries to answer to query after timeout expire. - /// - /// May happen in methods: - /// 1. [`AnswerCallbackQuery`] - /// - /// [`AnswerCallbackQuery`]: crate::payloads::AnswerCallbackQuery - InvalidQueryId = "Bad Request: query is too old and response timeout expired or query id is invalid", - - /// Occurs when bot tries to send InlineKeyboardMarkup with invalid button - /// url. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - ButtonUrlInvalid = "Bad Request: BUTTON_URL_INVALID", - - /// Occurs when bot tries to send button with data size more than 64 bytes. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - ButtonDataInvalid = "Bad Request: BUTTON_DATA_INVALID", - - /// Occurs when bot tries to send button with data size == 0. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - TextButtonsAreUnallowed = "Bad Request: can't parse inline keyboard button: Text buttons are unallowed in the \ - inline keyboard", - - /// Occurs when bot tries to get file by wrong file id. - /// - /// May happen in methods: - /// 1. [`GetFile`] - /// - /// [`GetFile`]: crate::payloads::GetFile - WrongFileId = "Bad Request: wrong file id", - - /// Occurs when bot tries to send files with wrong file identifier or HTTP - /// url - WrongFileIdOrUrl = "Bad Request: wrong file identifier/HTTP URL specified", - - /// Occurs when When sending files with an url to a site that doesn't - /// respond. - FailedToGetUrlContent = "Bad Request: failed to get HTTP URL content", - - /// Occurs when bot tries to do some with group which was deactivated. - GroupDeactivated = "Bad Request: group is deactivated", - - /// Occurs when image processing fails on telegram's side. - /// - /// This is likely caused by an incorrectly encoded image, make sure that - /// the image is correctly encoded in a format telegram accepts. - ImageProcessFailed = "Bad Request: IMAGE_PROCESS_FAILED", - - /// Occurs when bot tries to set chat photo from file ID - /// - /// May happen in methods: - /// 1. [`SetChatPhoto`] - /// - /// [`SetChatPhoto`]: crate::payloads::SetChatPhoto - PhotoAsInputFileRequired = "Bad Request: Photo should be uploaded as an InputFile", - - /// Occurs when bot tries to add sticker to stickerset by invalid name. - /// - /// May happen in methods: - /// 1. [`AddStickerToSet`] - /// - /// [`AddStickerToSet`]: crate::payloads::AddStickerToSet - InvalidStickersSet = "Bad Request: STICKERSET_INVALID", - - /// Occurs when bot tries to create a sticker set with a name that is - /// already used by another sticker set. - /// - /// May happen in methods: - /// 1. [`CreateNewStickerSet`] - /// - /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet - StickerSetNameOccupied = "Bad Request: sticker set name is already occupied", - - /// Occurs when bot tries to create a sticker set with user id of a bot. - /// - /// May happen in methods: - /// 1. [`CreateNewStickerSet`] - /// - /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet - StickerSetOwnerIsBot = "Bad Request: USER_IS_BOT", - - /// Occurs when bot tries to create a sticker set with invalid name. - /// - /// From documentation of [`CreateNewStickerSet`]: - /// > Short name of sticker set, to be used in `t.me/addstickers/` URLs - /// (e.g., _animals_). Can contain only english letters, digits and - /// underscores. Must begin with a letter, can't contain consecutive - /// underscores and must end in “\_by\_”. - /// is case insensitive. 1-64 characters. - /// - /// May happen in methods: - /// 1. [`CreateNewStickerSet`] - /// - /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet - InvalidStickerName = "Bad Request: invalid sticker set name is specified", - - /// Occurs when bot tries to pin a message without rights to pin in this - /// chat. - /// - /// May happen in methods: - /// 1. [`PinChatMessage`] - /// - /// [`PinChatMessage`]: crate::payloads::PinChatMessage - NotEnoughRightsToPinMessage = "Bad Request: not enough rights to pin a message", - - /// Occurs when bot tries to pin or unpin a message without rights to pin - /// in this chat. - /// - /// May happen in methods: - /// 1. [`PinChatMessage`] - /// 2. [`UnpinChatMessage`] - /// - /// [`PinChatMessage`]: crate::payloads::PinChatMessage - /// [`UnpinChatMessage`]: crate::payloads::UnpinChatMessage - NotEnoughRightsToManagePins = "Bad Request: not enough rights to manage pinned messages in the chat", - - /// Occurs when bot tries change default chat permissions without "Ban - /// Users" permission in this chat. - /// - /// May happen in methods: - /// 1. [`SetChatPermissions`] - /// - /// [`SetChatPermissions`]: crate::payloads::SetChatPermissions - NotEnoughRightsToChangeChatPermissions = "Bad Request: not enough rights to change chat permissions", - - /// Occurs when bot tries to use method in group which is allowed only in a - /// supergroup or channel. - MethodNotAvailableInPrivateChats = "Bad Request: method is available only for supergroups and channel", - - /// Occurs when bot tries to demote chat creator. - /// - /// May happen in methods: - /// 1. [`PromoteChatMember`] - /// - /// [`PromoteChatMember`]: crate::payloads::PromoteChatMember - CantDemoteChatCreator = "Bad Request: can't demote chat creator", - - /// Occurs when bot tries to restrict self in group chats. - /// - /// May happen in methods: - /// 1. [`RestrictChatMember`] - /// - /// [`RestrictChatMember`]: crate::payloads::RestrictChatMember - CantRestrictSelf = "Bad Request: can't restrict self", - - /// Occurs when bot tries to restrict chat member without rights to - /// restrict in this chat. - /// - /// May happen in methods: - /// 1. [`RestrictChatMember`] - /// - /// [`RestrictChatMember`]: crate::payloads::RestrictChatMember - NotEnoughRightsToRestrict = "Bad Request: not enough rights to restrict/unrestrict chat member", - - /// Occurs when bot tries to post a message in a channel without "Post - /// Messages" admin right. - NotEnoughRightsToPostMessages = "Bad Request: need administrator rights in the channel chat", - - /// Occurs when bot tries set webhook to protocol other than HTTPS. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::payloads::SetWebhook - WebhookRequireHttps = "Bad Request: bad webhook: HTTPS url must be provided for webhook", - - /// Occurs when bot tries to set webhook to port other than 80, 88, 443 or - /// 8443. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::payloads::SetWebhook - BadWebhookPort = "Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443", - - /// Occurs when bot tries to set webhook to unknown host. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::payloads::SetWebhook - UnknownHost = "Bad Request: bad webhook: Failed to resolve host: Name or service not known", - - /// Occurs when bot tries to set webhook to invalid URL. - /// - /// May happen in methods: - /// 1. [`SetWebhook`] - /// - /// [`SetWebhook`]: crate::payloads::SetWebhook - CantParseUrl = "Bad Request: can't parse URL", - - /// Occurs when bot tries to send message with unfinished entities. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - CantParseEntities(String) = "{0}" with {match_prefix!("Bad Request: can't parse entities")}, - - /// Occurs when bot tries to use getUpdates while webhook is active. - /// - /// May happen in methods: - /// 1. [`GetUpdates`] - /// - /// [`GetUpdates`]: crate::payloads::GetUpdates - CantGetUpdates = "can't use getUpdates method while webhook is active", - - /// Occurs when bot tries to do some in group where bot was kicked. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - BotKicked = "Unauthorized: bot was kicked from a chat", - - /// Occurs when bot tries to do something in a supergroup the bot was - /// kicked from. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - BotKickedFromSupergroup = "Forbidden: bot was kicked from the supergroup chat", - - /// Occurs when bot tries to send a message to a deactivated user (i.e. a - /// user that was banned by telegram). - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - UserDeactivated = "Forbidden: user is deactivated", - - /// Occurs when you tries to initiate conversation with a user. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - CantInitiateConversation = "Unauthorized: bot can't initiate conversation with a user", - - /// Occurs when you tries to send message to bot. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - CantTalkWithBots = "Unauthorized: bot can't send messages to bots", - - /// Occurs when bot tries to send button with invalid http url. - /// - /// May happen in methods: - /// 1. [`SendMessage`] - /// - /// [`SendMessage`]: crate::payloads::SendMessage - WrongHttpUrl = "Bad Request: wrong HTTP URL", - - /// Occurs when bot tries GetUpdate before the timeout. Make sure that only - /// one Updater is running. - /// - /// May happen in methods: - /// 1. [`GetUpdates`] - /// - /// [`GetUpdates`]: crate::payloads::GetUpdates - TerminatedByOtherGetUpdates = "Conflict: terminated by other getUpdates request; make sure that only one bot instance \ - is running", - - /// Occurs when bot tries to get file by invalid file id. - /// - /// May happen in methods: - /// 1. [`GetFile`] - /// - /// [`GetFile`]: crate::payloads::GetFile - FileIdInvalid = "Bad Request: invalid file id", - - /// Occurs when bot tries to upload a file which is larger than 50 MB using - /// multipart/form-data. - /// - /// May happen in methods: - /// 1. [`SendVideo`] - /// 2. [`SendDocument`] - /// - /// [`SendVideo`]: crate::payloads::SendVideo - /// [`SendDocument`]: crate::payloads::SendDocument - RequestEntityTooLarge = "Request Entity Too Large", - - - /// Error which is not known to `teloxide`. - /// - /// If you've received this error, please [open an issue] with the - /// description of the error. - /// - /// [open an issue]: https://github.com/teloxide/teloxide/issues/new - Unknown(String) = "Unknown error: {0:?}" with {match_prefix!("")} -} + /// A kind of an API error. + #[derive(Debug, PartialEq, Hash, Eq, Clone)] + #[non_exhaustive] + pub enum ApiError { + /// Occurs when the bot tries to send message to user who blocked the bot. + BotBlocked = "Forbidden: bot was blocked by the user", + + /// Occurs when the bot token is incorrect. + // FIXME: rename this to something akin "InvalidToken" + NotFound = "Unauthorized", + + /// Occurs when bot tries to modify a message without modification content. + /// + /// May happen in methods: + /// 1. [`EditMessageText`] + /// + /// [`EditMessageText`]: crate::payloads::EditMessageText + MessageNotModified = "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", + + /// Occurs when bot tries to forward or delete a message which was deleted. + /// + /// May happen in methods: + /// 1. [`ForwardMessage`] + /// 2. [`DeleteMessage`] + /// + /// [`ForwardMessage`]: crate::payloads::ForwardMessage + /// [`DeleteMessage`]: crate::payloads::DeleteMessage + MessageIdInvalid = "Bad Request: MESSAGE_ID_INVALID", + + /// Occurs when bot tries to forward a message which does not exists. + /// + /// May happen in methods: + /// 1. [`ForwardMessage`] + /// + /// [`ForwardMessage`]: crate::payloads::ForwardMessage + MessageToForwardNotFound = "Bad Request: message to forward not found", + + /// Occurs when bot tries to delete a message which does not exists. + /// + /// May happen in methods: + /// 1. [`DeleteMessage`] + /// + /// [`DeleteMessage`]: crate::payloads::DeleteMessage + MessageToDeleteNotFound = "Bad Request: message to delete not found", + + /// Occurs when bot tries to send a text message without text. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + MessageTextIsEmpty = "Bad Request: message text is empty", + + /// Occurs when bot tries to edit a message after long time. + /// + /// May happen in methods: + /// 1. [`EditMessageText`] + /// + /// [`EditMessageText`]: crate::payloads::EditMessageText + MessageCantBeEdited = "Bad Request: message can't be edited", + + /// 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::payloads::DeleteMessage + MessageCantBeDeleted = "Bad Request: message can't be deleted", + + /// Occurs when bot tries to edit a message which does not exists. + /// + /// May happen in methods: + /// 1. [`EditMessageText`] + /// + /// [`EditMessageText`]: crate::payloads::EditMessageText + MessageToEditNotFound = "Bad Request: message to edit not found", + + /// Occurs when bot tries to reply to a message which does not exists. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + MessageToReplyNotFound = "Bad Request: reply message not found", + + /// Occurs when bot tries to + MessageIdentifierNotSpecified = "Bad Request: message identifier is not specified", + + /// Occurs when bot tries to send a message with text size greater then + /// 4096 symbols. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + MessageIsTooLong = "Bad Request: message is too long", + + /// Occurs when bot tries to edit a message with text size greater then + /// 4096 symbols. + /// + /// May happen in methods: + /// 1. [`EditMessageText`] + /// 2. [`EditMessageTextInline`] + /// 3. [`EditMessageCaption`] + /// 4. [`EditMessageCaptionInline`] + /// + /// [`EditMessageText`]: crate::payloads::EditMessageText + /// [`EditMessageTextInline`]: crate::payloads::EditMessageTextInline + /// [`EditMessageCaption`]: crate::payloads::EditMessageCaption + /// [`EditMessageCaptionInline`]: crate::payloads::EditMessageCaptionInline + EditedMessageIsTooLong = "Bad Request: MESSAGE_TOO_LONG", + + /// Occurs when bot tries to send media group with more than 10 items. + /// + /// May happen in methods: + /// 1. [`SendMediaGroup`] + /// + /// [`SendMediaGroup`]: crate::payloads::SendMediaGroup + ToMuchMessages = "Bad Request: Too much messages to send as an album", + + /// Occurs when bot tries to answer an inline query with more than 50 + /// results. + /// + /// Consider using offsets to paginate results. + /// + /// May happen in methods: + /// 1. [`AnswerInlineQuery`] + /// + /// [`AnswerInlineQuery`]: crate::payloads::AnswerInlineQuery + TooMuchInlineQueryResults = "Bad Request: RESULTS_TOO_MUCH", + + /// Occurs when bot tries to stop poll that has already been stopped. + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollHasAlreadyClosed = "Bad Request: poll has already been closed", + + /// Occurs when bot tries to send poll with less than 2 options. + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollMustHaveMoreOptions = "Bad Request: poll must have at least 2 option", + + /// Occurs when bot tries to send poll with more than 10 options. + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollCantHaveMoreOptions = "Bad Request: poll can't have more than 10 options", + + /// Occurs when bot tries to send poll with empty option (without text). + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollOptionsMustBeNonEmpty = "Bad Request: poll options must be non-empty", + + /// Occurs when bot tries to send poll with empty question (without text). + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollQuestionMustBeNonEmpty = "Bad Request: poll question must be non-empty", + + /// Occurs when bot tries to send poll with total size of options more than + /// 100 symbols. + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollOptionsLengthTooLong = "Bad Request: poll options length must not exceed 100", + + /// Occurs when bot tries to send poll with question size more than 255 + /// symbols. + /// + /// May happen in methods: + /// 1. [`SendPoll`] + /// + /// [`SendPoll`]: crate::payloads::SendPoll + PollQuestionLengthTooLong = "Bad Request: poll question length must not exceed 255", + + /// Occurs when bot tries to stop poll with message without poll. + /// + /// May happen in methods: + /// 1. [`StopPoll`] + /// + /// [`StopPoll`]: crate::payloads::StopPoll + MessageWithPollNotFound = "Bad Request: message with poll to stop not found", + + /// Occurs when bot tries to stop poll with message without poll. + /// + /// May happen in methods: + /// 1. [`StopPoll`] + /// + /// [`StopPoll`]: crate::payloads::StopPoll + MessageIsNotAPoll = "Bad Request: message is not a poll", + + /// 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::payloads::SendMessage + ChatNotFound = "Bad Request: chat not found", + + /// Occurs when bot tries to send method with unknown user_id. + /// + /// May happen in methods: + /// 1. [`getUserProfilePhotos`] + /// + /// [`getUserProfilePhotos`]: + /// crate::payloads::GetUserProfilePhotos + UserNotFound = "Bad Request: user not found", + + /// Occurs when bot tries to send [`SetChatDescription`] with same text as + /// in the current description. + /// + /// May happen in methods: + /// 1. [`SetChatDescription`] + /// + /// [`SetChatDescription`]: crate::payloads::SetChatDescription + ChatDescriptionIsNotModified = "Bad Request: chat description is not modified", + + /// Occurs when bot tries to answer to query after timeout expire. + /// + /// May happen in methods: + /// 1. [`AnswerCallbackQuery`] + /// + /// [`AnswerCallbackQuery`]: crate::payloads::AnswerCallbackQuery + InvalidQueryId = "Bad Request: query is too old and response timeout expired or query id is invalid", + + /// Occurs when bot tries to send InlineKeyboardMarkup with invalid button + /// url. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + ButtonUrlInvalid = "Bad Request: BUTTON_URL_INVALID", + + /// Occurs when bot tries to send button with data size more than 64 bytes. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + ButtonDataInvalid = "Bad Request: BUTTON_DATA_INVALID", + + /// Occurs when bot tries to send button with data size == 0. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + TextButtonsAreUnallowed = "Bad Request: can't parse inline keyboard button: Text buttons are unallowed in the \ + inline keyboard", + + /// Occurs when bot tries to get file by wrong file id. + /// + /// May happen in methods: + /// 1. [`GetFile`] + /// + /// [`GetFile`]: crate::payloads::GetFile + WrongFileId = "Bad Request: wrong file id", + + /// Occurs when bot tries to send files with wrong file identifier or HTTP + /// url + WrongFileIdOrUrl = "Bad Request: wrong file identifier/HTTP URL specified", + + /// Occurs when When sending files with an url to a site that doesn't + /// respond. + FailedToGetUrlContent = "Bad Request: failed to get HTTP URL content", + + /// Occurs when bot tries to do some with group which was deactivated. + GroupDeactivated = "Bad Request: group is deactivated", + + /// Occurs when image processing fails on telegram's side. + /// + /// This is likely caused by an incorrectly encoded image, make sure that + /// the image is correctly encoded in a format telegram accepts. + ImageProcessFailed = "Bad Request: IMAGE_PROCESS_FAILED", + + /// Occurs when bot tries to set chat photo from file ID + /// + /// May happen in methods: + /// 1. [`SetChatPhoto`] + /// + /// [`SetChatPhoto`]: crate::payloads::SetChatPhoto + PhotoAsInputFileRequired = "Bad Request: Photo should be uploaded as an InputFile", + + /// Occurs when bot tries to add sticker to stickerset by invalid name. + /// + /// May happen in methods: + /// 1. [`AddStickerToSet`] + /// + /// [`AddStickerToSet`]: crate::payloads::AddStickerToSet + InvalidStickersSet = "Bad Request: STICKERSET_INVALID", + + /// Occurs when bot tries to create a sticker set with a name that is + /// already used by another sticker set. + /// + /// May happen in methods: + /// 1. [`CreateNewStickerSet`] + /// + /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet + StickerSetNameOccupied = "Bad Request: sticker set name is already occupied", + + /// Occurs when bot tries to create a sticker set with user id of a bot. + /// + /// May happen in methods: + /// 1. [`CreateNewStickerSet`] + /// + /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet + StickerSetOwnerIsBot = "Bad Request: USER_IS_BOT", + + /// Occurs when bot tries to create a sticker set with invalid name. + /// + /// From documentation of [`CreateNewStickerSet`]: + /// > Short name of sticker set, to be used in `t.me/addstickers/` URLs + /// (e.g., _animals_). Can contain only english letters, digits and + /// underscores. Must begin with a letter, can't contain consecutive + /// underscores and must end in “\_by\_”. + /// is case insensitive. 1-64 characters. + /// + /// May happen in methods: + /// 1. [`CreateNewStickerSet`] + /// + /// [`CreateNewStickerSet`]: crate::payloads::CreateNewStickerSet + InvalidStickerName = "Bad Request: invalid sticker set name is specified", + + /// Occurs when bot tries to pin a message without rights to pin in this + /// chat. + /// + /// May happen in methods: + /// 1. [`PinChatMessage`] + /// + /// [`PinChatMessage`]: crate::payloads::PinChatMessage + NotEnoughRightsToPinMessage = "Bad Request: not enough rights to pin a message", + + /// Occurs when bot tries to pin or unpin a message without rights to pin + /// in this chat. + /// + /// May happen in methods: + /// 1. [`PinChatMessage`] + /// 2. [`UnpinChatMessage`] + /// + /// [`PinChatMessage`]: crate::payloads::PinChatMessage + /// [`UnpinChatMessage`]: crate::payloads::UnpinChatMessage + NotEnoughRightsToManagePins = "Bad Request: not enough rights to manage pinned messages in the chat", + + /// Occurs when bot tries change default chat permissions without "Ban + /// Users" permission in this chat. + /// + /// May happen in methods: + /// 1. [`SetChatPermissions`] + /// + /// [`SetChatPermissions`]: crate::payloads::SetChatPermissions + NotEnoughRightsToChangeChatPermissions = "Bad Request: not enough rights to change chat permissions", + + /// Occurs when bot tries to use method in group which is allowed only in a + /// supergroup or channel. + MethodNotAvailableInPrivateChats = "Bad Request: method is available only for supergroups and channel", + + /// Occurs when bot tries to demote chat creator. + /// + /// May happen in methods: + /// 1. [`PromoteChatMember`] + /// + /// [`PromoteChatMember`]: crate::payloads::PromoteChatMember + CantDemoteChatCreator = "Bad Request: can't demote chat creator", + + /// Occurs when bot tries to restrict self in group chats. + /// + /// May happen in methods: + /// 1. [`RestrictChatMember`] + /// + /// [`RestrictChatMember`]: crate::payloads::RestrictChatMember + CantRestrictSelf = "Bad Request: can't restrict self", + + /// Occurs when bot tries to restrict chat member without rights to + /// restrict in this chat. + /// + /// May happen in methods: + /// 1. [`RestrictChatMember`] + /// + /// [`RestrictChatMember`]: crate::payloads::RestrictChatMember + NotEnoughRightsToRestrict = "Bad Request: not enough rights to restrict/unrestrict chat member", + + /// Occurs when bot tries to post a message in a channel without "Post + /// Messages" admin right. + NotEnoughRightsToPostMessages = "Bad Request: need administrator rights in the channel chat", + + /// Occurs when bot tries set webhook to protocol other than HTTPS. + /// + /// May happen in methods: + /// 1. [`SetWebhook`] + /// + /// [`SetWebhook`]: crate::payloads::SetWebhook + WebhookRequireHttps = "Bad Request: bad webhook: HTTPS url must be provided for webhook", + + /// Occurs when bot tries to set webhook to port other than 80, 88, 443 or + /// 8443. + /// + /// May happen in methods: + /// 1. [`SetWebhook`] + /// + /// [`SetWebhook`]: crate::payloads::SetWebhook + BadWebhookPort = "Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443", + + /// Occurs when bot tries to set webhook to unknown host. + /// + /// May happen in methods: + /// 1. [`SetWebhook`] + /// + /// [`SetWebhook`]: crate::payloads::SetWebhook + UnknownHost = "Bad Request: bad webhook: Failed to resolve host: Name or service not known", + + /// Occurs when bot tries to set webhook to invalid URL. + /// + /// May happen in methods: + /// 1. [`SetWebhook`] + /// + /// [`SetWebhook`]: crate::payloads::SetWebhook + CantParseUrl = "Bad Request: can't parse URL", + + /// Occurs when bot tries to send message with unfinished entities. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + CantParseEntities(String) = "{0}" with {match_prefix!("Bad Request: can't parse entities")}, + + /// Occurs when bot tries to use getUpdates while webhook is active. + /// + /// May happen in methods: + /// 1. [`GetUpdates`] + /// + /// [`GetUpdates`]: crate::payloads::GetUpdates + CantGetUpdates = "can't use getUpdates method while webhook is active", + + /// Occurs when bot tries to do some in group where bot was kicked. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + BotKicked = "Unauthorized: bot was kicked from a chat", + + /// Occurs when bot tries to do something in a supergroup the bot was + /// kicked from. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + BotKickedFromSupergroup = "Forbidden: bot was kicked from the supergroup chat", + + /// Occurs when bot tries to send a message to a deactivated user (i.e. a + /// user that was banned by telegram). + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + UserDeactivated = "Forbidden: user is deactivated", + + /// Occurs when you tries to initiate conversation with a user. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + CantInitiateConversation = "Unauthorized: bot can't initiate conversation with a user", + + /// Occurs when you tries to send message to bot. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + CantTalkWithBots = "Unauthorized: bot can't send messages to bots", + + /// Occurs when bot tries to send button with invalid http url. + /// + /// May happen in methods: + /// 1. [`SendMessage`] + /// + /// [`SendMessage`]: crate::payloads::SendMessage + WrongHttpUrl = "Bad Request: wrong HTTP URL", + + /// Occurs when bot tries GetUpdate before the timeout. Make sure that only + /// one Updater is running. + /// + /// May happen in methods: + /// 1. [`GetUpdates`] + /// + /// [`GetUpdates`]: crate::payloads::GetUpdates + TerminatedByOtherGetUpdates = "Conflict: terminated by other getUpdates request; make sure that only one bot instance \ + is running", + + /// Occurs when bot tries to get file by invalid file id. + /// + /// May happen in methods: + /// 1. [`GetFile`] + /// + /// [`GetFile`]: crate::payloads::GetFile + FileIdInvalid = "Bad Request: invalid file id", + + /// Occurs when bot tries to upload a file which is larger than 50 MB using + /// multipart/form-data. + /// + /// May happen in methods: + /// 1. [`SendVideo`] + /// 2. [`SendDocument`] + /// + /// [`SendVideo`]: crate::payloads::SendVideo + /// [`SendDocument`]: crate::payloads::SendDocument + RequestEntityTooLarge = "Request Entity Too Large", + + + /// Error which is not known to `teloxide`. + /// + /// If you've received this error, please [open an issue] with the + /// description of the error. + /// + /// [open an issue]: https://github.com/teloxide/teloxide/issues/new + Unknown(String) = "Unknown error: {0:?}" with {match_prefix!("")} + } } /// This impl allows to use `?` to propagate [`DownloadError`]s in function @@ -798,3 +796,230 @@ pub(crate) fn hide_token(mut error: reqwest::Error) -> reqwest::Error { // couldn't find token in the url, hide the whole url error.without_url() } + +#[cfg(test)] +mod tests { + #[test] + fn custom_result() { + use super::ApiError; + use serde::Deserialize; + + let cases = &[ + ("{\"data\": \"Forbidden: bot was blocked by the user\"}", ApiError::BotBlocked), + ("{\"data\": \"Unauthorized\"}", ApiError::NotFound), + ( + "{\"data\": \"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\"}", + ApiError::MessageNotModified, + ), + ("{\"data\": \"Bad Request: MESSAGE_ID_INVALID\"}", ApiError::MessageIdInvalid), + ( + "{\"data\": \"Bad Request: message to forward not found\"}", + ApiError::MessageToForwardNotFound, + ), + ( + "{\"data\": \"Bad Request: message to delete not found\"}", + ApiError::MessageToDeleteNotFound, + ), + ("{\"data\": \"Bad Request: message text is empty\"}", ApiError::MessageTextIsEmpty), + ("{\"data\": \"Bad Request: message can't be edited\"}", ApiError::MessageCantBeEdited), + ( + "{\"data\": \"Bad Request: message can't be deleted\"}", + ApiError::MessageCantBeDeleted, + ), + ( + "{\"data\": \"Bad Request: message to edit not found\"}", + ApiError::MessageToEditNotFound, + ), + ( + "{\"data\": \"Bad Request: reply message not found\"}", + ApiError::MessageToReplyNotFound, + ), + ( + "{\"data\": \"Bad Request: message identifier is not specified\"}", + ApiError::MessageIdentifierNotSpecified, + ), + ("{\"data\": \"Bad Request: message is too long\"}", ApiError::MessageIsTooLong), + ("{\"data\": \"Bad Request: MESSAGE_TOO_LONG\"}", ApiError::EditedMessageIsTooLong), + ( + "{\"data\": \"Bad Request: Too much messages to send as an album\"}", + ApiError::ToMuchMessages, + ), + ("{\"data\": \"Bad Request: RESULTS_TOO_MUCH\"}", ApiError::TooMuchInlineQueryResults), + ( + "{\"data\": \"Bad Request: poll has already been closed\"}", + ApiError::PollHasAlreadyClosed, + ), + ( + "{\"data\": \"Bad Request: poll must have at least 2 option\"}", + ApiError::PollMustHaveMoreOptions, + ), + ( + "{\"data\": \"Bad Request: poll can't have more than 10 options\"}", + ApiError::PollCantHaveMoreOptions, + ), + ( + "{\"data\": \"Bad Request: poll options must be non-empty\"}", + ApiError::PollOptionsMustBeNonEmpty, + ), + ( + "{\"data\": \"Bad Request: poll question must be non-empty\"}", + ApiError::PollQuestionMustBeNonEmpty, + ), + ( + "{\"data\": \"Bad Request: poll options length must not exceed 100\"}", + ApiError::PollOptionsLengthTooLong, + ), + ( + "{\"data\": \"Bad Request: poll question length must not exceed 255\"}", + ApiError::PollQuestionLengthTooLong, + ), + ( + "{\"data\": \"Bad Request: message with poll to stop not found\"}", + ApiError::MessageWithPollNotFound, + ), + ("{\"data\": \"Bad Request: message is not a poll\"}", ApiError::MessageIsNotAPoll), + ("{\"data\": \"Bad Request: chat not found\"}", ApiError::ChatNotFound), + ("{\"data\": \"Bad Request: user not found\"}", ApiError::UserNotFound), + ( + "{\"data\": \"Bad Request: chat description is not modified\"}", + ApiError::ChatDescriptionIsNotModified, + ), + ( + "{\"data\": \"Bad Request: query is too old and response timeout expired or query \ + id is invalid\"}", + ApiError::InvalidQueryId, + ), + ("{\"data\": \"Bad Request: BUTTON_URL_INVALID\"}", ApiError::ButtonUrlInvalid), + ("{\"data\": \"Bad Request: BUTTON_DATA_INVALID\"}", ApiError::ButtonDataInvalid), + ( + "{\"data\": \"Bad Request: can't parse inline keyboard button: Text buttons are \ + unallowed in the inline keyboard\"}", + ApiError::TextButtonsAreUnallowed, + ), + ("{\"data\": \"Bad Request: wrong file id\"}", ApiError::WrongFileId), + ( + "{\"data\": \"Bad Request: wrong file identifier/HTTP URL specified\"}", + ApiError::WrongFileIdOrUrl, + ), + ( + "{\"data\": \"Bad Request: failed to get HTTP URL content\"}", + ApiError::FailedToGetUrlContent, + ), + ("{\"data\": \"Bad Request: group is deactivated\"}", ApiError::GroupDeactivated), + ("{\"data\": \"Bad Request: IMAGE_PROCESS_FAILED\"}", ApiError::ImageProcessFailed), + ( + "{\"data\": \"Bad Request: Photo should be uploaded as an InputFile\"}", + ApiError::PhotoAsInputFileRequired, + ), + ("{\"data\": \"Bad Request: STICKERSET_INVALID\"}", ApiError::InvalidStickersSet), + ( + "{\"data\": \"Bad Request: sticker set name is already occupied\"}", + ApiError::StickerSetNameOccupied, + ), + ("{\"data\": \"Bad Request: USER_IS_BOT\"}", ApiError::StickerSetOwnerIsBot), + ( + "{\"data\": \"Bad Request: invalid sticker set name is specified\"}", + ApiError::InvalidStickerName, + ), + ( + "{\"data\": \"Bad Request: not enough rights to pin a message\"}", + ApiError::NotEnoughRightsToPinMessage, + ), + ( + "{\"data\": \"Bad Request: not enough rights to manage pinned messages in the \ + chat\"}", + ApiError::NotEnoughRightsToManagePins, + ), + ( + "{\"data\": \"Bad Request: not enough rights to change chat permissions\"}", + ApiError::NotEnoughRightsToChangeChatPermissions, + ), + ( + "{\"data\": \"Bad Request: method is available only for supergroups and channel\"}", + ApiError::MethodNotAvailableInPrivateChats, + ), + ( + "{\"data\": \"Bad Request: can't demote chat creator\"}", + ApiError::CantDemoteChatCreator, + ), + ("{\"data\": \"Bad Request: can't restrict self\"}", ApiError::CantRestrictSelf), + ( + "{\"data\": \"Bad Request: not enough rights to restrict/unrestrict chat member\"}", + ApiError::NotEnoughRightsToRestrict, + ), + ( + "{\"data\": \"Bad Request: need administrator rights in the channel chat\"}", + ApiError::NotEnoughRightsToPostMessages, + ), + ( + "{\"data\": \"Bad Request: bad webhook: HTTPS url must be provided for webhook\"}", + ApiError::WebhookRequireHttps, + ), + ( + "{\"data\": \"Bad Request: bad webhook: Webhook can be set up only on ports 80, \ + 88, 443 or 8443\"}", + ApiError::BadWebhookPort, + ), + ( + "{\"data\": \"Bad Request: bad webhook: Failed to resolve host: Name or service \ + not known\"}", + ApiError::UnknownHost, + ), + ("{\"data\": \"Bad Request: can't parse URL\"}", ApiError::CantParseUrl), + ( + "{\"data\": \"Bad Request: can't parse entities: SomeRandomString\"}", + ApiError::CantParseEntities( + "Bad Request: can't parse entities: SomeRandomString".to_owned(), + ), + ), + ( + "{\"data\": \"can't use getUpdates method while webhook is active\"}", + ApiError::CantGetUpdates, + ), + ("{\"data\": \"Unauthorized: bot was kicked from a chat\"}", ApiError::BotKicked), + ( + "{\"data\": \"Forbidden: bot was kicked from the supergroup chat\"}", + ApiError::BotKickedFromSupergroup, + ), + ("{\"data\": \"Forbidden: user is deactivated\"}", ApiError::UserDeactivated), + ( + "{\"data\": \"Unauthorized: bot can't initiate conversation with a user\"}", + ApiError::CantInitiateConversation, + ), + ( + "{\"data\": \"Unauthorized: bot can't send messages to bots\"}", + ApiError::CantTalkWithBots, + ), + ("{\"data\": \"Bad Request: wrong HTTP URL\"}", ApiError::WrongHttpUrl), + ( + "{\"data\": \"Conflict: terminated by other getUpdates request; make sure that \ + only one bot instance is running\"}", + ApiError::TerminatedByOtherGetUpdates, + ), + ("{\"data\": \"Bad Request: invalid file id\"}", ApiError::FileIdInvalid), + ("{\"data\": \"Request Entity Too Large\"}", ApiError::RequestEntityTooLarge), + ("{\"data\": \"RandomError\"}", ApiError::Unknown("RandomError".to_string())), + ]; + + #[derive(Deserialize, Debug)] + struct Res { + data: T, + } + + for (data, expected) in cases { + let raw = serde_json::from_str::>(data).unwrap().data; + let parsed = serde_json::from_str::>(data).unwrap().data; + assert_eq!(&parsed, expected); + + let expected_error_message = match parsed { + ApiError::Unknown(_) => { + format!("Unknown error: \"{raw}\"") + } + _ => raw, + }; + assert_eq!(parsed.to_string(), expected_error_message); + } + } +} diff --git a/crates/teloxide/tests/errors.rs b/crates/teloxide/tests/errors.rs deleted file mode 100644 index f0edcf78..00000000 --- a/crates/teloxide/tests/errors.rs +++ /dev/null @@ -1,212 +0,0 @@ -use serde::Deserialize; - -#[test] -fn custom_result() { - use teloxide_core::ApiError; - - let cases = &[ - ("{\"data\": \"Forbidden: bot was blocked by the user\"}", ApiError::BotBlocked), - ("{\"data\": \"Unauthorized\"}", ApiError::NotFound), - ( - "{\"data\": \"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\"}", - ApiError::MessageNotModified, - ), - ("{\"data\": \"Bad Request: MESSAGE_ID_INVALID\"}", ApiError::MessageIdInvalid), - ( - "{\"data\": \"Bad Request: message to forward not found\"}", - ApiError::MessageToForwardNotFound, - ), - ( - "{\"data\": \"Bad Request: message to delete not found\"}", - ApiError::MessageToDeleteNotFound, - ), - ("{\"data\": \"Bad Request: message text is empty\"}", ApiError::MessageTextIsEmpty), - ("{\"data\": \"Bad Request: message can't be edited\"}", ApiError::MessageCantBeEdited), - ("{\"data\": \"Bad Request: message can't be deleted\"}", ApiError::MessageCantBeDeleted), - ("{\"data\": \"Bad Request: message to edit not found\"}", ApiError::MessageToEditNotFound), - ("{\"data\": \"Bad Request: reply message not found\"}", ApiError::MessageToReplyNotFound), - ( - "{\"data\": \"Bad Request: message identifier is not specified\"}", - ApiError::MessageIdentifierNotSpecified, - ), - ("{\"data\": \"Bad Request: message is too long\"}", ApiError::MessageIsTooLong), - ("{\"data\": \"Bad Request: MESSAGE_TOO_LONG\"}", ApiError::EditedMessageIsTooLong), - ( - "{\"data\": \"Bad Request: Too much messages to send as an album\"}", - ApiError::ToMuchMessages, - ), - ("{\"data\": \"Bad Request: RESULTS_TOO_MUCH\"}", ApiError::TooMuchInlineQueryResults), - ( - "{\"data\": \"Bad Request: poll has already been closed\"}", - ApiError::PollHasAlreadyClosed, - ), - ( - "{\"data\": \"Bad Request: poll must have at least 2 option\"}", - ApiError::PollMustHaveMoreOptions, - ), - ( - "{\"data\": \"Bad Request: poll can't have more than 10 options\"}", - ApiError::PollCantHaveMoreOptions, - ), - ( - "{\"data\": \"Bad Request: poll options must be non-empty\"}", - ApiError::PollOptionsMustBeNonEmpty, - ), - ( - "{\"data\": \"Bad Request: poll question must be non-empty\"}", - ApiError::PollQuestionMustBeNonEmpty, - ), - ( - "{\"data\": \"Bad Request: poll options length must not exceed 100\"}", - ApiError::PollOptionsLengthTooLong, - ), - ( - "{\"data\": \"Bad Request: poll question length must not exceed 255\"}", - ApiError::PollQuestionLengthTooLong, - ), - ( - "{\"data\": \"Bad Request: message with poll to stop not found\"}", - ApiError::MessageWithPollNotFound, - ), - ("{\"data\": \"Bad Request: message is not a poll\"}", ApiError::MessageIsNotAPoll), - ("{\"data\": \"Bad Request: chat not found\"}", ApiError::ChatNotFound), - ("{\"data\": \"Bad Request: user not found\"}", ApiError::UserNotFound), - ( - "{\"data\": \"Bad Request: chat description is not modified\"}", - ApiError::ChatDescriptionIsNotModified, - ), - ( - "{\"data\": \"Bad Request: query is too old and response timeout expired or query id \ - is invalid\"}", - ApiError::InvalidQueryId, - ), - ("{\"data\": \"Bad Request: BUTTON_URL_INVALID\"}", ApiError::ButtonUrlInvalid), - ("{\"data\": \"Bad Request: BUTTON_DATA_INVALID\"}", ApiError::ButtonDataInvalid), - ( - "{\"data\": \"Bad Request: can't parse inline keyboard button: Text buttons are \ - unallowed in the inline keyboard\"}", - ApiError::TextButtonsAreUnallowed, - ), - ("{\"data\": \"Bad Request: wrong file id\"}", ApiError::WrongFileId), - ( - "{\"data\": \"Bad Request: wrong file identifier/HTTP URL specified\"}", - ApiError::WrongFileIdOrUrl, - ), - ( - "{\"data\": \"Bad Request: failed to get HTTP URL content\"}", - ApiError::FailedToGetUrlContent, - ), - ("{\"data\": \"Bad Request: group is deactivated\"}", ApiError::GroupDeactivated), - ("{\"data\": \"Bad Request: IMAGE_PROCESS_FAILED\"}", ApiError::ImageProcessFailed), - ( - "{\"data\": \"Bad Request: Photo should be uploaded as an InputFile\"}", - ApiError::PhotoAsInputFileRequired, - ), - ("{\"data\": \"Bad Request: STICKERSET_INVALID\"}", ApiError::InvalidStickersSet), - ( - "{\"data\": \"Bad Request: sticker set name is already occupied\"}", - ApiError::StickerSetNameOccupied, - ), - ("{\"data\": \"Bad Request: USER_IS_BOT\"}", ApiError::StickerSetOwnerIsBot), - ( - "{\"data\": \"Bad Request: invalid sticker set name is specified\"}", - ApiError::InvalidStickerName, - ), - ( - "{\"data\": \"Bad Request: not enough rights to pin a message\"}", - ApiError::NotEnoughRightsToPinMessage, - ), - ( - "{\"data\": \"Bad Request: not enough rights to manage pinned messages in the chat\"}", - ApiError::NotEnoughRightsToManagePins, - ), - ( - "{\"data\": \"Bad Request: not enough rights to change chat permissions\"}", - ApiError::NotEnoughRightsToChangeChatPermissions, - ), - ( - "{\"data\": \"Bad Request: method is available only for supergroups and channel\"}", - ApiError::MethodNotAvailableInPrivateChats, - ), - ("{\"data\": \"Bad Request: can't demote chat creator\"}", ApiError::CantDemoteChatCreator), - ("{\"data\": \"Bad Request: can't restrict self\"}", ApiError::CantRestrictSelf), - ( - "{\"data\": \"Bad Request: not enough rights to restrict/unrestrict chat member\"}", - ApiError::NotEnoughRightsToRestrict, - ), - ( - "{\"data\": \"Bad Request: need administrator rights in the channel chat\"}", - ApiError::NotEnoughRightsToPostMessages, - ), - ( - "{\"data\": \"Bad Request: bad webhook: HTTPS url must be provided for webhook\"}", - ApiError::WebhookRequireHttps, - ), - ( - "{\"data\": \"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, \ - 443 or 8443\"}", - ApiError::BadWebhookPort, - ), - ( - "{\"data\": \"Bad Request: bad webhook: Failed to resolve host: Name or service not \ - known\"}", - ApiError::UnknownHost, - ), - ("{\"data\": \"Bad Request: can't parse URL\"}", ApiError::CantParseUrl), - ( - "{\"data\": \"Bad Request: can't parse entities\"}", - ApiError::CantParseEntities( - "Bad Request: can't parse entities: SomeRandomString".to_owned(), - ), - ), - ( - "{\"data\": \"can't use getUpdates method while webhook is active\"}", - ApiError::CantGetUpdates, - ), - ("{\"data\": \"Unauthorized: bot was kicked from a chat\"}", ApiError::BotKicked), - ( - "{\"data\": \"Forbidden: bot was kicked from the supergroup chat\"}", - ApiError::BotKickedFromSupergroup, - ), - ("{\"data\": \"Forbidden: user is deactivated\"}", ApiError::UserDeactivated), - ( - "{\"data\": \"Unauthorized: bot can't initiate conversation with a user\"}", - ApiError::CantInitiateConversation, - ), - ( - "{\"data\": \"Unauthorized: bot can't send messages to bots\"}", - ApiError::CantTalkWithBots, - ), - ("{\"data\": \"Bad Request: wrong HTTP URL\"}", ApiError::WrongHttpUrl), - ( - "{\"data\": \"Conflict: terminated by other getUpdates request; make sure that only \ - one bot instance is running\"}", - ApiError::TerminatedByOtherGetUpdates, - ), - ("{\"data\": \"Bad Request: invalid file id\"}", ApiError::FileIdInvalid), - ("{\"data\": \"Request Entity Too Large\"}", ApiError::RequestEntityTooLarge), - ("{\"data\": \"RandomError\"}", ApiError::Unknown("RandomError".to_string())), - ]; - - #[derive(Deserialize, Debug)] - struct Res { - data: T, - } - - for (data, expected) in cases { - let raw = serde_json::from_str::>(data).unwrap().data; - let parsed = serde_json::from_str::>(data).unwrap().data; - assert_eq!(&parsed, expected); - - let expected_error_message = match parsed { - ApiError::Unknown(_) => { - format!("Unknown error: \"{raw}\"") - } - _ => raw, - }; - assert_eq!(parsed.to_string(), expected_error_message); - } -} -