From f76512c31e62aea96e236daaca36bd2323d081c8 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Wed, 27 Jun 2018 00:16:30 +0000 Subject: [PATCH] Remove authenticated get function from urlfetch Implement twitch account emote getter function in TwitchAccount --- lib/settings | 2 +- src/common/SerializeCustom.hpp | 8 ++-- src/common/UrlFetch.hpp | 15 -------- src/providers/twitch/TwitchAccount.cpp | 38 +++++++++++++++++++ src/providers/twitch/TwitchAccount.hpp | 5 +++ src/providers/twitch/TwitchEmotes.cpp | 52 +++++++++++++++----------- src/util/RapidjsonHelpers.hpp | 18 +++------ 7 files changed, 86 insertions(+), 52 deletions(-) diff --git a/lib/settings b/lib/settings index 8309a170..29accdf9 160000 --- a/lib/settings +++ b/lib/settings @@ -1 +1 @@ -Subproject commit 8309a17041777dde281da617a5e4460df42ba5b9 +Subproject commit 29accdf9dea05947d687112594ad06bf6001ee0a diff --git a/src/common/SerializeCustom.hpp b/src/common/SerializeCustom.hpp index 4682a2eb..7a85f4a2 100644 --- a/src/common/SerializeCustom.hpp +++ b/src/common/SerializeCustom.hpp @@ -18,10 +18,12 @@ struct Serialize { template <> struct Deserialize { - static QString get(const rapidjson::Value &value) + static QString get(const rapidjson::Value &value, bool *error = nullptr) { if (!value.IsString()) { - throw std::runtime_error("Deserialized rapidjson::Value is not a string"); + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION("Deserialized rapidjson::Value is not a string"); + return QString{}; } try { @@ -35,7 +37,7 @@ struct Deserialize { // int y = 5; } - return QString(); + return QString{}; } }; diff --git a/src/common/UrlFetch.hpp b/src/common/UrlFetch.hpp index df3fbdda..f0d86b12 100644 --- a/src/common/UrlFetch.hpp +++ b/src/common/UrlFetch.hpp @@ -50,21 +50,6 @@ static void twitchApiGet2(QString url, const QObject *caller, bool useQuickLoadC }); } -static void twitchApiGetAuthorized(QString url, const QString &clientID, const QString &oauthToken, - const QObject *caller, - std::function successCallback) -{ - NetworkRequest req(url); - req.setCaller(caller); - req.setRawHeader("Client-ID", clientID.toUtf8()); - req.setRawHeader("Authorization", "OAuth " + oauthToken.toUtf8()); - req.setRawHeader("Accept", "application/vnd.twitchtv.v5+json"); - - req.getJSON([=](const QJsonObject &node) { - successCallback(node); // - }); -} - static void twitchApiGetUserID(QString username, const QObject *caller, std::function successCallback) { diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 65e378de..2f115ab2 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -256,4 +256,42 @@ std::set TwitchAccount::getIgnores() const return this->ignores; } +void TwitchAccount::loadEmotes(std::function cb) +{ + Log("Loading Twitch emotes for user {}", this->getUserName()); + + const auto &clientID = this->getOAuthClient(); + const auto &oauthToken = this->getOAuthToken(); + + if (clientID.isEmpty() || oauthToken.isEmpty()) { + Log("Missing Client ID or OAuth token"); + return; + } + + QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/emotes"); + + NetworkRequest req(url); + req.setRequestType(NetworkRequest::GetRequest); + req.setCaller(QThread::currentThread()); + req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + + req.onError([=](int errorCode) { + Log("Error {}", errorCode); + if (errorCode == 203) { + // onFinished(FollowResult_NotFollowing); + } else { + // onFinished(FollowResult_Failed); + } + + return true; + }); + + req.onSuccess([=](const rapidjson::Document &document) { + cb(document); + return true; + }); + + req.execute(); +} + } // namespace chatterino diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index 56e5b9db..2cf16c73 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -3,9 +3,12 @@ #include "controllers/accounts/Account.hpp" #include "providers/twitch/TwitchUser.hpp" +#include #include #include +#include +#include #include namespace chatterino { @@ -65,6 +68,8 @@ public: std::set getIgnores() const; + void loadEmotes(std::function cb); + QColor color; private: diff --git a/src/providers/twitch/TwitchEmotes.cpp b/src/providers/twitch/TwitchEmotes.cpp index 8e3a393e..cae80a61 100644 --- a/src/providers/twitch/TwitchEmotes.cpp +++ b/src/providers/twitch/TwitchEmotes.cpp @@ -142,17 +142,7 @@ EmoteData TwitchEmotes::getEmoteById(const QString &id, const QString &emoteName void TwitchEmotes::refresh(const std::shared_ptr &user) { - Log("Loading Twitch emotes for user {}", user->getUserName()); - const auto &roomID = user->getUserId(); - const auto &clientID = user->getOAuthClient(); - const auto &oauthToken = user->getOAuthToken(); - - if (clientID.isEmpty() || oauthToken.isEmpty()) { - Log("Missing Client ID or OAuth token"); - return; - } - TwitchAccountEmoteData &emoteData = this->emotes[roomID]; if (emoteData.filled) { @@ -160,24 +150,44 @@ void TwitchEmotes::refresh(const std::shared_ptr &user) return; } - QString url("https://api.twitch.tv/kraken/users/" + roomID + "/emotes"); - - auto loadEmotes = [=, &emoteData](const QJsonObject &root) { + auto loadEmotes = [=, &emoteData](const rapidjson::Document &root) { emoteData.emoteSets.clear(); emoteData.emoteCodes.clear(); - auto emoticonSets = root.value("emoticon_sets").toObject(); - for (QJsonObject::iterator it = emoticonSets.begin(); it != emoticonSets.end(); ++it) { + auto emoticonSets = root.FindMember("emoticon_sets"); + if (emoticonSets == root.MemberEnd() || !emoticonSets->value.IsObject()) { + Log("No emoticon_sets in load emotes response"); + return; + } + + for (const auto &emoteSetJSON : emoticonSets->value.GetObject()) { auto emoteSet = std::make_shared(); - emoteSet->key = it.key(); + emoteSet->key = emoteSetJSON.name.GetString(); loadSetData(emoteSet); - for (QJsonValue emoteValue : it.value().toArray()) { - QJsonObject emoticon = emoteValue.toObject(); - QString id = QString::number(emoticon["id"].toInt()); - QString code = emoticon["code"].toString(); + for (const rapidjson::Value &emoteJSON : emoteSetJSON.value.GetArray()) { + if (!emoteJSON.IsObject()) { + Log("Emote value was invalid"); + return; + } + + QString id, code; + + uint64_t idNumber; + + if (!rj::getSafe(emoteJSON, "id", idNumber)) { + Log("No ID key found in Emote value"); + return; + } + + if (!rj::getSafe(emoteJSON, "code", code)) { + Log("No code key found in Emote value"); + return; + } + + id = QString::number(idNumber); auto cleanCode = cleanUpCode(code); emoteSet->emotes.emplace_back(id, cleanCode); @@ -193,7 +203,7 @@ void TwitchEmotes::refresh(const std::shared_ptr &user) emoteData.filled = true; }; - twitchApiGetAuthorized(url, clientID, oauthToken, QThread::currentThread(), loadEmotes); + user->loadEmotes(loadEmotes); } void TwitchEmotes::loadSetData(std::shared_ptr emoteSet) diff --git a/src/util/RapidjsonHelpers.hpp b/src/util/RapidjsonHelpers.hpp index abc06e31..25e72ed4 100644 --- a/src/util/RapidjsonHelpers.hpp +++ b/src/util/RapidjsonHelpers.hpp @@ -77,25 +77,19 @@ bool getSafe(const rapidjson::Value &obj, const char *key, Type &out) return false; } - try { - out = pajlada::Settings::Deserialize::get(obj[key]); - } catch (const std::runtime_error &) { - return false; - } + bool error = false; + out = pajlada::Settings::Deserialize::get(obj[key], &error); - return true; + return !error; } template bool getSafe(const rapidjson::Value &value, Type &out) { - try { - out = pajlada::Settings::Deserialize::get(value); - } catch (const std::runtime_error &) { - return false; - } + bool error = false; + out = pajlada::Settings::Deserialize::get(value, &error); - return true; + return !error; } std::string stringify(const rapidjson::Value &value);