Split list of emote sets into bunches when performing Ivr API reqeusts (#2856)

This commit is contained in:
Paweł 2021-06-06 19:27:45 +02:00 committed by GitHub
parent f1e843a672
commit 2f568b88ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 41 deletions

View file

@ -15,6 +15,7 @@
- Minor: Switch to Twitch v2 emote API for animated emote support. (#2863) - Minor: Switch to Twitch v2 emote API for animated emote support. (#2863)
- Bugfix: Fixed FFZ emote links for global emotes (#2807, #2808) - Bugfix: Fixed FFZ emote links for global emotes (#2807, #2808)
- Bugfix: Fix reconnecting when IRC write connection is lost (#1831, #2356, #2850) - 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 ## 2.3.2

View file

@ -74,8 +74,7 @@ public:
ResultCallback<IvrSubage> resultCallback, ResultCallback<IvrSubage> resultCallback,
IvrFailureCallback failureCallback); IvrFailureCallback failureCallback);
// https://api.ivr.fi/docs#tag/Twitch/paths/~1twitch~1emoteset~1{setid}/get // https://api.ivr.fi/docs#tag/Twitch/paths/~1twitch~1emoteset/get
// however, we use undocumented endpoint, which takes ?set_id=1,2,3,4,... as query parameter
void getBulkEmoteSets(QString emoteSetList, void getBulkEmoteSets(QString emoteSetList,
ResultCallback<QJsonArray> successCallback, ResultCallback<QJsonArray> successCallback,
IvrFailureCallback failureCallback); IvrFailureCallback failureCallback);

View file

@ -281,11 +281,13 @@ void TwitchAccount::loadUserstateEmotes(QStringList emoteSetKeys)
auto userEmoteSets = emoteData->emoteSets; auto userEmoteSets = emoteData->emoteSets;
QStringList newEmoteSetKeys, currentEmoteSetKeys; QStringList newEmoteSetKeys, currentEmoteSetKeys;
// get list of already fetched emote sets // get list of already fetched emote sets
for (const auto &userEmoteSet : userEmoteSets) for (const auto &userEmoteSet : userEmoteSets)
{ {
currentEmoteSetKeys.push_back(userEmoteSet->key); currentEmoteSetKeys.push_back(userEmoteSet->key);
} }
// filter out emote sets from userstate message, which are not in fetched emote set list // filter out emote sets from userstate message, which are not in fetched emote set list
for (const auto &emoteSetKey : emoteSetKeys) for (const auto &emoteSetKey : emoteSetKeys)
{ {
@ -301,54 +303,75 @@ void TwitchAccount::loadUserstateEmotes(QStringList emoteSetKeys)
return; return;
} }
getIvr()->getBulkEmoteSets( // splitting newEmoteSetKeys to batches of 100, because Ivr API endpoint accepts a maximum of 100 emotesets at once
newEmoteSetKeys.join(","), constexpr int batchSize = 100;
[this](QJsonArray emoteSetArray) {
auto emoteData = this->emotes_.access();
for (auto emoteSet : emoteSetArray)
{
auto newUserEmoteSet = std::make_shared<EmoteSet>();
IvrEmoteSet ivrEmoteSet(emoteSet.toObject()); std::vector<QStringList> batches;
newUserEmoteSet->key = ivrEmoteSet.setId; batches.reserve((newEmoteSetKeys.size() + 1) / batchSize);
auto name = ivrEmoteSet.login; for (int i = 0; i < newEmoteSetKeys.size(); i += batchSize)
name.detach(); {
name[0] = name[0].toUpper(); QStringList batch;
for (int j = batchSize * i; j < batchSize; j++)
{
batch.push_back(newEmoteSetKeys.at(j));
}
batches.emplace_back(batch);
}
newUserEmoteSet->text = name; for (const auto &batch : batches)
newUserEmoteSet->type = QString(); {
newUserEmoteSet->channelName = ivrEmoteSet.login; getIvr()->getBulkEmoteSets(
batch.join(","),
for (const auto &emote : ivrEmoteSet.emotes) [this](QJsonArray emoteSetArray) {
auto emoteData = this->emotes_.access();
for (auto emoteSet : emoteSetArray)
{ {
IvrEmote ivrEmote(emote.toObject()); auto newUserEmoteSet = std::make_shared<EmoteSet>();
auto id = EmoteId{ivrEmote.id}; IvrEmoteSet ivrEmoteSet(emoteSet.toObject());
auto code = EmoteName{ivrEmote.code};
auto cleanCode =
EmoteName{TwitchEmotes::cleanUpEmoteCode(code)};
newUserEmoteSet->emotes.emplace_back(
TwitchEmote{id, cleanCode});
emoteData->allEmoteNames.push_back(cleanCode); newUserEmoteSet->key = ivrEmoteSet.setId;
auto twitchEmote = auto name = ivrEmoteSet.login;
getApp()->emotes->twitch.getOrCreateEmote(id, code); name.detach();
emoteData->emotes.emplace(code, twitchEmote); 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) { // fetching emotes failed, ivr API might be down
return l.name.string < r.name.string; });
}); };
emoteData->emoteSets.emplace_back(newUserEmoteSet); return;
}
},
[] {
// fetching emotes failed, ivr API might be down
});
} }
SharedAccessGuard<const TwitchAccount::TwitchAccountEmoteData> SharedAccessGuard<const TwitchAccount::TwitchAccountEmoteData>