diff --git a/src/errors.rs b/src/errors.rs index 999692be..da2666b2 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -8,9 +8,11 @@ use thiserror::Error; /// An error caused by downloading a file. #[derive(Debug, Error, From)] pub enum DownloadError { + /// Network error while downloading file from telegram. #[error("A network error: {0}")] NetworkError(#[source] reqwest::Error), + /// I/O error while writing file to destination. #[error("An I/O error: {0}")] Io(#[source] std::io::Error), } @@ -18,8 +20,14 @@ pub enum DownloadError { /// An error caused by sending a request to Telegram. #[derive(Debug, Error)] pub enum RequestError { + /// Telegram API error #[error("A Telegram's error #{status_code}: {kind:?}")] - ApiError { status_code: StatusCode, kind: ApiErrorKind }, + ApiError { + /// Kind of api error + kind: ApiError, + /// HTTP code returned by telegram, not very usefull in practice. + status_code: StatusCode, + }, /// The group has been migrated to a supergroup with the specified /// identifier. @@ -31,9 +39,16 @@ pub enum RequestError { #[error("Retry after {0} seconds")] RetryAfter(i32), + /// Network error while sending request to telegram. #[error("A network error: {0}")] NetworkError(#[source] reqwest::Error), + /// Error while parsing response from telegram. + /// + /// 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 #[error("An error while parsing JSON: {0}")] InvalidJson(#[source] serde_json::Error), @@ -42,480 +57,480 @@ pub enum RequestError { Io(#[source] io::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, +serde_or_unknown! { + #[unknown_mod = api_error_internals] + #[unknown_kind = Kind] + #[unknown_path = "api_error_internals::Kind"] + + /// A kind of an API error. + #[derive(Debug, Deserialize, PartialEq, Hash, Eq, Clone)] + pub enum ApiError { + #[unknown] + /// 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), + + /// 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 6e7b78b0..e12421e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ mod local_macros; // FIXME(waffle): rethink modules, find a place for wrappers. pub use self::{ bot::{AutoSend, Bot, BotBuilder, CacheMe}, - errors::{ApiErrorKind, DownloadError, KnownApiErrorKind, RequestError}, + errors::{ApiError, DownloadError, RequestError}, }; pub mod payloads; diff --git a/src/local_macros.rs b/src/local_macros.rs index 5a48a207..85c421f6 100644 --- a/src/local_macros.rs +++ b/src/local_macros.rs @@ -106,3 +106,85 @@ macro_rules! req_future { }; } + +#[macro_use] +macro_rules! serde_or_unknown { + ( + #[unknown_mod = $mod_:ident] + #[unknown_kind = $Kind:ident] + #[unknown_path = $path:literal] + $( + #[ $($meta:tt)* ] + )* + $v:vis enum $Name:ident { + #[unknown] + $( + #[ $($unknown_meta:tt)* ] + )* + $Unknown:ident(String) + + $( + , + $( + #[ $($var_meta:tt)* ] + )* + $Var:ident + )* + $(,)? + } + ) => { + mod $mod_ { + #[allow(unused_imports)] + use super::{*, $Name as _}; + + $( + #[ $($meta)* ] + )* + $v enum $Name { + $( + $( + #[ $($var_meta)* ] + )* + $Var, + )* + } + + #[derive(::serde::Deserialize)] + #[serde(untagged)] + $v enum $Kind { + Known($Name), + Unknown(String), + } + + impl ::core::convert::From<$Kind> for super::$Name { + fn from(kind: $Kind) -> Self { + match kind { + $Kind::Unknown(string) => Self::Unknown(string), + $Kind::Known(known) => match known { + $( + $Name::$Var => Self::$Var, + )* + } + } + } + } + } + + $( + #[ $($meta)* ] + )* + #[serde(from = $path)] + $v enum $Name { + $( + $( + #[ $($var_meta)* ] + )* + $Var, + )* + $( + #[ $($unknown_meta)* ] + )* + $Unknown(String), + } + } +} diff --git a/src/net/mod.rs b/src/net/mod.rs index de38dacc..97db838a 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -1,7 +1,7 @@ #[cfg(feature = "unstable-stream")] -pub use download::download_file_stream; +pub(crate) use download::download_file_stream; -pub use self::{ +pub(crate) use self::{ download::download_file, request::{request_json, request_json2, request_multipart, request_multipart2}, telegram_response::TelegramResponse, diff --git a/src/net/telegram_response.rs b/src/net/telegram_response.rs index d5062e8f..4bf3849b 100644 --- a/src/net/telegram_response.rs +++ b/src/net/telegram_response.rs @@ -4,18 +4,18 @@ use serde::Deserialize; use crate::{ requests::ResponseResult, types::{False, ResponseParameters, True}, - ApiErrorKind, RequestError, + ApiError, RequestError, }; #[derive(Deserialize)] #[serde(untagged)] -pub enum TelegramResponse<R> { +pub(crate) enum TelegramResponse<R> { Ok { /// A dummy field. Used only for deserialization. #[allow(dead_code)] ok: True, - result: R, + response: R, }, Err { /// A dummy field. Used only for deserialization. @@ -23,7 +23,7 @@ pub enum TelegramResponse<R> { ok: False, #[serde(rename = "description")] - kind: ApiErrorKind, + error: ApiError, error_code: u16, response_parameters: Option<ResponseParameters>, }, @@ -32,8 +32,8 @@ pub enum TelegramResponse<R> { 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, .. } => { + TelegramResponse::Ok { response, .. } => Ok(response), + TelegramResponse::Err { error, error_code, response_parameters, .. } => { if let Some(params) = response_parameters { match params { ResponseParameters::RetryAfter(i) => Err(RequestError::RetryAfter(i)), @@ -43,7 +43,7 @@ impl<R> Into<ResponseResult<R>> for TelegramResponse<R> { } } else { Err(RequestError::ApiError { - kind, + kind: error, status_code: StatusCode::from_u16(error_code).unwrap(), }) } @@ -55,16 +55,15 @@ impl<R> Into<ResponseResult<R>> for TelegramResponse<R> { #[cfg(test)] mod tests { use super::*; - use crate::{errors::KnownApiErrorKind, types::Update}; + use crate::{errors::ApiError, 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"); - } + fn parse_terminated_by_other_get_updates() { + let s = r#"{"ok":false,"error_code":409,"description":"Conflict: terminated by other getUpdates request; make sure that only one bot instance is running"}"#; + let val = serde_json::from_str::<TelegramResponse<Update>>(s).unwrap(); + + assert!( + matches!(val, TelegramResponse::Err { error: ApiError::TerminatedByOtherGetUpdates, .. }) + ); } }