From 2f568b88ae2a86aa298a627dfa8e058dd8cb44a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82?= Date: Sun, 6 Jun 2021 19:27:45 +0200 Subject: [PATCH] Split list of emote sets into bunches when performing Ivr API reqeusts (#2856) --- CHANGELOG.md | 1 + src/providers/IvrApi.hpp | 3 +- src/providers/twitch/TwitchAccount.cpp | 101 +++++++++++++++---------- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bc5e9d6e..b76b2d621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Minor: Switch to Twitch v2 emote API for animated emote support. (#2863) - Bugfix: Fixed FFZ emote links for global emotes (#2807, #2808) - Bugfix: Fix reconnecting when IRC write connection is lost (#1831, #2356, #2850) +- Bugfix: Fixed bit emotes not loading in some rare cases. (#2856) ## 2.3.2 diff --git a/src/providers/IvrApi.hpp b/src/providers/IvrApi.hpp index 1a658cdba..857a48696 100644 --- a/src/providers/IvrApi.hpp +++ b/src/providers/IvrApi.hpp @@ -74,8 +74,7 @@ public: ResultCallback resultCallback, IvrFailureCallback failureCallback); - // https://api.ivr.fi/docs#tag/Twitch/paths/~1twitch~1emoteset~1{setid}/get - // however, we use undocumented endpoint, which takes ?set_id=1,2,3,4,... as query parameter + // https://api.ivr.fi/docs#tag/Twitch/paths/~1twitch~1emoteset/get void getBulkEmoteSets(QString emoteSetList, ResultCallback successCallback, IvrFailureCallback failureCallback); diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 675155681..e98707cc5 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -281,11 +281,13 @@ void TwitchAccount::loadUserstateEmotes(QStringList emoteSetKeys) auto userEmoteSets = emoteData->emoteSets; QStringList newEmoteSetKeys, currentEmoteSetKeys; + // get list of already fetched emote sets for (const auto &userEmoteSet : userEmoteSets) { currentEmoteSetKeys.push_back(userEmoteSet->key); } + // filter out emote sets from userstate message, which are not in fetched emote set list for (const auto &emoteSetKey : emoteSetKeys) { @@ -301,54 +303,75 @@ void TwitchAccount::loadUserstateEmotes(QStringList emoteSetKeys) return; } - getIvr()->getBulkEmoteSets( - newEmoteSetKeys.join(","), - [this](QJsonArray emoteSetArray) { - auto emoteData = this->emotes_.access(); - for (auto emoteSet : emoteSetArray) - { - auto newUserEmoteSet = std::make_shared(); + // splitting newEmoteSetKeys to batches of 100, because Ivr API endpoint accepts a maximum of 100 emotesets at once + constexpr int batchSize = 100; - IvrEmoteSet ivrEmoteSet(emoteSet.toObject()); + std::vector batches; - newUserEmoteSet->key = ivrEmoteSet.setId; + batches.reserve((newEmoteSetKeys.size() + 1) / batchSize); - auto name = ivrEmoteSet.login; - name.detach(); - name[0] = name[0].toUpper(); + for (int i = 0; i < newEmoteSetKeys.size(); i += batchSize) + { + QStringList batch; + for (int j = batchSize * i; j < batchSize; j++) + { + batch.push_back(newEmoteSetKeys.at(j)); + } + batches.emplace_back(batch); + } - newUserEmoteSet->text = name; - newUserEmoteSet->type = QString(); - newUserEmoteSet->channelName = ivrEmoteSet.login; - - for (const auto &emote : ivrEmoteSet.emotes) + for (const auto &batch : batches) + { + getIvr()->getBulkEmoteSets( + batch.join(","), + [this](QJsonArray emoteSetArray) { + auto emoteData = this->emotes_.access(); + for (auto emoteSet : emoteSetArray) { - IvrEmote ivrEmote(emote.toObject()); + auto newUserEmoteSet = std::make_shared(); - auto id = EmoteId{ivrEmote.id}; - auto code = EmoteName{ivrEmote.code}; - auto cleanCode = - EmoteName{TwitchEmotes::cleanUpEmoteCode(code)}; - newUserEmoteSet->emotes.emplace_back( - TwitchEmote{id, cleanCode}); + IvrEmoteSet ivrEmoteSet(emoteSet.toObject()); - emoteData->allEmoteNames.push_back(cleanCode); + newUserEmoteSet->key = ivrEmoteSet.setId; - auto twitchEmote = - getApp()->emotes->twitch.getOrCreateEmote(id, code); - emoteData->emotes.emplace(code, twitchEmote); + auto name = ivrEmoteSet.login; + name.detach(); + name[0] = name[0].toUpper(); + + newUserEmoteSet->text = name; + newUserEmoteSet->type = QString(); + newUserEmoteSet->channelName = ivrEmoteSet.login; + + for (const auto &emote : ivrEmoteSet.emotes) + { + IvrEmote ivrEmote(emote.toObject()); + + auto id = EmoteId{ivrEmote.id}; + auto code = EmoteName{ivrEmote.code}; + auto cleanCode = + EmoteName{TwitchEmotes::cleanUpEmoteCode(code)}; + newUserEmoteSet->emotes.push_back( + TwitchEmote{id, cleanCode}); + + emoteData->allEmoteNames.push_back(cleanCode); + + auto twitchEmote = + getApp()->emotes->twitch.getOrCreateEmote(id, code); + emoteData->emotes.emplace(code, twitchEmote); + } + std::sort(newUserEmoteSet->emotes.begin(), + newUserEmoteSet->emotes.end(), + [](const TwitchEmote &l, const TwitchEmote &r) { + return l.name.string < r.name.string; + }); + emoteData->emoteSets.emplace_back(newUserEmoteSet); } - std::sort(newUserEmoteSet->emotes.begin(), - newUserEmoteSet->emotes.end(), - [](const TwitchEmote &l, const TwitchEmote &r) { - return l.name.string < r.name.string; - }); - emoteData->emoteSets.emplace_back(newUserEmoteSet); - } - }, - [] { - // fetching emotes failed, ivr API might be down - }); + }, + [] { + // fetching emotes failed, ivr API might be down + }); + }; + return; } SharedAccessGuard