From 7697ec01b46c51734ca64a623696e9842adb32d5 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 20 Aug 2019 21:50:36 +0200 Subject: [PATCH] removed old NetworkRequest api --- src/autogenerated/ResourcesAutogen.hpp | 3 +- src/common/NetworkRequest.cpp | 78 +-- src/common/NetworkRequest.hpp | 22 - src/controllers/ignores/IgnorePhrase.hpp | 3 +- .../notifications/NotificationController.cpp | 94 ++-- src/providers/LinkResolver.cpp | 58 +- src/providers/bttv/BttvEmotes.cpp | 53 +- src/providers/chatterino/ChatterinoBadges.cpp | 46 +- src/providers/ffz/FfzEmotes.cpp | 84 ++- src/providers/ffz/FfzModBadge.cpp | 51 +- src/providers/twitch/PartialTwitchUser.cpp | 75 +-- src/providers/twitch/TwitchAccount.cpp | 500 +++++++++--------- src/providers/twitch/TwitchApi.cpp | 118 +++-- src/providers/twitch/TwitchBadges.cpp | 70 +-- src/providers/twitch/TwitchChannel.cpp | 181 +++---- src/singletons/Settings.hpp | 7 +- src/singletons/Toasts.cpp | 85 ++- src/singletons/Updates.cpp | 267 +++++----- src/widgets/dialogs/LogsPopup.cpp | 159 +++--- src/widgets/dialogs/UserInfoPopup.cpp | 34 +- src/widgets/helper/ChannelView.hpp | 2 +- src/widgets/settingspages/GeneralPage.cpp | 18 +- src/widgets/splits/Split.cpp | 47 +- 23 files changed, 954 insertions(+), 1101 deletions(-) diff --git a/src/autogenerated/ResourcesAutogen.hpp b/src/autogenerated/ResourcesAutogen.hpp index c865f4054..214bbdad5 100644 --- a/src/autogenerated/ResourcesAutogen.hpp +++ b/src/autogenerated/ResourcesAutogen.hpp @@ -3,7 +3,8 @@ namespace chatterino { -class Resources2 : public Singleton { +class Resources2 : public Singleton +{ public: Resources2(); diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index 0eeb562c6..adab1e6be 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -39,85 +39,9 @@ NetworkRequest::NetworkRequest(QUrl url, NetworkRequestType requestType) NetworkRequest::~NetworkRequest() { - //assert(this->executed_); + //assert(!this->data || this->executed_); } -// old -void NetworkRequest::type(NetworkRequestType newRequestType) & -{ - this->data->requestType_ = newRequestType; -} - -void NetworkRequest::setCaller(const QObject *caller) & -{ - this->data->caller_ = caller; -} - -void NetworkRequest::onReplyCreated(NetworkReplyCreatedCallback cb) & -{ - this->data->onReplyCreated_ = cb; -} - -void NetworkRequest::onError(NetworkErrorCallback cb) & -{ - this->data->onError_ = cb; -} - -void NetworkRequest::onSuccess(NetworkSuccessCallback cb) & -{ - this->data->onSuccess_ = cb; -} - -void NetworkRequest::setRawHeader(const char *headerName, const char *value) & -{ - this->data->request_.setRawHeader(headerName, value); -} - -void NetworkRequest::setRawHeader(const char *headerName, - const QByteArray &value) & -{ - this->data->request_.setRawHeader(headerName, value); -} - -void NetworkRequest::setRawHeader(const char *headerName, - const QString &value) & -{ - this->data->request_.setRawHeader(headerName, value.toUtf8()); -} - -void NetworkRequest::setTimeout(int ms) & -{ - this->data->hasTimeout_ = true; - this->data->timer_.setInterval(ms); -} - -void NetworkRequest::setExecuteConcurrently(bool value) & -{ - this->data->executeConcurrently = value; -} - -void NetworkRequest::makeAuthorizedV5(const QString &clientID, - const QString &oauthToken) & -{ - this->setRawHeader("Client-ID", clientID); - this->setRawHeader("Accept", "application/vnd.twitchtv.v5+json"); - if (!oauthToken.isEmpty()) - { - this->setRawHeader("Authorization", "OAuth " + oauthToken); - } -} - -void NetworkRequest::setPayload(const QByteArray &payload) & -{ - this->data->payload_ = payload; -} - -void NetworkRequest::setUseQuickLoadCache(bool value) & -{ - this->data->useQuickLoadCache_ = value; -} - -// new NetworkRequest NetworkRequest::type(NetworkRequestType newRequestType) && { this->data->requestType_ = newRequestType; diff --git a/src/common/NetworkRequest.hpp b/src/common/NetworkRequest.hpp index 71cb5fc82..f82be761b 100644 --- a/src/common/NetworkRequest.hpp +++ b/src/common/NetworkRequest.hpp @@ -36,28 +36,6 @@ public: ~NetworkRequest(); - // old - [[deprecated]] void type(NetworkRequestType newRequestType) &; - - [[deprecated]] void onReplyCreated(NetworkReplyCreatedCallback cb) &; - [[deprecated]] void onError(NetworkErrorCallback cb) &; - [[deprecated]] void onSuccess(NetworkSuccessCallback cb) &; - - [[deprecated]] void setPayload(const QByteArray &payload) &; - [[deprecated]] void setUseQuickLoadCache(bool value) &; - [[deprecated]] void setCaller(const QObject *caller) &; - [[deprecated]] void setRawHeader(const char *headerName, - const char *value) &; - [[deprecated]] void setRawHeader(const char *headerName, - const QByteArray &value) &; - [[deprecated]] void setRawHeader(const char *headerName, - const QString &value) &; - [[deprecated]] void setTimeout(int ms) &; - [[deprecated]] void setExecuteConcurrently(bool value) &; - [[deprecated]] void makeAuthorizedV5( - const QString &clientID, const QString &oauthToken = QString()) &; - - // new NetworkRequest type(NetworkRequestType newRequestType) &&; NetworkRequest onReplyCreated(NetworkReplyCreatedCallback cb) &&; diff --git a/src/controllers/ignores/IgnorePhrase.hpp b/src/controllers/ignores/IgnorePhrase.hpp index 4eea81f96..2d4987887 100644 --- a/src/controllers/ignores/IgnorePhrase.hpp +++ b/src/controllers/ignores/IgnorePhrase.hpp @@ -106,8 +106,7 @@ public: { if (!this->emotesChecked_) { - const auto &accvec = - getApp()->accounts->twitch.accounts; + const auto &accvec = getApp()->accounts->twitch.accounts; for (const auto &acc : accvec) { const auto &accemotes = *acc->accessEmotes(); diff --git a/src/controllers/notifications/NotificationController.cpp b/src/controllers/notifications/NotificationController.cpp index 1b3e64143..f86bf3db5 100644 --- a/src/controllers/notifications/NotificationController.cpp +++ b/src/controllers/notifications/NotificationController.cpp @@ -155,56 +155,56 @@ void NotificationController::getFakeTwitchChannelLiveStatus( log("[TwitchChannel:{}] Refreshing live status", channelName); QString url("https://api.twitch.tv/kraken/streams/" + roomID); - auto request = NetworkRequest::twitchRequest(url); - request.setCaller(QThread::currentThread()); - - request.onSuccess([this, channelName](auto result) -> Outcome { - rapidjson::Document document = result.parseRapidJson(); - if (!document.IsObject()) - { - log("[TwitchChannel:refreshLiveStatus]root is not an object"); - return Failure; - } - - if (!document.HasMember("stream")) - { - log("[TwitchChannel:refreshLiveStatus] Missing stream in root"); - return Failure; - } - - const auto &stream = document["stream"]; - - if (!stream.IsObject()) - { - // Stream is offline (stream is most likely null) - // removeFakeChannel(channelName); - return Failure; - } - // Stream is live - auto i = std::find(fakeTwitchChannels.begin(), - fakeTwitchChannels.end(), channelName); - - if (!(i != fakeTwitchChannels.end())) - { - fakeTwitchChannels.push_back(channelName); - if (Toasts::isEnabled()) + NetworkRequest::twitchRequest(url) + .caller(QThread::currentThread()) + .onSuccess([this, channelName](auto result) -> Outcome { + rapidjson::Document document = result.parseRapidJson(); + if (!document.IsObject()) { - getApp()->toasts->sendChannelNotification(channelName, - Platform::Twitch); + log("[TwitchChannel:refreshLiveStatus]root is not an " + "object"); + return Failure; } - if (getSettings()->notificationPlaySound) - { - getApp()->notifications->playSound(); - } - if (getSettings()->notificationFlashTaskbar) - { - getApp()->windows->sendAlert(); - } - } - return Success; - }); - request.execute(); + if (!document.HasMember("stream")) + { + log("[TwitchChannel:refreshLiveStatus] Missing stream in " + "root"); + return Failure; + } + + const auto &stream = document["stream"]; + + if (!stream.IsObject()) + { + // Stream is offline (stream is most likely null) + // removeFakeChannel(channelName); + return Failure; + } + // Stream is live + auto i = std::find(fakeTwitchChannels.begin(), + fakeTwitchChannels.end(), channelName); + + if (!(i != fakeTwitchChannels.end())) + { + fakeTwitchChannels.push_back(channelName); + if (Toasts::isEnabled()) + { + getApp()->toasts->sendChannelNotification( + channelName, Platform::Twitch); + } + if (getSettings()->notificationPlaySound) + { + getApp()->notifications->playSound(); + } + if (getSettings()->notificationFlashTaskbar) + { + getApp()->windows->sendAlert(); + } + } + return Success; + }) + .execute(); }); } diff --git a/src/providers/LinkResolver.cpp b/src/providers/LinkResolver.cpp index 0137a130c..0de151575 100644 --- a/src/providers/LinkResolver.cpp +++ b/src/providers/LinkResolver.cpp @@ -20,40 +20,38 @@ void LinkResolver::getLinkInfo( } // Uncomment to test crashes // QTimer::singleShot(3000, [=]() { - NetworkRequest request(Env::get().linkResolverUrl.arg( - QString::fromUtf8(QUrl::toPercentEncoding(url, "", "/:")))); - request.setCaller(QThread::currentThread()); - request.setTimeout(30000); - request.onSuccess([successCallback, url](auto result) mutable -> Outcome { - auto root = result.parseJson(); - auto statusCode = root.value("status").toInt(); - QString response = QString(); - QString linkString = url; - if (statusCode == 200) - { - response = root.value("tooltip").toString(); - if (getSettings()->unshortLinks) + NetworkRequest(Env::get().linkResolverUrl.arg(QString::fromUtf8( + QUrl::toPercentEncoding(url, "", "/:")))) + .caller(QThread::currentThread()) + .timeout(30000) + .onSuccess([successCallback, url](auto result) mutable -> Outcome { + auto root = result.parseJson(); + auto statusCode = root.value("status").toInt(); + QString response = QString(); + QString linkString = url; + if (statusCode == 200) { - linkString = root.value("link").toString(); + response = root.value("tooltip").toString(); + if (getSettings()->unshortLinks) + { + linkString = root.value("link").toString(); + } } - } - else - { - response = root.value("message").toString(); - } - successCallback(QUrl::fromPercentEncoding(response.toUtf8()), - Link(Link::Url, linkString)); + else + { + response = root.value("message").toString(); + } + successCallback(QUrl::fromPercentEncoding(response.toUtf8()), + Link(Link::Url, linkString)); - return Success; - }); + return Success; + }) + .onError([successCallback, url](auto /*result*/) { + successCallback("No link info found", Link(Link::Url, url)); - request.onError([successCallback, url](auto result) { - successCallback("No link info found", Link(Link::Url, url)); - - return true; - }); - - request.execute(); + return true; + }) + .execute(); // }); } diff --git a/src/providers/bttv/BttvEmotes.cpp b/src/providers/bttv/BttvEmotes.cpp index 21d937f22..4b2602e4c 100644 --- a/src/providers/bttv/BttvEmotes.cpp +++ b/src/providers/bttv/BttvEmotes.cpp @@ -112,42 +112,36 @@ boost::optional BttvEmotes::emote(const EmoteName &name) const void BttvEmotes::loadEmotes() { - auto request = NetworkRequest(QString(globalEmoteApiUrl)); - - request.setCaller(QThread::currentThread()); - request.setTimeout(30000); - - request.onSuccess([this](auto result) -> Outcome { - auto emotes = this->global_.get(); - auto pair = parseGlobalEmotes(result.parseJson(), *emotes); - if (pair.first) - this->global_.set( - std::make_shared(std::move(pair.second))); - return pair.first; - }); - - request.execute(); + NetworkRequest(QString(globalEmoteApiUrl)) + .caller(QThread::currentThread()) + .timeout(30000) + .onSuccess([this](auto result) -> Outcome { + auto emotes = this->global_.get(); + auto pair = parseGlobalEmotes(result.parseJson(), *emotes); + if (pair.first) + this->global_.set( + std::make_shared(std::move(pair.second))); + return pair.first; + }) + .execute(); } void BttvEmotes::loadChannel(const QString &channelName, std::function callback) { - auto request = - NetworkRequest(QString(bttvChannelEmoteApiUrl) + channelName); - - request.setCaller(QThread::currentThread()); - request.setTimeout(3000); - - request.onSuccess([callback = std::move(callback)](auto result) -> Outcome { - auto pair = parseChannelEmotes(result.parseJson()); - if (pair.first) - callback(std::move(pair.second)); - return pair.first; - }); - - request.execute(); + NetworkRequest(QString(bttvChannelEmoteApiUrl) + channelName) + .caller(QThread::currentThread()) + .timeout(3000) + .onSuccess([callback = std::move(callback)](auto result) -> Outcome { + auto pair = parseChannelEmotes(result.parseJson()); + if (pair.first) + callback(std::move(pair.second)); + return pair.first; + }) + .execute(); } +/* static Url getEmoteLink(QString urlTemplate, const EmoteId &id, const QString &emoteScale) { @@ -156,5 +150,6 @@ static Url getEmoteLink(QString urlTemplate, const EmoteId &id, return {urlTemplate.replace("{{id}}", id.string) .replace("{{image}}", emoteScale)}; } +*/ } // namespace chatterino diff --git a/src/providers/chatterino/ChatterinoBadges.cpp b/src/providers/chatterino/ChatterinoBadges.cpp index 37db25c13..5efde5da6 100644 --- a/src/providers/chatterino/ChatterinoBadges.cpp +++ b/src/providers/chatterino/ChatterinoBadges.cpp @@ -36,32 +36,32 @@ void ChatterinoBadges::loadChatterinoBadges() { static QUrl url("https://fourtf.com/chatterino/badges.json"); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - - req.onSuccess([this](auto result) -> Outcome { - auto jsonRoot = result.parseJson(); - int index = 0; - for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray()) - { - auto jsonBadge = jsonBadge_.toObject(); - auto emote = Emote{ - EmoteName{}, ImageSet{Url{jsonBadge.value("image").toString()}}, - Tooltip{jsonBadge.value("tooltip").toString()}, Url{}}; - - emotes.push_back(std::make_shared(std::move(emote))); - - for (const auto &user : jsonBadge.value("users").toArray()) + NetworkRequest(url) + .caller(QThread::currentThread()) + .onSuccess([this](auto result) -> Outcome { + auto jsonRoot = result.parseJson(); + int index = 0; + for (const auto &jsonBadge_ : jsonRoot.value("badges").toArray()) { - badgeMap[user.toString()] = index; + auto jsonBadge = jsonBadge_.toObject(); + auto emote = Emote{ + EmoteName{}, + ImageSet{Url{jsonBadge.value("image").toString()}}, + Tooltip{jsonBadge.value("tooltip").toString()}, Url{}}; + + emotes.push_back( + std::make_shared(std::move(emote))); + + for (const auto &user : jsonBadge.value("users").toArray()) + { + badgeMap[user.toString()] = index; + } + ++index; } - ++index; - } - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/providers/ffz/FfzEmotes.cpp b/src/providers/ffz/FfzEmotes.cpp index 5dc24fe80..b7d3825ee 100644 --- a/src/providers/ffz/FfzEmotes.cpp +++ b/src/providers/ffz/FfzEmotes.cpp @@ -137,20 +137,18 @@ void FfzEmotes::loadEmotes() { QString url("https://api.frankerfacez.com/v1/set/global"); - NetworkRequest request(url); - request.setCaller(QThread::currentThread()); - request.setTimeout(30000); - - request.onSuccess([this](auto result) -> Outcome { - auto emotes = this->emotes(); - auto pair = parseGlobalEmotes(result.parseJson(), *emotes); - if (pair.first) - this->global_.set( - std::make_shared(std::move(pair.second))); - return pair.first; - }); - - request.execute(); + NetworkRequest(url) + .caller(QThread::currentThread()) + .timeout(30000) + .onSuccess([this](auto result) -> Outcome { + auto emotes = this->emotes(); + auto pair = parseGlobalEmotes(result.parseJson(), *emotes); + if (pair.first) + this->global_.set( + std::make_shared(std::move(pair.second))); + return pair.first; + }) + .execute(); } void FfzEmotes::loadChannel(const QString &channelName, @@ -158,40 +156,36 @@ void FfzEmotes::loadChannel(const QString &channelName, { log("[FFZEmotes] Reload FFZ Channel Emotes for channel {}\n", channelName); - NetworkRequest request("https://api.frankerfacez.com/v1/room/" + - channelName); - request.setCaller(QThread::currentThread()); - request.setTimeout(20000); + NetworkRequest("https://api.frankerfacez.com/v1/room/" + channelName) + .caller(QThread::currentThread()) + .timeout(20000) + .onSuccess([callback = std::move(callback)](auto result) -> Outcome { + auto pair = parseChannelEmotes(result.parseJson()); + if (pair.first) + callback(std::move(pair.second)); + return pair.first; + }) + .onError([channelName](int result) { + if (result == 203) + { + // User does not have any FFZ emotes + return true; + } - request.onSuccess([callback = std::move(callback)](auto result) -> Outcome { - auto pair = parseChannelEmotes(result.parseJson()); - if (pair.first) - callback(std::move(pair.second)); - return pair.first; - }); + if (result == -2) + { + // TODO: Auto retry in case of a timeout, with a delay + log("Fetching FFZ emotes for channel {} failed due to timeout", + channelName); + return true; + } + + log("Error fetching FFZ emotes for channel {}, error {}", + channelName, result); - request.onError([channelName](int result) { - if (result == 203) - { - // User does not have any FFZ emotes return true; - } - - if (result == -2) - { - // TODO: Auto retry in case of a timeout, with a delay - log("Fetching FFZ emotes for channel {} failed due to timeout", - channelName); - return true; - } - - log("Error fetching FFZ emotes for channel {}, error {}", channelName, - result); - - return true; - }); - - request.execute(); + }) + .execute(); } } // namespace chatterino diff --git a/src/providers/ffz/FfzModBadge.cpp b/src/providers/ffz/FfzModBadge.cpp index e4a6569e3..2d29e95d9 100644 --- a/src/providers/ffz/FfzModBadge.cpp +++ b/src/providers/ffz/FfzModBadge.cpp @@ -22,38 +22,37 @@ void FfzModBadge::loadCustomModBadge() static QString partialUrl("https://cdn.frankerfacez.com/room-badge/mod/"); QString url = partialUrl + channelName_ + "/1"; - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - req.onSuccess([this, url](auto result) -> Outcome { - auto data = result.getData(); + NetworkRequest(url) + .caller(QThread::currentThread()) + .onSuccess([this, url](auto result) -> Outcome { + auto data = result.getData(); - QBuffer buffer(const_cast(&data)); - buffer.open(QIODevice::ReadOnly); - QImageReader reader(&buffer); - if (reader.imageCount() == 0) - return Failure; + QBuffer buffer(const_cast(&data)); + buffer.open(QIODevice::ReadOnly); + QImageReader reader(&buffer); + if (reader.imageCount() == 0) + return Failure; - QPixmap badgeOverlay = QPixmap::fromImageReader(&reader); - QPixmap badgePixmap(18, 18); + QPixmap badgeOverlay = QPixmap::fromImageReader(&reader); + QPixmap badgePixmap(18, 18); - // the default mod badge green color - badgePixmap.fill(QColor("#34AE0A")); - QPainter painter(&badgePixmap); - QRectF rect(0, 0, 18, 18); - painter.drawPixmap(rect, badgeOverlay, rect); + // the default mod badge green color + badgePixmap.fill(QColor("#34AE0A")); + QPainter painter(&badgePixmap); + QRectF rect(0, 0, 18, 18); + painter.drawPixmap(rect, badgeOverlay, rect); - auto emote = Emote{{""}, - ImageSet{Image::fromPixmap(badgePixmap)}, - Tooltip{"Twitch Channel Moderator"}, - Url{url}}; + auto emote = Emote{{""}, + ImageSet{Image::fromPixmap(badgePixmap)}, + Tooltip{"Twitch Channel Moderator"}, + Url{url}}; - this->badge_ = std::make_shared(emote); - // getBadge.execute(); + this->badge_ = std::make_shared(emote); + // getBadge.execute(); - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } EmotePtr FfzModBadge::badge() const diff --git a/src/providers/twitch/PartialTwitchUser.cpp b/src/providers/twitch/PartialTwitchUser.cpp index 157274bf0..5c3ceeec1 100644 --- a/src/providers/twitch/PartialTwitchUser.cpp +++ b/src/providers/twitch/PartialTwitchUser.cpp @@ -36,45 +36,46 @@ void PartialTwitchUser::getId(std::function successCallback, caller = QThread::currentThread(); } - NetworkRequest request("https://api.twitch.tv/kraken/users?login=" + - this->username_); - request.setCaller(caller); - request.makeAuthorizedV5(getDefaultClientID()); + NetworkRequest("https://api.twitch.tv/kraken/users?login=" + + this->username_) + .caller(caller) + .authorizeTwitchV5(getDefaultClientID()) + .onSuccess([successCallback](auto result) -> Outcome { + auto root = result.parseJson(); + if (!root.value("users").isArray()) + { + log("API Error while getting user id, users is not an array"); + return Failure; + } - request.onSuccess([successCallback](auto result) -> Outcome { - auto root = result.parseJson(); - if (!root.value("users").isArray()) - { - log("API Error while getting user id, users is not an array"); - return Failure; - } + auto users = root.value("users").toArray(); + if (users.size() != 1) + { + log("API Error while getting user id, users array size is not " + "1"); + return Failure; + } + if (!users[0].isObject()) + { + log("API Error while getting user id, first user is not an " + "object"); + return Failure; + } + auto firstUser = users[0].toObject(); + auto id = firstUser.value("_id"); + if (!id.isString()) + { + log("API Error: while getting user id, first user object `_id` " + "key " + "is not a " + "string"); + return Failure; + } + successCallback(id.toString()); - auto users = root.value("users").toArray(); - if (users.size() != 1) - { - log("API Error while getting user id, users array size is not 1"); - return Failure; - } - if (!users[0].isObject()) - { - log("API Error while getting user id, first user is not an object"); - return Failure; - } - auto firstUser = users[0].toObject(); - auto id = firstUser.value("_id"); - if (!id.isString()) - { - log("API Error: while getting user id, first user object `_id` key " - "is not a " - "string"); - return Failure; - } - successCallback(id.toString()); - - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index c397a2248..88be4685f 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -94,59 +94,58 @@ void TwitchAccount::loadIgnores() QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks"); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - req.onSuccess([=](auto result) -> Outcome { - auto document = result.parseRapidJson(); - if (!document.IsObject()) - { - return Failure; - } - - auto blocksIt = document.FindMember("blocks"); - if (blocksIt == document.MemberEnd()) - { - return Failure; - } - const auto &blocks = blocksIt->value; - - if (!blocks.IsArray()) - { - return Failure; - } - - { - std::lock_guard lock(this->ignoresMutex_); - this->ignores_.clear(); - - for (const auto &block : blocks.GetArray()) + NetworkRequest(url) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onSuccess([=](auto result) -> Outcome { + auto document = result.parseRapidJson(); + if (!document.IsObject()) { - if (!block.IsObject()) - { - continue; - } - auto userIt = block.FindMember("user"); - if (userIt == block.MemberEnd()) - { - continue; - } - TwitchUser ignoredUser; - if (!rj::getSafe(userIt->value, ignoredUser)) - { - log("Error parsing twitch user JSON {}", - rj::stringify(userIt->value)); - continue; - } - - this->ignores_.insert(ignoredUser); + return Failure; } - } - return Success; - }); + auto blocksIt = document.FindMember("blocks"); + if (blocksIt == document.MemberEnd()) + { + return Failure; + } + const auto &blocks = blocksIt->value; - req.execute(); + if (!blocks.IsArray()) + { + return Failure; + } + + { + std::lock_guard lock(this->ignoresMutex_); + this->ignores_.clear(); + + for (const auto &block : blocks.GetArray()) + { + if (!block.IsObject()) + { + continue; + } + auto userIt = block.FindMember("user"); + if (userIt == block.MemberEnd()) + { + continue; + } + TwitchUser ignoredUser; + if (!rj::getSafe(userIt->value, ignoredUser)) + { + log("Error parsing twitch user JSON {}", + rj::stringify(userIt->value)); + continue; + } + + this->ignores_.insert(ignoredUser); + } + } + + return Success; + }) + .execute(); } void TwitchAccount::ignore( @@ -167,64 +166,63 @@ void TwitchAccount::ignoreByID( { QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks/" + targetUserID); - NetworkRequest req(url, NetworkRequestType::Put); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - req.onError([=](int errorCode) { - onFinished(IgnoreResult_Failed, - "An unknown error occured while trying to ignore user " + - targetName + " (" + QString::number(errorCode) + ")"); - - return true; - }); - - req.onSuccess([=](auto result) -> Outcome { - auto document = result.parseRapidJson(); - if (!document.IsObject()) - { + NetworkRequest(url, NetworkRequestType::Put) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { onFinished(IgnoreResult_Failed, - "Bad JSON data while ignoring user " + targetName); - return Failure; - } + "An unknown error occured while trying to ignore user " + + targetName + " (" + QString::number(errorCode) + + ")"); - auto userIt = document.FindMember("user"); - if (userIt == document.MemberEnd()) - { - onFinished(IgnoreResult_Failed, - "Bad JSON data while ignoring user (missing user) " + - targetName); - return Failure; - } - - TwitchUser ignoredUser; - if (!rj::getSafe(userIt->value, ignoredUser)) - { - onFinished(IgnoreResult_Failed, - "Bad JSON data while ignoring user (invalid user) " + - targetName); - return Failure; - } - { - std::lock_guard lock(this->ignoresMutex_); - - auto res = this->ignores_.insert(ignoredUser); - if (!res.second) + return true; + }) + .onSuccess([=](auto result) -> Outcome { + auto document = result.parseRapidJson(); + if (!document.IsObject()) { - const TwitchUser &existingUser = *(res.first); - existingUser.update(ignoredUser); - onFinished(IgnoreResult_AlreadyIgnored, - "User " + targetName + " is already ignored"); + onFinished(IgnoreResult_Failed, + "Bad JSON data while ignoring user " + targetName); return Failure; } - } - onFinished(IgnoreResult_Success, - "Successfully ignored user " + targetName); - return Success; - }); + auto userIt = document.FindMember("user"); + if (userIt == document.MemberEnd()) + { + onFinished(IgnoreResult_Failed, + "Bad JSON data while ignoring user (missing user) " + + targetName); + return Failure; + } - req.execute(); + TwitchUser ignoredUser; + if (!rj::getSafe(userIt->value, ignoredUser)) + { + onFinished(IgnoreResult_Failed, + "Bad JSON data while ignoring user (invalid user) " + + targetName); + return Failure; + } + { + std::lock_guard lock(this->ignoresMutex_); + + auto res = this->ignores_.insert(ignoredUser); + if (!res.second) + { + const TwitchUser &existingUser = *(res.first); + existingUser.update(ignoredUser); + onFinished(IgnoreResult_AlreadyIgnored, + "User " + targetName + " is already ignored"); + return Failure; + } + } + onFinished(IgnoreResult_Success, + "Successfully ignored user " + targetName); + + return Success; + }) + .execute(); } void TwitchAccount::unignore( @@ -246,34 +244,32 @@ void TwitchAccount::unignoreByID( QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/blocks/" + targetUserID); - NetworkRequest req(url, NetworkRequestType::Delete); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + NetworkRequest(url, NetworkRequestType::Delete) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { + onFinished( + UnignoreResult_Failed, + "An unknown error occured while trying to unignore user " + + targetName + " (" + QString::number(errorCode) + ")"); - req.onError([=](int errorCode) { - onFinished(UnignoreResult_Failed, - "An unknown error occured while trying to unignore user " + - targetName + " (" + QString::number(errorCode) + ")"); + return true; + }) + .onSuccess([=](auto result) -> Outcome { + auto document = result.parseRapidJson(); + TwitchUser ignoredUser; + ignoredUser.id = targetUserID; + { + std::lock_guard lock(this->ignoresMutex_); - return true; - }); + this->ignores_.erase(ignoredUser); + } + onFinished(UnignoreResult_Success, + "Successfully unignored user " + targetName); - req.onSuccess([=](auto result) -> Outcome { - auto document = result.parseRapidJson(); - TwitchUser ignoredUser; - ignoredUser.id = targetUserID; - { - std::lock_guard lock(this->ignoresMutex_); - - this->ignores_.erase(ignoredUser); - } - onFinished(UnignoreResult_Success, - "Successfully unignored user " + targetName); - - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } void TwitchAccount::checkFollow(const QString targetUserID, @@ -282,30 +278,27 @@ void TwitchAccount::checkFollow(const QString targetUserID, QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/follows/channels/" + targetUserID); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + NetworkRequest(url) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { + if (errorCode == 203) + { + onFinished(FollowResult_NotFollowing); + } + else + { + onFinished(FollowResult_Failed); + } - req.onError([=](int errorCode) { - if (errorCode == 203) - { - onFinished(FollowResult_NotFollowing); - } - else - { - onFinished(FollowResult_Failed); - } - - return true; - }); - - req.onSuccess([=](auto result) -> Outcome { - auto document = result.parseRapidJson(); - onFinished(FollowResult_Following); - return Success; - }); - - req.execute(); + return true; + }) + .onSuccess([=](auto result) -> Outcome { + auto document = result.parseRapidJson(); + onFinished(FollowResult_Following); + return Success; + }) + .execute(); } void TwitchAccount::followUser(const QString userID, @@ -314,19 +307,16 @@ void TwitchAccount::followUser(const QString userID, QUrl requestUrl("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/follows/channels/" + userID); - NetworkRequest request(requestUrl, NetworkRequestType::Put); - request.setCaller(QThread::currentThread()); + NetworkRequest(requestUrl, NetworkRequestType::Put) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onSuccess([successCallback](auto result) -> Outcome { + // TODO: Properly check result of follow request + successCallback(); - request.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - - // TODO: Properly check result of follow request - request.onSuccess([successCallback](auto result) -> Outcome { - successCallback(); - - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); } void TwitchAccount::unfollowUser(const QString userID, @@ -335,27 +325,23 @@ void TwitchAccount::unfollowUser(const QString userID, QUrl requestUrl("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/follows/channels/" + userID); - NetworkRequest request(requestUrl, NetworkRequestType::Delete); - request.setCaller(QThread::currentThread()); + NetworkRequest(requestUrl, NetworkRequestType::Delete) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([successCallback](int code) { + if (code >= 200 && code <= 299) + { + successCallback(); + } - request.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - - request.onError([successCallback](int code) { - if (code >= 200 && code <= 299) - { + return true; + }) + .onSuccess([successCallback](const auto &document) -> Outcome { successCallback(); - } - return true; - }); - - request.onSuccess([successCallback](const auto &document) -> Outcome { - successCallback(); - - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); } std::set TwitchAccount::getIgnores() const @@ -381,31 +367,28 @@ void TwitchAccount::loadEmotes() QString url("https://api.twitch.tv/kraken/users/" + this->getUserId() + "/emotes"); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + NetworkRequest(url) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { + log("[TwitchAccount::loadEmotes] Error {}", errorCode); + if (errorCode == 203) + { + // onFinished(FollowResult_NotFollowing); + } + else + { + // onFinished(FollowResult_Failed); + } - req.onError([=](int errorCode) { - log("[TwitchAccount::loadEmotes] Error {}", errorCode); - if (errorCode == 203) - { - // onFinished(FollowResult_NotFollowing); - } - else - { - // onFinished(FollowResult_Failed); - } + return true; + }) + .onSuccess([=](auto result) -> Outcome { + this->parseEmotes(result.parseRapidJson()); - return true; - }); - - req.onSuccess([=](auto result) -> Outcome { - this->parseEmotes(result.parseRapidJson()); - - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } AccessGuard @@ -419,44 +402,40 @@ void TwitchAccount::autoModAllow(const QString msgID) { QString url("https://api.twitch.tv/kraken/chat/twitchbot/approve"); - NetworkRequest req(url, NetworkRequestType::Post); - req.setRawHeader("Content-Type", "application/json"); - auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); qDebug() << qba; - req.setRawHeader("Content-Length", QByteArray::number(qba.size())); - req.setPayload(qba); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - - req.onError([=](int errorCode) { - log("[TwitchAccounts::autoModAllow] Error {}", errorCode); - return true; - }); - - req.execute(); + NetworkRequest(url, NetworkRequestType::Post) + .header("Content-Type", "application/json") + .header("Content-Length", QByteArray::number(qba.size())) + .payload(qba) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { + log("[TwitchAccounts::autoModAllow] Error {}", errorCode); + return true; + }) + .execute(); } void TwitchAccount::autoModDeny(const QString msgID) { QString url("https://api.twitch.tv/kraken/chat/twitchbot/deny"); - NetworkRequest req(url, NetworkRequestType::Post); - req.setRawHeader("Content-Type", "application/json"); auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); qDebug() << qba; - req.setRawHeader("Content-Length", QByteArray::number(qba.size())); - req.setPayload(qba); - req.setCaller(QThread::currentThread()); - req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); - - req.onError([=](int errorCode) { - log("[TwitchAccounts::autoModDeny] Error {}", errorCode); - return true; - }); - req.execute(); + NetworkRequest(url, NetworkRequestType::Post) + .header("Content-Type", "application/json") + .header("Content-Length", QByteArray::number(qba.size())) + .payload(qba) + .caller(QThread::currentThread()) + .authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken()) + .onError([=](int errorCode) { + log("[TwitchAccounts::autoModDeny] Error {}", errorCode); + return true; + }) + .execute(); } void TwitchAccount::parseEmotes(const rapidjson::Document &root) @@ -535,49 +514,46 @@ void TwitchAccount::loadEmoteSetData(std::shared_ptr emoteSet) return; } - NetworkRequest req(Env::get().twitchEmoteSetResolverUrl.arg(emoteSet->key)); - req.setUseQuickLoadCache(true); + NetworkRequest(Env::get().twitchEmoteSetResolverUrl.arg(emoteSet->key)) + .cache() + .onError([](int errorCode) -> bool { + log("Error code {} while loading emote set data", errorCode); + return true; + }) + .onSuccess([emoteSet](auto result) -> Outcome { + auto root = result.parseRapidJson(); + if (!root.IsObject()) + { + return Failure; + } - req.onError([](int errorCode) -> bool { - log("Error code {} while loading emote set data", errorCode); - return true; - }); + std::string emoteSetID; + QString channelName; + QString type; + if (!rj::getSafe(root, "channel_name", channelName)) + { + return Failure; + } - req.onSuccess([emoteSet](auto result) -> Outcome { - auto root = result.parseRapidJson(); - if (!root.IsObject()) - { - return Failure; - } + if (!rj::getSafe(root, "type", type)) + { + return Failure; + } - std::string emoteSetID; - QString channelName; - QString type; - if (!rj::getSafe(root, "channel_name", channelName)) - { - return Failure; - } + log("Loaded twitch emote set data for {}!", emoteSet->key); - if (!rj::getSafe(root, "type", type)) - { - return Failure; - } + auto name = channelName; + name.detach(); + name[0] = name[0].toUpper(); - log("Loaded twitch emote set data for {}!", emoteSet->key); + emoteSet->text = name; - auto name = channelName; - name.detach(); - name[0] = name[0].toUpper(); + emoteSet->type = type; + emoteSet->channelName = channelName; - emoteSet->text = name; - - emoteSet->type = type; - emoteSet->channelName = channelName; - - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/providers/twitch/TwitchApi.cpp b/src/providers/twitch/TwitchApi.cpp index 495ac9929..c80e9dd15 100644 --- a/src/providers/twitch/TwitchApi.cpp +++ b/src/providers/twitch/TwitchApi.cpp @@ -15,46 +15,48 @@ void TwitchApi::findUserId(const QString user, { QString requestUrl("https://api.twitch.tv/kraken/users?login=" + user); - NetworkRequest request(requestUrl); - request.setCaller(QThread::currentThread()); - request.makeAuthorizedV5(getDefaultClientID()); - request.setTimeout(30000); - request.onSuccess([successCallback](auto result) mutable -> Outcome { - auto root = result.parseJson(); - if (!root.value("users").isArray()) - { - log("API Error while getting user id, users is not an array"); - successCallback(""); - return Failure; - } - auto users = root.value("users").toArray(); - if (users.size() != 1) - { - log("API Error while getting user id, users array size is not 1"); - successCallback(""); - return Failure; - } - if (!users[0].isObject()) - { - log("API Error while getting user id, first user is not an object"); - successCallback(""); - return Failure; - } - auto firstUser = users[0].toObject(); - auto id = firstUser.value("_id"); - if (!id.isString()) - { - log("API Error: while getting user id, first user object `_id` key " - "is not a " - "string"); - successCallback(""); - return Failure; - } - successCallback(id.toString()); - return Success; - }); - - request.execute(); + NetworkRequest(requestUrl) + .caller(QThread::currentThread()) + .authorizeTwitchV5(getDefaultClientID()) + .timeout(30000) + .onSuccess([successCallback](auto result) mutable -> Outcome { + auto root = result.parseJson(); + if (!root.value("users").isArray()) + { + log("API Error while getting user id, users is not an array"); + successCallback(""); + return Failure; + } + auto users = root.value("users").toArray(); + if (users.size() != 1) + { + log("API Error while getting user id, users array size is not " + "1"); + successCallback(""); + return Failure; + } + if (!users[0].isObject()) + { + log("API Error while getting user id, first user is not an " + "object"); + successCallback(""); + return Failure; + } + auto firstUser = users[0].toObject(); + auto id = firstUser.value("_id"); + if (!id.isString()) + { + log("API Error: while getting user id, first user object `_id` " + "key " + "is not a " + "string"); + successCallback(""); + return Failure; + } + successCallback(id.toString()); + return Success; + }) + .execute(); } void TwitchApi::findUserName(const QString userid, @@ -62,24 +64,24 @@ void TwitchApi::findUserName(const QString userid, { QString requestUrl("https://api.twitch.tv/kraken/users/" + userid); - NetworkRequest request(requestUrl); - request.setCaller(QThread::currentThread()); - request.makeAuthorizedV5(getDefaultClientID()); - request.setTimeout(30000); - request.onSuccess([successCallback](auto result) mutable -> Outcome { - auto root = result.parseJson(); - auto name = root.value("name"); - if (!name.isString()) - { - log("API Error: while getting user name, `name` is not a string"); - successCallback(""); - return Failure; - } - successCallback(name.toString()); - return Success; - }); - - request.execute(); + NetworkRequest(requestUrl) + .caller(QThread::currentThread()) + .authorizeTwitchV5(getDefaultClientID()) + .timeout(30000) + .onSuccess([successCallback](auto result) mutable -> Outcome { + auto root = result.parseJson(); + auto name = root.value("name"); + if (!name.isString()) + { + log("API Error: while getting user name, `name` is not a " + "string"); + successCallback(""); + return Failure; + } + successCallback(name.toString()); + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/providers/twitch/TwitchBadges.cpp b/src/providers/twitch/TwitchBadges.cpp index fb65900c3..4de38ec9b 100644 --- a/src/providers/twitch/TwitchBadges.cpp +++ b/src/providers/twitch/TwitchBadges.cpp @@ -17,45 +17,49 @@ void TwitchBadges::loadTwitchBadges() static QString url( "https://badges.twitch.tv/v1/badges/global/display?language=en"); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); - req.onSuccess([this](auto result) -> Outcome { - auto root = result.parseJson(); - auto badgeSets = this->badgeSets_.access(); + NetworkRequest(url) + .caller(QThread::currentThread()) + .onSuccess([this](auto result) -> Outcome { + auto root = result.parseJson(); + auto badgeSets = this->badgeSets_.access(); - auto jsonSets = root.value("badge_sets").toObject(); - for (auto sIt = jsonSets.begin(); sIt != jsonSets.end(); ++sIt) - { - auto key = sIt.key(); - auto versions = sIt.value().toObject().value("versions").toObject(); - - for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) + auto jsonSets = root.value("badge_sets").toObject(); + for (auto sIt = jsonSets.begin(); sIt != jsonSets.end(); ++sIt) { - auto versionObj = vIt.value().toObject(); + auto key = sIt.key(); + auto versions = + sIt.value().toObject().value("versions").toObject(); - auto emote = Emote{ - {""}, - ImageSet{ - Image::fromUrl( - {versionObj.value("image_url_1x").toString()}, 1), - Image::fromUrl( - {versionObj.value("image_url_2x").toString()}, .5), - Image::fromUrl( - {versionObj.value("image_url_4x").toString()}, .25), - }, - Tooltip{versionObj.value("description").toString()}, - Url{versionObj.value("click_url").toString()}}; - // "title" - // "clickAction" + for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) + { + auto versionObj = vIt.value().toObject(); - (*badgeSets)[key][vIt.key()] = std::make_shared(emote); + auto emote = Emote{ + {""}, + ImageSet{ + Image::fromUrl( + {versionObj.value("image_url_1x").toString()}, + 1), + Image::fromUrl( + {versionObj.value("image_url_2x").toString()}, + .5), + Image::fromUrl( + {versionObj.value("image_url_4x").toString()}, + .25), + }, + Tooltip{versionObj.value("description").toString()}, + Url{versionObj.value("click_url").toString()}}; + // "title" + // "clickAction" + + (*badgeSets)[key][vIt.key()] = + std::make_shared(emote); + } } - } - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } boost::optional TwitchBadges::badge(const QString &set, diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 5ec10aa3a..2ec8823fb 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -501,19 +501,17 @@ void TwitchChannel::refreshLiveStatus() QString url("https://api.twitch.tv/kraken/streams/" + roomID); // auto request = makeGetStreamRequest(roomID, QThread::currentThread()); - auto request = NetworkRequest::twitchRequest(url); - request.setCaller(QThread::currentThread()); + NetworkRequest::twitchRequest(url) + .caller(QThread::currentThread()) + .onSuccess( + [this, weak = weakOf(this)](auto result) -> Outcome { + ChannelPtr shared = weak.lock(); + if (!shared) + return Failure; - request.onSuccess( - [this, weak = weakOf(this)](auto result) -> Outcome { - ChannelPtr shared = weak.lock(); - if (!shared) - return Failure; - - return this->parseLiveStatus(result.parseRapidJson()); - }); - - request.execute(); + return this->parseLiveStatus(result.parseRapidJson()); + }) + .execute(); } Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document) @@ -608,42 +606,38 @@ void TwitchChannel::loadRecentMessages() return; } - NetworkRequest request( - Env::get().recentMessagesApiUrl.arg(this->getName())); - request.setCaller(QThread::currentThread()); - // can't be concurrent right now due to SignalVector - request.setExecuteConcurrently(true); + NetworkRequest(Env::get().recentMessagesApiUrl.arg(this->getName())) + .caller(QThread::currentThread()) + .concurrent() + .onSuccess([weak = weakOf(this)](auto result) -> Outcome { + auto shared = weak.lock(); + if (!shared) + return Failure; - request.onSuccess([weak = weakOf(this)](auto result) -> Outcome { - auto shared = weak.lock(); - if (!shared) - return Failure; + auto messages = parseRecentMessages(result.parseJson(), shared); - auto messages = parseRecentMessages(result.parseJson(), shared); + auto &handler = IrcMessageHandler::getInstance(); - auto &handler = IrcMessageHandler::getInstance(); + std::vector allBuiltMessages; - std::vector allBuiltMessages; - - for (auto message : messages) - { - for (auto builtMessage : - handler.parseMessage(shared.get(), message)) + for (auto message : messages) { - builtMessage->flags.set(MessageFlag::RecentMessage); - allBuiltMessages.emplace_back(builtMessage); + for (auto builtMessage : + handler.parseMessage(shared.get(), message)) + { + builtMessage->flags.set(MessageFlag::RecentMessage); + allBuiltMessages.emplace_back(builtMessage); + } } - } - postToThread( - [shared, messages = std::move(allBuiltMessages)]() mutable { - shared->addMessagesAtStart(messages); - }); + postToThread( + [shared, messages = std::move(allBuiltMessages)]() mutable { + shared->addMessagesAtStart(messages); + }); - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); } void TwitchChannel::refreshPubsub() @@ -675,76 +669,73 @@ void TwitchChannel::refreshChatters() } // get viewer list - NetworkRequest request("https://tmi.twitch.tv/group/user/" + - this->getName() + "/chatters"); + NetworkRequest("https://tmi.twitch.tv/group/user/" + this->getName() + + "/chatters") + .caller(QThread::currentThread()) + .onSuccess( + [this, weak = weakOf(this)](auto result) -> Outcome { + // channel still exists? + auto shared = weak.lock(); + if (!shared) + return Failure; - request.setCaller(QThread::currentThread()); - request.onSuccess( - [this, weak = weakOf(this)](auto result) -> Outcome { - // channel still exists? - auto shared = weak.lock(); - if (!shared) - return Failure; + auto pair = parseChatters(result.parseJson()); + if (pair.first) + { + *this->chatters_.access() = std::move(pair.second); + } - auto pair = parseChatters(result.parseJson()); - if (pair.first) - { - *this->chatters_.access() = std::move(pair.second); - } - - return pair.first; - }); - - request.execute(); + return pair.first; + }) + .execute(); } void TwitchChannel::refreshBadges() { auto url = Url{"https://badges.twitch.tv/v1/badges/channels/" + this->roomId() + "/display?language=en"}; - NetworkRequest req(url.string); - req.setCaller(QThread::currentThread()); + NetworkRequest(url.string) + .caller(QThread::currentThread()) + .onSuccess([this, + weak = weakOf(this)](auto result) -> Outcome { + auto shared = weak.lock(); + if (!shared) + return Failure; - req.onSuccess([this, weak = weakOf(this)](auto result) -> Outcome { - auto shared = weak.lock(); - if (!shared) - return Failure; + auto badgeSets = this->badgeSets_.access(); - auto badgeSets = this->badgeSets_.access(); + auto jsonRoot = result.parseJson(); - auto jsonRoot = result.parseJson(); - - auto _ = jsonRoot["badge_sets"].toObject(); - for (auto jsonBadgeSet = _.begin(); jsonBadgeSet != _.end(); - jsonBadgeSet++) - { - auto &versions = (*badgeSets)[jsonBadgeSet.key()]; - - auto _set = jsonBadgeSet->toObject()["versions"].toObject(); - for (auto jsonVersion_ = _set.begin(); jsonVersion_ != _set.end(); - jsonVersion_++) + auto _ = jsonRoot["badge_sets"].toObject(); + for (auto jsonBadgeSet = _.begin(); jsonBadgeSet != _.end(); + jsonBadgeSet++) { - auto jsonVersion = jsonVersion_->toObject(); - auto emote = std::make_shared(Emote{ - EmoteName{}, - ImageSet{ - Image::fromUrl({jsonVersion["image_url_1x"].toString()}, - 1), - Image::fromUrl({jsonVersion["image_url_2x"].toString()}, - .5), - Image::fromUrl({jsonVersion["image_url_4x"].toString()}, - .25)}, - Tooltip{jsonVersion["description"].toString()}, - Url{jsonVersion["clickURL"].toString()}}); + auto &versions = (*badgeSets)[jsonBadgeSet.key()]; - versions.emplace(jsonVersion_.key(), emote); - }; - } + auto _set = jsonBadgeSet->toObject()["versions"].toObject(); + for (auto jsonVersion_ = _set.begin(); + jsonVersion_ != _set.end(); jsonVersion_++) + { + auto jsonVersion = jsonVersion_->toObject(); + auto emote = std::make_shared(Emote{ + EmoteName{}, + ImageSet{ + Image::fromUrl( + {jsonVersion["image_url_1x"].toString()}, 1), + Image::fromUrl( + {jsonVersion["image_url_2x"].toString()}, .5), + Image::fromUrl( + {jsonVersion["image_url_4x"].toString()}, .25)}, + Tooltip{jsonVersion["description"].toString()}, + Url{jsonVersion["clickURL"].toString()}}); - return Success; - }); + versions.emplace(jsonVersion_.key(), emote); + }; + } - req.execute(); + return Success; + }) + .execute(); } void TwitchChannel::refreshCheerEmotes() diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index e771ee904..4f6e04dcb 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -42,8 +42,8 @@ public: BoolSetting hideModerated = {"/appearance/messages/hideModerated", false}; BoolSetting hideModerationActions = { "/appearance/messages/hideModerationActions", false}; - BoolSetting colorizeNicknames = { - "/appearance/messages/colorizeNicknames", false}; + BoolSetting colorizeNicknames = {"/appearance/messages/colorizeNicknames", + false}; // BoolSetting collapseLongMessages = // {"/appearance/messages/collapseLongMessages", false}; @@ -99,7 +99,8 @@ public: "/behaviour/autocompletion/onlyFetchChattersForSmallerStreamers", true}; IntSetting smallStreamerLimit = { "/behaviour/autocompletion/smallStreamerLimit", 1000}; - BoolSetting prefixOnlyEmoteCompletion = {"/behaviour/autocompletion/prefixOnlyCompletion", true}; + BoolSetting prefixOnlyEmoteCompletion = { + "/behaviour/autocompletion/prefixOnlyCompletion", true}; BoolSetting pauseChatOnHover = {"/behaviour/pauseChatHover", false}; BoolSetting autorun = {"/behaviour/autorun", false}; diff --git a/src/singletons/Toasts.cpp b/src/singletons/Toasts.cpp index 6b5ba9636..813bf9e64 100644 --- a/src/singletons/Toasts.cpp +++ b/src/singletons/Toasts.cpp @@ -213,48 +213,47 @@ void Toasts::fetchChannelAvatar(const QString channelName, QString requestUrl("https://api.twitch.tv/kraken/users?login=" + channelName); - NetworkRequest request(requestUrl); - request.setCaller(QThread::currentThread()); - request.makeAuthorizedV5(getDefaultClientID()); - request.setTimeout(30000); - request.onSuccess([successCallback](auto result) mutable -> Outcome { - auto root = result.parseJson(); - if (!root.value("users").isArray()) - { - // log("API Error while getting user id, users is not an array"); - successCallback(""); - return Failure; - } - auto users = root.value("users").toArray(); - if (users.size() != 1) - { - // log("API Error while getting user id, users array size is not - // 1"); - successCallback(""); - return Failure; - } - if (!users[0].isObject()) - { - // log("API Error while getting user id, first user is not an - // object"); - successCallback(""); - return Failure; - } - auto firstUser = users[0].toObject(); - auto avatar = firstUser.value("logo"); - if (!avatar.isString()) - { - // log("API Error: while getting user avatar, first user object " - // "`avatar` key " - // "is not a " - // "string"); - successCallback(""); - return Failure; - } - successCallback(avatar.toString()); - return Success; - }); - - request.execute(); + NetworkRequest(requestUrl) + .caller(QThread::currentThread()) + .authorizeTwitchV5(getDefaultClientID()) + .timeout(30000) + .onSuccess([successCallback](auto result) mutable -> Outcome { + auto root = result.parseJson(); + if (!root.value("users").isArray()) + { + // log("API Error while getting user id, users is not an array"); + successCallback(""); + return Failure; + } + auto users = root.value("users").toArray(); + if (users.size() != 1) + { + // log("API Error while getting user id, users array size is not + // 1"); + successCallback(""); + return Failure; + } + if (!users[0].isObject()) + { + // log("API Error while getting user id, first user is not an + // object"); + successCallback(""); + return Failure; + } + auto firstUser = users[0].toObject(); + auto avatar = firstUser.value("logo"); + if (!avatar.isString()) + { + // log("API Error: while getting user avatar, first user object " + // "`avatar` key " + // "is not a " + // "string"); + successCallback(""); + return Failure; + } + successCallback(avatar.toString()); + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/singletons/Updates.cpp b/src/singletons/Updates.cpp index afc5d44f9..55fa3dace 100644 --- a/src/singletons/Updates.cpp +++ b/src/singletons/Updates.cpp @@ -73,47 +73,46 @@ void Updates::installUpdates() box->setAttribute(Qt::WA_DeleteOnClose); box->show(); - NetworkRequest req(this->updatePortable_); - req.setTimeout(600000); - req.onError([this](int) -> bool { - this->setStatus_(DownloadFailed); + NetworkRequest(this->updatePortable_) + .timeout(600000) + .onError([this](int) -> bool { + this->setStatus_(DownloadFailed); - postToThread([] { - QMessageBox *box = new QMessageBox( - QMessageBox::Information, "Chatterino Update", - "Failed while trying to download the update."); - box->setAttribute(Qt::WA_DeleteOnClose); - box->show(); - box->raise(); - }); + postToThread([] { + QMessageBox *box = new QMessageBox( + QMessageBox::Information, "Chatterino Update", + "Failed while trying to download the update."); + box->setAttribute(Qt::WA_DeleteOnClose); + box->show(); + box->raise(); + }); - return true; - }); + return true; + }) + .onSuccess([this](auto result) -> Outcome { + QByteArray object = result.getData(); + auto filename = + combinePath(getPaths()->miscDirectory, "update.zip"); - req.onSuccess([this](auto result) -> Outcome { - QByteArray object = result.getData(); - auto filename = - combinePath(getPaths()->miscDirectory, "update.zip"); + QFile file(filename); + file.open(QIODevice::Truncate | QIODevice::WriteOnly); - QFile file(filename); - file.open(QIODevice::Truncate | QIODevice::WriteOnly); + if (file.write(object) == -1) + { + this->setStatus_(WriteFileFailed); + return Failure; + } - if (file.write(object) == -1) - { - this->setStatus_(WriteFileFailed); - return Failure; - } + QProcess::startDetached( + combinePath(QCoreApplication::applicationDirPath(), + "updater.1/ChatterinoUpdater.exe"), + {filename, "restart"}); - QProcess::startDetached( - combinePath(QCoreApplication::applicationDirPath(), - "updater.1/ChatterinoUpdater.exe"), - {filename, "restart"}); - - QApplication::exit(0); - return Success; - }); + QApplication::exit(0); + return Success; + }) + .execute(); this->setStatus_(Downloading); - req.execute(); } else { @@ -125,67 +124,67 @@ void Updates::installUpdates() box->setAttribute(Qt::WA_DeleteOnClose); box->show(); - NetworkRequest req(this->updateExe_); - req.setTimeout(600000); - req.onError([this](int) -> bool { - this->setStatus_(DownloadFailed); + NetworkRequest(this->updateExe_) + .timeout(600000) + .onError([this](int) -> bool { + this->setStatus_(DownloadFailed); - QMessageBox *box = new QMessageBox( - QMessageBox::Information, "Chatterino Update", - "Failed to download the update. \n\nTry manually " - "downloading the update."); - box->setAttribute(Qt::WA_DeleteOnClose); - box->exec(); - return true; - }); - - req.onSuccess([this](auto result) -> Outcome { - QByteArray object = result.getData(); - auto filename = - combinePath(getPaths()->miscDirectory, "Update.exe"); - - QFile file(filename); - file.open(QIODevice::Truncate | QIODevice::WriteOnly); - - if (file.write(object) == -1) - { - this->setStatus_(WriteFileFailed); QMessageBox *box = new QMessageBox( QMessageBox::Information, "Chatterino Update", - "Failed to save the update file. This could be due to " - "window settings or antivirus software.\n\nTry manually " + "Failed to download the update. \n\nTry manually " "downloading the update."); box->setAttribute(Qt::WA_DeleteOnClose); box->exec(); + return true; + }) + .onSuccess([this](auto result) -> Outcome { + QByteArray object = result.getData(); + auto filename = + combinePath(getPaths()->miscDirectory, "Update.exe"); - QDesktopServices::openUrl(this->updateExe_); - return Failure; - } - file.close(); + QFile file(filename); + file.open(QIODevice::Truncate | QIODevice::WriteOnly); - if (QProcess::startDetached(filename)) - { - QApplication::exit(0); - } - else - { - QMessageBox *box = new QMessageBox( - QMessageBox::Information, "Chatterino Update", - "Failed to execute update binary. This could be due to " - "window " - "settings or antivirus software.\n\nTry manually " - "downloading " - "the update."); - box->setAttribute(Qt::WA_DeleteOnClose); - box->exec(); + if (file.write(object) == -1) + { + this->setStatus_(WriteFileFailed); + QMessageBox *box = new QMessageBox( + QMessageBox::Information, "Chatterino Update", + "Failed to save the update file. This could be due to " + "window settings or antivirus software.\n\nTry " + "manually " + "downloading the update."); + box->setAttribute(Qt::WA_DeleteOnClose); + box->exec(); - QDesktopServices::openUrl(this->updateExe_); - } + QDesktopServices::openUrl(this->updateExe_); + return Failure; + } + file.close(); - return Success; - }); + if (QProcess::startDetached(filename)) + { + QApplication::exit(0); + } + else + { + QMessageBox *box = new QMessageBox( + QMessageBox::Information, "Chatterino Update", + "Failed to execute update binary. This could be due to " + "window " + "settings or antivirus software.\n\nTry manually " + "downloading " + "the update."); + box->setAttribute(Qt::WA_DeleteOnClose); + box->exec(); + + QDesktopServices::openUrl(this->updateExe_); + } + + return Success; + }) + .execute(); this->setStatus_(Downloading); - req.execute(); } #endif } @@ -196,67 +195,67 @@ void Updates::checkForUpdates() "https://notitia.chatterino.com/version/chatterino/" CHATTERINO_OS "/stable"; - NetworkRequest req(url); - req.setTimeout(60000); - req.onSuccess([this](auto result) -> Outcome { - auto object = result.parseJson(); - /// Version available on every platform - QJsonValue version_val = object.value("version"); + NetworkRequest(url) + .timeout(60000) + .onSuccess([this](auto result) -> Outcome { + auto object = result.parseJson(); + /// Version available on every platform + QJsonValue version_val = object.value("version"); - if (!version_val.isString()) - { - this->setStatus_(SearchFailed); - qDebug() << "error updating"; - return Failure; - } + if (!version_val.isString()) + { + this->setStatus_(SearchFailed); + qDebug() << "error updating"; + return Failure; + } #if defined Q_OS_WIN || defined Q_OS_MACOS - /// Windows downloads an installer for the new version - QJsonValue updateExe_val = object.value("updateexe"); - if (!updateExe_val.isString()) - { - this->setStatus_(SearchFailed); - qDebug() << "error updating"; - return Failure; - } - this->updateExe_ = updateExe_val.toString(); + /// Windows downloads an installer for the new version + QJsonValue updateExe_val = object.value("updateexe"); + if (!updateExe_val.isString()) + { + this->setStatus_(SearchFailed); + qDebug() << "error updating"; + return Failure; + } + this->updateExe_ = updateExe_val.toString(); - /// Windows portable - QJsonValue portable_val = object.value("portable_download"); - if (!portable_val.isString()) - { - this->setStatus_(SearchFailed); - qDebug() << "error updating"; - return Failure; - } - this->updatePortable_ = portable_val.toString(); + /// Windows portable + QJsonValue portable_val = object.value("portable_download"); + if (!portable_val.isString()) + { + this->setStatus_(SearchFailed); + qDebug() << "error updating"; + return Failure; + } + this->updatePortable_ = portable_val.toString(); #elif defined Q_OS_LINUX - QJsonValue updateGuide_val = object.value("updateguide"); - if (updateGuide_val.isString()) - { - this->updateGuideLink_ = updateGuide_val.toString(); - } + QJsonValue updateGuide_val = object.value("updateguide"); + if (updateGuide_val.isString()) + { + this->updateGuideLink_ = updateGuide_val.toString(); + } #else - return Failure; + return Failure; #endif - /// Current version - this->onlineVersion_ = version_val.toString(); + /// Current version + this->onlineVersion_ = version_val.toString(); - /// Update available :) - if (this->currentVersion_ != this->onlineVersion_) - { - this->setStatus_(UpdateAvailable); - } - else - { - this->setStatus_(NoUpdateAvailable); - } - return Failure; - }); + /// Update available :) + if (this->currentVersion_ != this->onlineVersion_) + { + this->setStatus_(UpdateAvailable); + } + else + { + this->setStatus_(NoUpdateAvailable); + } + return Failure; + }) + .execute(); this->setStatus_(Searching); - req.execute(); } Updates::Status Updates::getStatus() const diff --git a/src/widgets/dialogs/LogsPopup.cpp b/src/widgets/dialogs/LogsPopup.cpp index eedfb3e4b..3263f0dfd 100644 --- a/src/widgets/dialogs/LogsPopup.cpp +++ b/src/widgets/dialogs/LogsPopup.cpp @@ -91,45 +91,43 @@ void LogsPopup::getLogviewerLogs(const QString &roomID) auto url = QString("https://cbenni.com/api/logs/%1/?nick=%2&before=500") .arg(this->channelName_, this->userName_); - NetworkRequest req(url); - req.setCaller(this); + NetworkRequest(url) + .caller(this) + .onError([this](int errorCode) { + this->getOverrustleLogs(); + return true; + }) + .onSuccess([this, roomID](auto result) -> Outcome { + auto data = result.parseJson(); + std::vector messages; - req.onError([this](int errorCode) { - this->getOverrustleLogs(); - return true; - }); + QJsonValue before = data.value("before"); - req.onSuccess([this, roomID](auto result) -> Outcome { - auto data = result.parseJson(); - std::vector messages; + for (auto i : before.toArray()) + { + auto messageObject = i.toObject(); + QString message = messageObject.value("text").toString(); - QJsonValue before = data.value("before"); + // Hacky way to fix the timestamp + message.insert(1, "historical=1;"); + message.insert(1, QString("tmi-sent-ts=%10000;") + .arg(messageObject["time"].toInt())); + message.insert(1, QString("room-id=%1;").arg(roomID)); - for (auto i : before.toArray()) - { - auto messageObject = i.toObject(); - QString message = messageObject.value("text").toString(); + MessageParseArgs args; + auto ircMessage = + Communi::IrcMessage::fromData(message.toUtf8(), nullptr); + auto privMsg = + static_cast(ircMessage); + TwitchMessageBuilder builder(this->channel_.get(), privMsg, + args); + messages.push_back(builder.build()); + } + this->setMessages(messages); - // Hacky way to fix the timestamp - message.insert(1, "historical=1;"); - message.insert(1, QString("tmi-sent-ts=%10000;") - .arg(messageObject["time"].toInt())); - message.insert(1, QString("room-id=%1;").arg(roomID)); - - MessageParseArgs args; - auto ircMessage = - Communi::IrcMessage::fromData(message.toUtf8(), nullptr); - auto privMsg = - static_cast(ircMessage); - TwitchMessageBuilder builder(this->channel_.get(), privMsg, args); - messages.push_back(builder.build()); - } - this->setMessages(messages); - - return Success; - }); - - req.execute(); + return Success; + }) + .execute(); } void LogsPopup::getOverrustleLogs() @@ -138,57 +136,56 @@ void LogsPopup::getOverrustleLogs() QString("https://overrustlelogs.net/api/v1/stalk/%1/%2.json?limit=500") .arg(this->channelName_, this->userName_); - NetworkRequest req(url); - req.setCaller(this); - req.onError([this](int errorCode) { - auto box = new QMessageBox( - QMessageBox::Information, "Error getting logs", - "No logs could be found for channel " + this->channelName_); - box->setAttribute(Qt::WA_DeleteOnClose); - box->show(); - box->raise(); + NetworkRequest(url) + .caller(this) + .onError([this](int errorCode) { + auto box = new QMessageBox( + QMessageBox::Information, "Error getting logs", + "No logs could be found for channel " + this->channelName_); + box->setAttribute(Qt::WA_DeleteOnClose); + box->show(); + box->raise(); - static QSet closeButtons{ - QMessageBox::Ok, - QMessageBox::Close, - }; - if (closeButtons.contains(box->exec())) - { - this->close(); - } - - return true; - }); - - req.onSuccess([this](auto result) -> Outcome { - auto data = result.parseJson(); - std::vector messages; - if (data.contains("lines")) - { - QJsonArray dataMessages = data.value("lines").toArray(); - for (auto i : dataMessages) + static QSet closeButtons{ + QMessageBox::Ok, + QMessageBox::Close, + }; + if (closeButtons.contains(box->exec())) { - QJsonObject singleMessage = i.toObject(); - QTime timeStamp = QDateTime::fromSecsSinceEpoch( - singleMessage.value("timestamp").toInt()) - .time(); - - MessageBuilder builder; - builder.emplace(timeStamp); - builder.emplace(this->userName_, - MessageElementFlag::Username, - MessageColor::System); - builder.emplace( - singleMessage.value("text").toString(), - MessageElementFlag::Text, MessageColor::Text); - messages.push_back(builder.release()); + this->close(); } - } - this->setMessages(messages); - return Success; - }); + return true; + }) + .onSuccess([this](auto result) -> Outcome { + auto data = result.parseJson(); + std::vector messages; + if (data.contains("lines")) + { + QJsonArray dataMessages = data.value("lines").toArray(); + for (auto i : dataMessages) + { + QJsonObject singleMessage = i.toObject(); + QTime timeStamp = + QDateTime::fromSecsSinceEpoch( + singleMessage.value("timestamp").toInt()) + .time(); - req.execute(); + MessageBuilder builder; + builder.emplace(timeStamp); + builder.emplace(this->userName_, + MessageElementFlag::Username, + MessageColor::System); + builder.emplace( + singleMessage.value("text").toString(), + MessageElementFlag::Text, MessageColor::Text); + messages.push_back(builder.release()); + } + } + this->setMessages(messages); + + return Success; + }) + .execute(); } } // namespace chatterino diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index f326d9cc9..899a4aaf8 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -350,26 +350,24 @@ void UserInfoPopup::updateUserData() QString url("https://api.twitch.tv/kraken/channels/" + id); - auto request = NetworkRequest::twitchRequest(url); - request.setCaller(this); + NetworkRequest::twitchRequest(url) + .caller(this) + .onSuccess([this](auto result) -> Outcome { + auto obj = result.parseJson(); + this->ui_.followerCountLabel->setText( + TEXT_FOLLOWERS + + QString::number(obj.value("followers").toInt())); + this->ui_.viewCountLabel->setText( + TEXT_VIEWS + QString::number(obj.value("views").toInt())); + this->ui_.createdDateLabel->setText( + TEXT_CREATED + + obj.value("created_at").toString().section("T", 0, 0)); - request.onSuccess([this](auto result) -> Outcome { - auto obj = result.parseJson(); - this->ui_.followerCountLabel->setText( - TEXT_FOLLOWERS + - QString::number(obj.value("followers").toInt())); - this->ui_.viewCountLabel->setText( - TEXT_VIEWS + QString::number(obj.value("views").toInt())); - this->ui_.createdDateLabel->setText( - TEXT_CREATED + - obj.value("created_at").toString().section("T", 0, 0)); + this->loadAvatar(QUrl(obj.value("logo").toString())); - this->loadAvatar(QUrl(obj.value("logo").toString())); - - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); // get follow state currentUser->checkFollow(id, [this, hack](auto result) { diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index b4f33bf71..0ea042e13 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -1,10 +1,10 @@ #pragma once #include "common/FlagsEnum.hpp" +#include "messages/Image.hpp" #include "messages/LimitedQueue.hpp" #include "messages/LimitedQueueSnapshot.hpp" #include "messages/Selection.hpp" -#include "messages/Image.hpp" #include "widgets/BaseWidget.hpp" #include diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 64365e0ac..c4288c696 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -218,10 +218,10 @@ void GeneralPage::initLayout(SettingsLayout &layout) layout.addCheckbox("Hide moderated messages", s.hideModerated); layout.addCheckbox("Hide moderation messages", s.hideModerationActions); layout.addCheckbox("Colorize gray nicknames", s.colorizeNicknames); - layout.addDropdown( - "Timeout stacking style", {"Stack", "Stack sparingly"}, - s.timeoutStackStyle, [](int index) { return index; }, - [](auto args) { return args.index; }, false); + layout.addDropdown("Timeout stacking style", + {"Stack", "Stack sparingly"}, s.timeoutStackStyle, + [](int index) { return index; }, + [](auto args) { return args.index; }, false); layout.addTitle("Emotes"); layout.addDropdown( @@ -278,11 +278,11 @@ void GeneralPage::initLayout(SettingsLayout &layout) layout.addCheckbox("Double click links to open", s.linksDoubleClickOnly); layout.addCheckbox("Unshorten links", s.unshortLinks); layout.addCheckbox("Show live indicator in tabs", s.showTabLive); - layout.addDropdown( - "Show emote preview in tooltip on hover", - {"Don't show", "Always show", "Hold shift"}, s.emotesTooltipPreview, - [](int index) { return index; }, [](auto args) { return args.index; }, - false); + layout.addDropdown("Show emote preview in tooltip on hover", + {"Don't show", "Always show", "Hold shift"}, + s.emotesTooltipPreview, + [](int index) { return index; }, + [](auto args) { return args.index; }, false); layout.addCheckbox( "Only search for emote autocompletion at the start of emote names", diff --git a/src/widgets/splits/Split.cpp b/src/widgets/splits/Split.cpp index d610b5226..1d4e123a7 100644 --- a/src/widgets/splits/Split.cpp +++ b/src/widgets/splits/Split.cpp @@ -554,34 +554,31 @@ void Split::showViewerList() } auto loadingLabel = new QLabel("Loading..."); - auto request = NetworkRequest::twitchRequest( - "https://tmi.twitch.tv/group/user/" + this->getChannel()->getName() + - "/chatters"); + NetworkRequest::twitchRequest("https://tmi.twitch.tv/group/user/" + + this->getChannel()->getName() + "/chatters") + .caller(this) + .onSuccess([=](auto result) -> Outcome { + auto obj = result.parseJson(); + QJsonObject chattersObj = obj.value("chatters").toObject(); - request.setCaller(this); - request.onSuccess([=](auto result) -> Outcome { - auto obj = result.parseJson(); - QJsonObject chattersObj = obj.value("chatters").toObject(); + loadingLabel->hide(); + for (int i = 0; i < jsonLabels.size(); i++) + { + auto currentCategory = + chattersObj.value(jsonLabels.at(i)).toArray(); + // If current category of chatters is empty, dont show this + // category. + if (currentCategory.empty()) + continue; - loadingLabel->hide(); - for (int i = 0; i < jsonLabels.size(); i++) - { - auto currentCategory = - chattersObj.value(jsonLabels.at(i)).toArray(); - // If current category of chatters is empty, dont show this - // category. - if (currentCategory.empty()) - continue; + chattersList->addItem(labelList.at(i)); + foreach (const QJsonValue &v, currentCategory) + chattersList->addItem(v.toString()); + } - chattersList->addItem(labelList.at(i)); - foreach (const QJsonValue &v, currentCategory) - chattersList->addItem(v.toString()); - } - - return Success; - }); - - request.execute(); + return Success; + }) + .execute(); searchBar->setPlaceholderText("Search User..."); QObject::connect(searchBar, &QLineEdit::textEdited, this, [=]() {