Skip to content

Commit

Permalink
Split list of emote sets into bunches when performing Ivr API reqeusts (
Browse files Browse the repository at this point in the history
  • Loading branch information
zneix committed Jun 6, 2021
1 parent f1e843a commit 2f568b8
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions src/providers/IvrApi.hpp
Expand Up @@ -74,8 +74,7 @@ class IvrApi final : boost::noncopyable
ResultCallback<IvrSubage> 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<QJsonArray> successCallback,
IvrFailureCallback failureCallback);
Expand Down
101 changes: 62 additions & 39 deletions src/providers/twitch/TwitchAccount.cpp
Expand Up @@ -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)
{
Expand All @@ -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<EmoteSet>();

IvrEmoteSet ivrEmoteSet(emoteSet.toObject());
// splitting newEmoteSetKeys to batches of 100, because Ivr API endpoint accepts a maximum of 100 emotesets at once
constexpr int batchSize = 100;

newUserEmoteSet->key = ivrEmoteSet.setId;
std::vector<QStringList> batches;

auto name = ivrEmoteSet.login;
name.detach();
name[0] = name[0].toUpper();
batches.reserve((newEmoteSetKeys.size() + 1) / batchSize);

newUserEmoteSet->text = name;
newUserEmoteSet->type = QString();
newUserEmoteSet->channelName = ivrEmoteSet.login;
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);
}

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<EmoteSet>();

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<const TwitchAccount::TwitchAccountEmoteData>
Expand Down

0 comments on commit 2f568b8

Please sign in to comment.