Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Twitch badges to Helix #4537

Merged
merged 38 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9abe788
Initial implementation of Helix.cpp & Helix.hpp
ZonianMidian Apr 11, 2023
ad94591
Add changelog item
ZonianMidian Apr 11, 2023
e538c4a
Class declaration for errors
ZonianMidian Apr 11, 2023
b997784
New implementations and fixes for Helix.cpp and Helix.hpp
ZonianMidian Apr 12, 2023
cdaf33c
Minor correction
ZonianMidian Apr 12, 2023
e0db1e4
Class correction for clickURL in Helix.hpp
ZonianMidian Apr 12, 2023
ae4e27a
Removed unnecessary Content-Type
ZonianMidian Apr 12, 2023
8c99efb
Merge branch 'helix-migration/twitch-badges' of https://github.com/Zo…
ZonianMidian Apr 12, 2023
cd0c55d
Virtual functions getGlobalBadges and getChannelBadges defined in IHelix
ZonianMidian Apr 12, 2023
ca8653d
Added missing
ZonianMidian Apr 12, 2023
8702f8a
Added mock method to MockHelix for HelixGlobalBadges and HelixChannel…
ZonianMidian Apr 13, 2023
88cb070
Added extra parenthesis in mock method
ZonianMidian Apr 13, 2023
a0841cb
Correction of file formatting
ZonianMidian Apr 14, 2023
1218dc3
Merge branch 'master' into helix-migration/twitch-badges
ZonianMidian Apr 14, 2023
4f8fb94
Merge branch 'master' into helix-migration/twitch-badges
ZonianMidian Apr 15, 2023
97c4f52
Implementation of getGlobalsBadges in TwitchBadges.cpp
ZonianMidian Apr 15, 2023
dbff8bb
Merge branch 'helix-migration/twitch-badges' of https://github.com/Zo…
ZonianMidian Apr 15, 2023
521f297
Merge branch 'master' into helix-migration/twitch-badges
ZonianMidian Apr 15, 2023
30811e9
Fixing error message in TwitchBadges.cpp
ZonianMidian Apr 16, 2023
91677d6
Merge branch 'helix-migration/twitch-badges' of https://github.com/Zo…
ZonianMidian Apr 16, 2023
eb59af8
Implementation of getChannelBadges in TwitchChannel.cpp
ZonianMidian Apr 16, 2023
58b07dd
README update on Helix to add the new endpoints
ZonianMidian Apr 16, 2023
20feb1c
nit: const ref HelixBadgeVersion constructor parameter
pajlada Apr 16, 2023
17ca5ea
nit: Rename `json_versions` to `jsonVersions`
pajlada Apr 16, 2023
17ac301
nit: rename `badge_version` to `badgeVersion`
pajlada Apr 16, 2023
f50dae6
nit: use emplace_back to in-place construct badges
pajlada Apr 16, 2023
1b4f04f
nit: Remove HelixGlobalBadges default constructor
pajlada Apr 16, 2023
85c3517
nit: rename badges member `data` to `badgeSets`
pajlada Apr 16, 2023
3a84760
nit: Change the rare helix error cases to be warnings
pajlada Apr 16, 2023
3672216
nit: add space inbetween using & the makeRequest/variable definitions
pajlada Apr 16, 2023
8ccfb99
nit: don't specify the network request type to get
pajlada Apr 16, 2023
35d90f3
fix: we must make sure the channel is alive when channel badges finish
pajlada Apr 16, 2023
ffeb297
nit: Reformat Emote creation
pajlada Apr 16, 2023
f1907c9
nit: Remove const ref in emote creation
pajlada Apr 16, 2023
f6c855b
nit: add back scale for 1x url
pajlada Apr 16, 2023
ef89d7c
nit: keep `EmoteName{}` for specifying an empty emote name
pajlada Apr 16, 2023
1f31077
nit: Don't recreate the global badges
pajlada Apr 16, 2023
cc50428
Merge remote-tracking branch 'origin/master' into helix-migration/twi…
pajlada Apr 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Minor: Added the ability to reply to a message by `Shift + Right Click`ing the username. (#4424)
- Minor: Added better filter validation and error messages. (#4364)
- Minor: Updated the look of the Black Theme to be more in line with the other themes. (#4523)
- Minor: Migrated badges to Helix API. (#4537)
- Bugfix: Fixed an issue where animated emotes would render on top of zero-width emotes. (#4314)
- Bugfix: Fixed an issue where it was difficult to hover a zero-width emote. (#4314)
- Bugfix: Fixed an issue where context-menu items for zero-width emotes displayed the wrong provider. (#4460)
Expand Down
92 changes: 92 additions & 0 deletions src/providers/twitch/api/Helix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,98 @@ void Helix::startCommercial(
.execute();
}

// Twitch global badges
// https://dev.twitch.tv/docs/api/reference/#get-global-chat-badges
void Helix::getGlobalBadges(
ResultCallback<HelixGlobalBadges> successCallback,
FailureCallback<HelixGetGlobalBadgesError, QString> failureCallback)
{
using Error = HelixGetGlobalBadgesError;
this->makeRequest("chat/badges/global", QUrlQuery())
.type(NetworkRequestType::Get)
.onSuccess([successCallback](auto result) -> Outcome {
if (result.status() != 200)
{
qCWarning(chatterinoTwitch)
<< "Success result for getting global badges was "
<< result.status() << "but we expected it to be 200";
}

auto response = result.parseJson();
successCallback(HelixGlobalBadges(response));
return Success;
})
.onError([failureCallback](auto result) {
auto obj = result.parseJson();
auto message = obj.value("message").toString();

switch (result.status())
{
case 401: {
failureCallback(Error::Forwarded, message);
}
break;

default: {
qCDebug(chatterinoTwitch)
<< "Unhandled error data:" << result.status()
<< result.getData() << obj;
failureCallback(Error::Unknown, message);
}
break;
}
})
.execute();
}

// Badges for the `broadcasterID` channel
// https://dev.twitch.tv/docs/api/reference/#get-channel-chat-badges
void Helix::getChannelBadges(
QString broadcasterID, ResultCallback<HelixChannelBadges> successCallback,
FailureCallback<HelixGetChannelBadgesError, QString> failureCallback)
{
using Error = HelixGetChannelBadgesError;
QUrlQuery urlQuery;
urlQuery.addQueryItem("broadcaster_id", broadcasterID);

this->makeRequest("chat/badges", urlQuery)
.type(NetworkRequestType::Get)
.onSuccess([successCallback](auto result) -> Outcome {
if (result.status() != 200)
{
qCWarning(chatterinoTwitch)
<< "Success result for getting badges was "
<< result.status() << "but we expected it to be 200";
}

auto response = result.parseJson();
successCallback(HelixChannelBadges(response));
return Success;
})
.onError([failureCallback](auto result) {
auto obj = result.parseJson();
auto message = obj.value("message").toString();

switch (result.status())
{
case 400:
case 401: {
failureCallback(Error::Forwarded, message);
}
break;

default: {
qCDebug(chatterinoTwitch)
<< "Unhandled error data:" << result.status()
<< result.getData() << obj;
failureCallback(Error::Unknown, message);
}
break;
}
})
.execute();
}

NetworkRequest Helix::makeRequest(QString url, QUrlQuery urlQuery)
{
assert(!url.startsWith("/"));
Expand Down
94 changes: 92 additions & 2 deletions src/providers/twitch/api/Helix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,59 @@ struct HelixModerators {
}
};

struct HelixBadgeVersion
{
QString id;
Url imageURL1x;
Url imageURL2x;
Url imageURL4x;
QString title;
Url clickURL;

explicit HelixBadgeVersion(QJsonObject jsonObject)
: id(jsonObject.value("id").toString())
, imageURL1x(Url{jsonObject.value("image_url_1x").toString()})
, imageURL2x(Url{jsonObject.value("image_url_2x").toString()})
, imageURL4x(Url{jsonObject.value("image_url_4x").toString()})
, title(jsonObject.value("title").toString())
, clickURL(Url{jsonObject.value("click_url").toString()})
{
}
};

struct HelixBadgeSet
{
QString setID;
std::vector<HelixBadgeVersion> versions;

explicit HelixBadgeSet(const QJsonObject& json)
: setID(json.value("set_id").toString())
{
const auto json_versions = json.value("versions").toArray();
ZonianMidian marked this conversation as resolved.
Show resolved Hide resolved
for (const auto& version : json_versions)
{
HelixBadgeVersion badge_version(version.toObject());
versions.push_back(badge_version);
}
}
};

struct HelixGlobalBadges {
std::vector<HelixBadgeSet> data;
HelixGlobalBadges() = default;
explicit HelixGlobalBadges(const QJsonObject &jsonObject)
{
const auto &data = jsonObject.value("data").toArray();
for (const auto &set : data)
{
HelixBadgeSet badgeSet(set.toObject());
this->data.push_back(badgeSet);
}
}
};

using HelixChannelBadges = HelixGlobalBadges;

enum class HelixAnnouncementColor {
Blue,
Green,
Expand Down Expand Up @@ -616,6 +669,20 @@ enum class HelixStartCommercialError {
Forwarded,
};

enum class HelixGetGlobalBadgesError {
Unknown,

// The error message is forwarded directly from the Twitch API
Forwarded,
};

enum class HelixGetChannelBadgesError {
Unknown,

// The error message is forwarded directly from the Twitch API
Forwarded,
};

class IHelix
{
public:
Expand Down Expand Up @@ -896,8 +963,19 @@ class IHelix
virtual void startCommercial(
QString broadcasterID, int length,
ResultCallback<HelixStartCommercialResponse> successCallback,
FailureCallback<HelixStartCommercialError, QString>
failureCallback) = 0;
FailureCallback<HelixStartCommercialError, QString> failureCallback) = 0;

// Get global Twitch badges
// https://dev.twitch.tv/docs/api/reference/#get-global-chat-badges
virtual void getGlobalBadges(
ResultCallback<HelixGlobalBadges> successCallback,
FailureCallback<HelixGetGlobalBadgesError, QString> failureCallback) = 0;

// Get badges for the `broadcasterID` channel
// https://dev.twitch.tv/docs/api/reference/#get-channel-chat-badges
virtual void getChannelBadges(
QString broadcasterID, ResultCallback<HelixChannelBadges> successCallback,
FailureCallback<HelixGetChannelBadgesError, QString> failureCallback) = 0;

virtual void update(QString clientId, QString oauthToken) = 0;

Expand Down Expand Up @@ -1184,6 +1262,18 @@ class Helix final : public IHelix
FailureCallback<HelixStartCommercialError, QString> failureCallback)
final;

// Get global Twitch badges
// https://dev.twitch.tv/docs/api/reference/#get-global-chat-badges
void getGlobalBadges(
ResultCallback<HelixGlobalBadges> successCallback,
FailureCallback<HelixGetGlobalBadgesError, QString> failureCallback) final;

// Get badges for the `broadcasterID` channel
// https://dev.twitch.tv/docs/api/reference/#get-channel-chat-badges
void getChannelBadges(
QString broadcasterID, ResultCallback<HelixChannelBadges> successCallback,
FailureCallback<HelixGetChannelBadgesError, QString> failureCallback) final;

void update(QString clientId, QString oauthToken) final;

static void initialize();
Expand Down