summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/tgbot/Api.h2
-rw-r--r--include/tgbot/TgException.h16
-rw-r--r--src/Api.cpp25
-rw-r--r--src/TgException.cpp4
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/tgbot/Api.cpp64
6 files changed, 101 insertions, 11 deletions
diff --git a/include/tgbot/Api.h b/include/tgbot/Api.h
index 7db68e7..6bd24e4 100644
--- a/include/tgbot/Api.h
+++ b/include/tgbot/Api.h
@@ -1989,7 +1989,7 @@ public:
const HttpClient& _httpClient;
-private:
+protected:
boost::property_tree::ptree sendRequest(const std::string& method, const std::vector<HttpReqArg>& args = std::vector<HttpReqArg>()) const;
const std::string _token;
diff --git a/include/tgbot/TgException.h b/include/tgbot/TgException.h
index e80711c..0fbda93 100644
--- a/include/tgbot/TgException.h
+++ b/include/tgbot/TgException.h
@@ -16,7 +16,21 @@ namespace TgBot {
class TGBOT_API TgException : public std::runtime_error {
public:
- explicit TgException(const std::string& description);
+
+ /**
+ * @brief Enum of possible errors from Api requests
+ */
+ enum class ErrorCode : size_t {
+ Undefined = 0,
+ BadRequest = 400, Unauthorized = 401,
+ Forbidden = 403, NotFound = 404,
+ Flood = 402, Internal = 500,
+ HtmlResponse = 100, InvalidJson = 101
+ };
+
+ explicit TgException(const std::string& description, ErrorCode errorCode);
+
+ const ErrorCode errorCode;
};
}
diff --git a/src/Api.cpp b/src/Api.cpp
index f238a70..f3f8124 100644
--- a/src/Api.cpp
+++ b/src/Api.cpp
@@ -2513,19 +2513,28 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st
{
try {
std::string serverResponse = _httpClient.makeRequest(url, args);
+
if (!serverResponse.compare(0, 6, "<html>")) {
- throw TgException("tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token.");
+ std::string message = "tgbot-cpp library have got html page instead of json response. Maybe you entered wrong bot token.";
+ throw TgException(message, TgException::ErrorCode::HtmlResponse);
}
- boost::property_tree::ptree result = _tgTypeParser.parseJson(serverResponse);
+ boost::property_tree::ptree result;
try {
- if (result.get<bool>("ok", false)) {
- return result.get_child("result");
- } else {
- throw TgException(result.get("description", ""));
- }
+ result = _tgTypeParser.parseJson(serverResponse);
} catch (boost::property_tree::ptree_error& e) {
- throw TgException("tgbot-cpp library can't parse json response. " + std::string(e.what()));
+ std::string message = "tgbot-cpp library can't parse json response. " + std::string(e.what());
+
+ throw TgException(message, TgException::ErrorCode::InvalidJson);
+ }
+
+ if (result.get<bool>("ok", false)) {
+ return result.get_child("result");
+ } else {
+ std::string message = result.get("description", "");
+ size_t errorCode = result.get<size_t>("error_code", 0u);
+
+ throw TgException(message, static_cast<TgException::ErrorCode>(errorCode));
}
} catch (...) {
int max_retries = _httpClient.getRequestMaxRetries();
diff --git a/src/TgException.cpp b/src/TgException.cpp
index e61e09c..7164ddc 100644
--- a/src/TgException.cpp
+++ b/src/TgException.cpp
@@ -4,7 +4,9 @@
namespace TgBot {
-TgBot::TgException::TgException(const std::string& description) : runtime_error(description) {
+TgException::TgException(const std::string& description, ErrorCode errorCode)
+ : runtime_error(description), errorCode(errorCode)
+{
}
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0cce236..899035f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,5 +1,6 @@
set(TEST_SRC_LIST
main.cpp
+ tgbot/Api.cpp
tgbot/net/Url.cpp
tgbot/net/HttpParser.cpp
tgbot/tools/StringTools.cpp
diff --git a/test/tgbot/Api.cpp b/test/tgbot/Api.cpp
new file mode 100644
index 0000000..2575865
--- /dev/null
+++ b/test/tgbot/Api.cpp
@@ -0,0 +1,64 @@
+#include <string>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include "tgbot/net/HttpClient.h"
+#include "tgbot/Api.h"
+#include "tgbot/TgException.h"
+
+using namespace std;
+using namespace TgBot;
+
+typedef TgException::ErrorCode TgErrorCode;
+
+class TestableApi : public Api {
+public:
+ using Api::Api;
+ using Api::sendRequest;
+};
+
+class HttpClientMock : public HttpClient {
+public:
+ std::string makeRequest(const Url& url, const std::vector<HttpReqArg>& args) const override
+ {return response;};
+
+ int getRequestMaxRetries() const override { return 0;};
+ int getRequestBackoff() const override {return 1;};
+
+ string response;
+};
+
+bool Request(TgErrorCode expectedCode, const string& response) {
+ HttpClientMock httpClientMock;
+ httpClientMock.response = response;
+
+ TestableApi api("token", httpClientMock, "url");
+
+ try {
+ api.sendRequest("", vector<HttpReqArg>());
+ } catch (TgException& exception) {
+ return exception.errorCode == expectedCode;
+ }
+
+ return false;
+}
+
+BOOST_AUTO_TEST_SUITE(tApi)
+
+BOOST_AUTO_TEST_CASE(sendRequest) {
+ BOOST_CHECK(Request(TgErrorCode::HtmlResponse, "<html>"));
+ BOOST_CHECK(Request(TgErrorCode::Undefined, "{\"ok\": false}"));
+ BOOST_CHECK(Request(TgErrorCode::Undefined, "{\"ok\": false, \"error_code\":0}"));
+
+ BOOST_CHECK(Request(TgErrorCode::BadRequest, "{\"ok\": false, \"error_code\":400}"));
+ BOOST_CHECK(Request(TgErrorCode::Unauthorized, "{\"ok\": false, \"error_code\":401}"));
+ BOOST_CHECK(Request(TgErrorCode::Forbidden, "{\"ok\": false, \"error_code\":403}"));
+ BOOST_CHECK(Request(TgErrorCode::NotFound, "{\"ok\": false, \"error_code\":404}"));
+ BOOST_CHECK(Request(TgErrorCode::Flood, "{\"ok\": false, \"error_code\":402}"));
+ BOOST_CHECK(Request(TgErrorCode::Internal, "{\"ok\": false, \"error_code\":500}"));
+
+ BOOST_CHECK(Request(TgErrorCode::InvalidJson, "error_code:101"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()