From 002129009df0743e1edb9b1e8c659f3b621a9e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82?= Date: Thu, 24 Jun 2021 23:23:31 +0200 Subject: [PATCH] Fix emotesets not loading properly (#2905) * Initial work fk I'm so tired... * Updated Twitch API documentation * Futher changes * Removed debug output * Added changelog entry * Advice: don't code at 4am removed all silly debug stuff * Add missing lambda capture --- CHANGELOG.md | 1 + src/providers/twitch/TwitchAccount.cpp | 67 +++++++++++++++----------- src/providers/twitch/TwitchAccount.hpp | 1 - src/providers/twitch/api/Helix.cpp | 32 ++++++++++++ src/providers/twitch/api/Helix.hpp | 16 ++++++ src/providers/twitch/api/README.md | 8 +++ src/widgets/dialogs/EmotePopup.cpp | 3 +- 7 files changed, 96 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 907bb135..9fe6aa1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - Bugfix: Fixed pasting text with URLs included (#1688, #2855) - Bugfix: Fix reconnecting when IRC write connection is lost (#1831, #2356, #2850, #2892) - Bugfix: Fixed bit and new subscriber emotes not (re)loading in some rare cases. (#2856, #2857) +- Bugfix: Fixed subscription emotes showing up incorrectly in the emote menu. (#2905) ## 2.3.2 diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 6f70386f..580ee89b 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -358,7 +358,6 @@ void TwitchAccount::loadUserstateEmotes() name[0] = name[0].toUpper(); newUserEmoteSet->text = name; - newUserEmoteSet->type = QString(); newUserEmoteSet->channelName = ivrEmoteSet.login; for (const auto &emote : ivrEmoteSet.emotes) @@ -508,38 +507,48 @@ void TwitchAccount::loadEmoteSetData(std::shared_ptr emoteSet) return; } - NetworkRequest(Env::get().twitchEmoteSetResolverUrl.arg(emoteSet->key)) - .cache() - .onSuccess([emoteSet](NetworkResult result) -> Outcome { - auto root = result.parseJson(); - if (root.isEmpty()) + getHelix()->getEmoteSetData( + emoteSet->key, + [emoteSet](HelixEmoteSetData emoteSetData) { + if (emoteSetData.ownerId.isEmpty() || + emoteSetData.setId != emoteSet->key) { - return Failure; + qCWarning(chatterinoTwitch) + << QString("Failed to fetch emoteSetData for %1, assuming " + "Twitch is the owner") + .arg(emoteSet->key); + + // most (if not all) emotes that fail to load are time limited event emotes owned by Twitch + emoteSet->channelName = "twitch"; + emoteSet->text = "Twitch"; + + return; } - TwitchEmoteSetResolverResponse response(root); + // emote set 0 = global emotes + if (emoteSetData.ownerId == "0") + { + // emoteSet->channelName = QString(); + emoteSet->text = "Twitch Global"; + return; + } - auto name = response.channelName; - name.detach(); - name[0] = name[0].toUpper(); - - emoteSet->text = name; - emoteSet->type = response.type; - emoteSet->channelName = response.channelName; - - qCDebug(chatterinoTwitch) - << QString("Loaded twitch emote set data for %1") - .arg(emoteSet->key); - - return Success; - }) - .onError([emoteSet](NetworkResult result) { - qCWarning(chatterinoTwitch) - << QString("Error code %1 while loading emote set data for %2") - .arg(result.status()) - .arg(emoteSet->key); - }) - .execute(); + getHelix()->getUserById( + emoteSetData.ownerId, + [emoteSet](HelixUser user) { + emoteSet->channelName = user.login; + emoteSet->text = user.displayName; + }, + [emoteSetData] { + qCWarning(chatterinoTwitch) + << "Failed to query user by id:" << emoteSetData.ownerId + << emoteSetData.setId; + }); + }, + [emoteSet] { + // fetching emoteset data failed + return; + }); } } // namespace chatterino diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index 761a583e..fc1918b1 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -62,7 +62,6 @@ public: QString key; QString channelName; QString text; - QString type; std::vector emotes; }; diff --git a/src/providers/twitch/api/Helix.cpp b/src/providers/twitch/api/Helix.cpp index a105914a..c430b59c 100644 --- a/src/providers/twitch/api/Helix.cpp +++ b/src/providers/twitch/api/Helix.cpp @@ -761,6 +761,38 @@ void Helix::getCheermotes( .execute(); } +void Helix::getEmoteSetData(QString emoteSetId, + ResultCallback successCallback, + HelixFailureCallback failureCallback) +{ + QUrlQuery urlQuery; + + urlQuery.addQueryItem("emote_set_id", emoteSetId); + + this->makeRequest("chat/emotes/set", urlQuery) + .onSuccess([successCallback, failureCallback, + emoteSetId](auto result) -> Outcome { + QJsonObject root = result.parseJson(); + auto data = root.value("data"); + + if (!data.isArray()) + { + failureCallback(); + return Failure; + } + + HelixEmoteSetData emoteSetData(data.toArray()[0].toObject()); + + successCallback(emoteSetData); + return Success; + }) + .onError([failureCallback](NetworkResult result) { + // TODO: make better xd + failureCallback(); + }) + .execute(); +} + NetworkRequest Helix::makeRequest(QString url, QUrlQuery urlQuery) { assert(!url.startsWith("/")); diff --git a/src/providers/twitch/api/Helix.hpp b/src/providers/twitch/api/Helix.hpp index 6e027391..a4f745a7 100644 --- a/src/providers/twitch/api/Helix.hpp +++ b/src/providers/twitch/api/Helix.hpp @@ -264,6 +264,17 @@ struct HelixCheermoteSet { } }; +struct HelixEmoteSetData { + QString setId; + QString ownerId; + + explicit HelixEmoteSetData(QJsonObject jsonObject) + : setId(jsonObject.value("emote_set_id").toString()) + , ownerId(jsonObject.value("owner_id").toString()) + { + } +}; + enum class HelixClipError { Unknown, ClipsDisabled, @@ -398,6 +409,11 @@ public: ResultCallback> successCallback, HelixFailureCallback failureCallback); + // https://dev.twitch.tv/docs/api/reference#get-emote-sets + void getEmoteSetData(QString emoteSetId, + ResultCallback successCallback, + HelixFailureCallback failureCallback); + void update(QString clientId, QString oauthToken); static void initialize(); diff --git a/src/providers/twitch/api/README.md b/src/providers/twitch/api/README.md index 9b24e8f7..2a4a2ded 100644 --- a/src/providers/twitch/api/README.md +++ b/src/providers/twitch/api/README.md @@ -157,6 +157,14 @@ URL: https://dev.twitch.tv/docs/api/reference/#get-cheermotes Used in: - `providers/twitch/TwitchChannel.cpp` to resolve a chats available cheer emotes. This helps us parse incoming messages like `pajaCheer1000` +### Get Emote Sets + +URL: https://dev.twitch.tv/docs/api/reference#get-emote-sets + +- We implement this in `providers/twitch/api/Helix.cpp getEmoteSetData` + Used in: + - `providers/twitch/TwitchAccount.cpp` to set emoteset owner data upon loading subscriber emotes from Kraken + ## TMI The TMI api is undocumented. diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 90bb80c6..ce839b4b 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -71,8 +71,7 @@ namespace { { // TITLE auto channelName = set->channelName; - auto text = - set->key == "0" || set->text.isEmpty() ? "Twitch" : set->text; + auto text = set->text.isEmpty() ? "Twitch" : set->text; // EMOTES MessageBuilder builder;