Skip to content

Commit

Permalink
Fix emotesets not loading properly (Chatterino#2905)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
zneix authored Jun 24, 2021
1 parent ed6ef0b commit 0021290
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
69 changes: 39 additions & 30 deletions src/providers/twitch/TwitchAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -508,38 +507,48 @@ void TwitchAccount::loadEmoteSetData(std::shared_ptr<EmoteSet> 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);

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();
// emote set 0 = global emotes
if (emoteSetData.ownerId == "0")
{
// emoteSet->channelName = QString();
emoteSet->text = "Twitch Global";
return;
}

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
1 change: 0 additions & 1 deletion src/providers/twitch/TwitchAccount.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class TwitchAccount : public Account
QString key;
QString channelName;
QString text;
QString type;
std::vector<TwitchEmote> emotes;
};

Expand Down
32 changes: 32 additions & 0 deletions src/providers/twitch/api/Helix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,38 @@ void Helix::getCheermotes(
.execute();
}

void Helix::getEmoteSetData(QString emoteSetId,
ResultCallback<HelixEmoteSetData> 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("/"));
Expand Down
16 changes: 16 additions & 0 deletions src/providers/twitch/api/Helix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -398,6 +409,11 @@ class Helix final : boost::noncopyable
ResultCallback<std::vector<HelixCheermoteSet>> successCallback,
HelixFailureCallback failureCallback);

// https://dev.twitch.tv/docs/api/reference#get-emote-sets
void getEmoteSetData(QString emoteSetId,
ResultCallback<HelixEmoteSetData> successCallback,
HelixFailureCallback failureCallback);

void update(QString clientId, QString oauthToken);

static void initialize();
Expand Down
8 changes: 8 additions & 0 deletions src/providers/twitch/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 1 addition & 2 deletions src/widgets/dialogs/EmotePopup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 0021290

Please sign in to comment.