From f8b8efcfc68c7dad952be71df0e5dde62c2eca00 Mon Sep 17 00:00:00 2001 From: Oleg Morozenkov Date: Mon, 14 Sep 2026 22:18:41 +0300 Subject: [PATCH] Parse Telegram error response parameters --- include/tgbot/TgException.h | 9 ++++++++- src/Api.cpp | 6 +++++- src/TgException.cpp | 8 ++++++-- tests/tgbot/Api.cpp | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/tgbot/TgException.h b/include/tgbot/TgException.h index ab563c07..97cbc428 100644 --- a/include/tgbot/TgException.h +++ b/include/tgbot/TgException.h @@ -1,5 +1,6 @@ #pragma once +#include "tgbot/Types.h" #include "tgbot/export.h" #include @@ -30,9 +31,15 @@ class TGBOT_API TgException : public std::runtime_error { InvalidJson = 101 }; - TgException(std::string_view description, ErrorCode errorCode); + TgException(std::string_view description, ErrorCode errorCode, + std::shared_ptr parameters = nullptr); const ErrorCode errorCode; + + /** + * @brief Additional details about the error returned by Telegram, if any. + */ + const std::shared_ptr parameters; }; } // namespace TgBot diff --git a/src/Api.cpp b/src/Api.cpp index 2a008a72..baa178e9 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -39,8 +39,12 @@ nlohmann::json Api::sendRequest(std::string_view method, const std::vector parameters; + if (const auto iterator = response.find("parameters"); iterator != response.end()) { + parameters = std::make_shared(iterator->get()); + } throw TgException(response.value("description", "Telegram Bot API request failed"), - static_cast(response.value("error_code", 0))); + static_cast(response.value("error_code", 0)), std::move(parameters)); } return response.at("result"); diff --git a/src/TgException.cpp b/src/TgException.cpp index 88482e2b..7767e1a5 100644 --- a/src/TgException.cpp +++ b/src/TgException.cpp @@ -1,10 +1,14 @@ #include "tgbot/TgException.h" +#include + namespace TgBot { -TgException::TgException(std::string_view description, ErrorCode errorCode) +TgException::TgException(std::string_view description, ErrorCode errorCode, + std::shared_ptr parameters) : runtime_error(std::string(description)) - , errorCode(errorCode) { + , errorCode(errorCode) + , parameters(std::move(parameters)) { } } // namespace TgBot diff --git a/tests/tgbot/Api.cpp b/tests/tgbot/Api.cpp index 27408734..c4227def 100644 --- a/tests/tgbot/Api.cpp +++ b/tests/tgbot/Api.cpp @@ -60,6 +60,25 @@ TEST(Api, GeneratedMethodMapsTelegramErrors) { EXPECT_TRUE(requestThrows(ErrorCode::InvalidJson, "error_code:101")); } +TEST(Api, GeneratedMethodPreservesTelegramErrorParameters) { + HttpClientMock httpClient; + httpClient.response + = R"({"ok":false,"error_code":400,"description":"migrated","parameters":{"migrate_to_chat_id":-1001234567890,"retry_after":42}})"; + TgBot::Api api("token", httpClient, "url"); + + try { + api.getMe(); + FAIL() << "Expected TgException"; + } catch (const TgBot::TgException& exception) { + EXPECT_EQ(exception.errorCode, TgBot::TgException::ErrorCode::BadRequest); + ASSERT_TRUE(exception.parameters); + ASSERT_TRUE(exception.parameters->migrateToChatId); + EXPECT_EQ(*exception.parameters->migrateToChatId, -1001234567890); + ASSERT_TRUE(exception.parameters->retryAfter); + EXPECT_EQ(*exception.parameters->retryAfter, 42); + } +} + TEST(Api, PassesCompleteUrlToHttpClient) { HttpClientMock httpClient; httpClient.response = R"({"ok":true,"result":{"id":1,"is_bot":true,"first_name":"bot"}})";