From fa68fda5acb6f1acfac7dcce6016ab2ae5856a3a Mon Sep 17 00:00:00 2001 From: blankie Date: Fri, 24 Nov 2023 18:11:05 +1100 Subject: [PATCH] Properly return errors to the user https://awoo.space/@noiob gives "This method requires an authenticated user" --- client.cpp | 38 +++++++++++++++++++------------------- client.h | 17 ++++++++++++++++- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/client.cpp b/client.cpp index b156c37..9acddc3 100644 --- a/client.cpp +++ b/client.cpp @@ -70,12 +70,11 @@ std::optional MastodonClient::get_account_by_username(const std::string using namespace std::string_literals; try { - std::string resp = this->_send_request("https://"s + host + "/api/v1/accounts/lookup?acct=" + username); - Account res = nlohmann::json::parse(std::move(resp)); - res.same_server = host == res.server; - return res; - } catch (const CurlException& e) { - if (e.code != CURLE_HTTP_RETURNED_ERROR || this->_response_status_code() != 404) { + Account account = this->_send_request("https://"s + host + "/api/v1/accounts/lookup?acct=" + username); + account.same_server = host == account.server; + return account; + } catch (const MastodonException& e) { + if (e.response_code != 404) { throw; } @@ -86,8 +85,7 @@ std::optional MastodonClient::get_account_by_username(const std::string std::vector MastodonClient::get_pinned_posts(const std::string& host, const std::string& account_id) { using namespace std::string_literals; - std::string resp = this->_send_request("https://"s + host + "/api/v1/accounts/" + account_id + "/statuses?pinned=true"); - std::vector posts = nlohmann::json::parse(std::move(resp)); + std::vector posts = this->_send_request("https://"s + host + "/api/v1/accounts/" + account_id + "/statuses?pinned=true"); for (Post& post : posts) { handle_post_server(post, host); @@ -114,8 +112,7 @@ std::vector MastodonClient::get_posts(const std::string& host, const std:: url += '?'; url += query; } - std::string resp = this->_send_request(url); - std::vector posts = nlohmann::json::parse(std::move(resp)); + std::vector posts = this->_send_request(url); for (Post& post : posts) { handle_post_server(post, host); @@ -128,12 +125,11 @@ std::optional MastodonClient::get_post(const std::string& host, const std: using namespace std::string_literals; try { - std::string resp = this->_send_request("https://"s + host + "/api/v1/statuses/" + id); - Post post = nlohmann::json::parse(std::move(resp)); + Post post = this->_send_request("https://"s + host + "/api/v1/statuses/" + id); handle_post_server(post, host); return post; - } catch (const CurlException& e) { - if (e.code != CURLE_HTTP_RETURNED_ERROR || this->_response_status_code() != 404) { + } catch (const MastodonException& e) { + if (e.response_code != 404) { throw; } @@ -144,8 +140,7 @@ std::optional MastodonClient::get_post(const std::string& host, const std: PostContext MastodonClient::get_post_context(const std::string& host, const std::string& id) { using namespace std::string_literals; - std::string resp = this->_send_request("https://"s + host + "/api/v1/statuses/" + id + "/context"); - PostContext context = nlohmann::json::parse(std::move(resp)); + PostContext context = this->_send_request("https://"s + host + "/api/v1/statuses/" + id + "/context"); for (Post& post : context.ancestors) { handle_post_server(post, host); @@ -166,7 +161,6 @@ CURL* MastodonClient::_get_easy() { } try { - setopt(curl, CURLOPT_FAILONERROR, 1L); setopt(curl, CURLOPT_TIMEOUT_MS, 10000L); setopt(curl, CURLOPT_PROTOCOLS_STR, "https"); setopt(curl, CURLOPT_USERAGENT, "Coyote (https://gitlab.com/blankX/coyote; blankie@nixnetmail.com)"); @@ -186,7 +180,7 @@ CURL* MastodonClient::_get_easy() { return curl; } -std::string MastodonClient::_send_request(const std::string& url) { +nlohmann::json MastodonClient::_send_request(const std::string& url) { std::string res; CURL* curl = this->_get_easy(); @@ -198,7 +192,13 @@ std::string MastodonClient::_send_request(const std::string& url) { throw CurlException(code); } - return res; + long response_code = this->_response_status_code(); + nlohmann::json j = nlohmann::json::parse(std::move(res)); + if (response_code != 200) { + throw MastodonException(response_code, j.at("error").get()); + } + + return j; } long MastodonClient::_response_status_code() { diff --git a/client.h b/client.h index a99fc4d..021d246 100644 --- a/client.h +++ b/client.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "models.h" @@ -30,6 +31,20 @@ public: CURLSHcode code; }; +class MastodonException : public std::exception { +public: + MastodonException(long response_code_, std::string error) : response_code(response_code_), _error(std::move(error)) {} + + const char* what() const noexcept { + return this->_error.c_str(); + } + + long response_code; + +private: + std::string _error; +}; + class MastodonClient { public: MastodonClient(const MastodonClient&&) = delete; @@ -58,7 +73,7 @@ public: private: CURL* _get_easy(); - std::string _send_request(const std::string& url); + nlohmann::json _send_request(const std::string& url); long _response_status_code(); std::mutex _share_locks[CURL_LOCK_DATA_LAST];