feat: improve create clip error messaging (#5879)

This commit is contained in:
pajlada
2025-02-01 13:18:34 +01:00
committed by GitHub
parent 810d3cdfd6
commit f629eecaa7
5 changed files with 89 additions and 24 deletions
+1
View File
@@ -8,6 +8,7 @@
- Minor: Remove incognito browser support for `iexplore`, because internet explorer is EOL. (#5810)
- Minor: When (re-)connecting, visible channels are now joined first. (#5850)
- Minor: Added the ability to filter on messages by the author's user ID (example: `author.user_id == "22484632"`). (#5862)
- Minor: Improved error messaging of the `/clip` command. (#5879)
- Bugfix: Fixed a potential way to escape the Lua Plugin sandbox. (#5846)
- Bugfix: Fixed a crash relating to Lua HTTP. (#5800)
- Bugfix: Fixed a crash that could occur on Linux and macOS when clicking "Install" from the update prompt. (#5818)
+1 -1
View File
@@ -78,7 +78,7 @@ public:
MOCK_METHOD(void, createClip,
(QString channelId, ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError)> failureCallback,
std::function<void(HelixClipError, QString)> failureCallback,
std::function<void()> finallyCallback),
(override));
+39 -6
View File
@@ -67,13 +67,21 @@ namespace {
#endif
constexpr int CLIP_CREATION_COOLDOWN = 5000;
const QString CLIPS_LINK("https://clips.twitch.tv/%1");
const QString CLIPS_FAILURE_CLIPS_UNAVAILABLE_TEXT(
"Failed to create a clip - clips are temporarily unavailable: %1");
const QString CLIPS_FAILURE_CLIPS_DISABLED_TEXT(
"Failed to create a clip - the streamer has clips disabled entirely or "
"requires a certain subscriber or follower status to create clips.");
"Failed to create a clip - the streamer has clips disabled in their "
"channel.");
const QString CLIPS_FAILURE_CLIPS_RESTRICTED_TEXT(
"Failed to create a clip - the streamer has restricted clip creation "
"to subscribers, or followers of an unknown duration.");
const QString CLIPS_FAILURE_CLIPS_RESTRICTED_CATEGORY_TEXT(
"Failed to create a clip - the streamer has disabled clips while in "
"this category.");
const QString CLIPS_FAILURE_NOT_AUTHENTICATED_TEXT(
"Failed to create a clip - you need to re-authenticate.");
const QString CLIPS_FAILURE_UNKNOWN_ERROR_TEXT(
"Failed to create a clip - an unknown error occurred.");
"Failed to create a clip: %1");
const QString LOGIN_PROMPT_TEXT("Click here to add your account again.");
const Link ACCOUNTS_LINK(Link::OpenAccountsPage, QString());
@@ -1771,7 +1779,7 @@ void TwitchChannel::createClip()
this->addMessage(builder.release(), MessageContext::Original);
},
// failureCallback
[this](auto error) {
[this](auto error, auto errorMessage) {
MessageBuilder builder;
QString text;
builder.message().flags.set(MessageFlag::System);
@@ -1780,6 +1788,15 @@ void TwitchChannel::createClip()
switch (error)
{
case HelixClipError::ClipsUnavailable: {
builder.emplace<TextElement>(
CLIPS_FAILURE_CLIPS_UNAVAILABLE_TEXT.arg(errorMessage),
MessageElementFlag::Text, MessageColor::System);
text =
CLIPS_FAILURE_CLIPS_UNAVAILABLE_TEXT.arg(errorMessage);
}
break;
case HelixClipError::ClipsDisabled: {
builder.emplace<TextElement>(
CLIPS_FAILURE_CLIPS_DISABLED_TEXT,
@@ -1788,6 +1805,22 @@ void TwitchChannel::createClip()
}
break;
case HelixClipError::ClipsRestricted: {
builder.emplace<TextElement>(
CLIPS_FAILURE_CLIPS_RESTRICTED_TEXT,
MessageElementFlag::Text, MessageColor::System);
text = CLIPS_FAILURE_CLIPS_RESTRICTED_TEXT;
}
break;
case HelixClipError::ClipsRestrictedCategory: {
builder.emplace<TextElement>(
CLIPS_FAILURE_CLIPS_RESTRICTED_CATEGORY_TEXT,
MessageElementFlag::Text, MessageColor::System);
text = CLIPS_FAILURE_CLIPS_RESTRICTED_CATEGORY_TEXT;
}
break;
case HelixClipError::UserNotAuthenticated: {
builder.emplace<TextElement>(
CLIPS_FAILURE_NOT_AUTHENTICATED_TEXT,
@@ -1807,9 +1840,9 @@ void TwitchChannel::createClip()
case HelixClipError::Unknown:
default: {
builder.emplace<TextElement>(
CLIPS_FAILURE_UNKNOWN_ERROR_TEXT,
CLIPS_FAILURE_UNKNOWN_ERROR_TEXT.arg(errorMessage),
MessageElementFlag::Text, MessageColor::System);
text = CLIPS_FAILURE_UNKNOWN_ERROR_TEXT;
text = CLIPS_FAILURE_UNKNOWN_ERROR_TEXT.arg(errorMessage);
}
break;
}
+37 -9
View File
@@ -351,10 +351,10 @@ void Helix::getGameById(QString gameId,
failureCallback);
}
void Helix::createClip(QString channelId,
ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError)> failureCallback,
std::function<void()> finallyCallback)
void Helix::createClip(
QString channelId, ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError, QString)> failureCallback,
std::function<void()> finallyCallback)
{
QUrlQuery urlQuery;
urlQuery.addQueryItem("broadcaster_id", channelId);
@@ -367,7 +367,7 @@ void Helix::createClip(QString channelId,
if (!data.isArray())
{
failureCallback(HelixClipError::Unknown);
failureCallback(HelixClipError::Unknown, "No clip was created");
return;
}
@@ -376,17 +376,45 @@ void Helix::createClip(QString channelId,
successCallback(clip);
})
.onError([failureCallback](auto result) {
auto obj = result.parseJson();
auto message = obj.value("message").toString();
switch (result.status().value_or(0))
{
case 503: {
// Channel has disabled clip-creation, or channel has made cliops only creatable by followers and the user is not a follower (or subscriber)
failureCallback(HelixClipError::ClipsDisabled);
// We should not necessarily handle this, so the error messaging will use `message` if it exists
failureCallback(HelixClipError::ClipsUnavailable, message);
}
break;
case 401: {
// User does not have the required scope to be able to create clips, user must reauthenticate
failureCallback(HelixClipError::UserNotAuthenticated);
failureCallback(HelixClipError::UserNotAuthenticated,
message);
}
break;
case 403: {
if (message.contains("restricted for this channel"))
{
failureCallback(HelixClipError::ClipsDisabled, message);
}
else if (message.contains("User does not have permissions"))
{
failureCallback(HelixClipError::ClipsRestricted,
message);
}
else if (message.contains("restricted for this category"))
{
failureCallback(HelixClipError::ClipsRestrictedCategory,
message);
}
else
{
qCDebug(chatterinoTwitch)
<< "Failed to create a clip: "
<< result.formatError() << result.getData();
failureCallback(HelixClipError::Unknown, message);
}
}
break;
@@ -394,7 +422,7 @@ void Helix::createClip(QString channelId,
qCDebug(chatterinoTwitch)
<< "Failed to create a clip: " << result.formatError()
<< result.getData();
failureCallback(HelixClipError::Unknown);
failureCallback(HelixClipError::Unknown, message);
}
break;
}
+11 -8
View File
@@ -474,7 +474,10 @@ enum class HelixAnnouncementColor {
enum class HelixClipError {
Unknown,
ClipsUnavailable,
ClipsDisabled,
ClipsRestricted,
ClipsRestrictedCategory,
UserNotAuthenticated,
};
@@ -864,10 +867,10 @@ public:
HelixFailureCallback failureCallback) = 0;
// https://dev.twitch.tv/docs/api/reference#create-clip
virtual void createClip(QString channelId,
ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError)> failureCallback,
std::function<void()> finallyCallback) = 0;
virtual void createClip(
QString channelId, ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError, QString)> failureCallback,
std::function<void()> finallyCallback) = 0;
// https://dev.twitch.tv/docs/api/reference#get-channel-information
virtual void fetchChannels(
@@ -1207,10 +1210,10 @@ public:
HelixFailureCallback failureCallback) final;
// https://dev.twitch.tv/docs/api/reference#create-clip
void createClip(QString channelId,
ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError)> failureCallback,
std::function<void()> finallyCallback) final;
void createClip(
QString channelId, ResultCallback<HelixClip> successCallback,
std::function<void(HelixClipError, QString)> failureCallback,
std::function<void()> finallyCallback) final;
// https://dev.twitch.tv/docs/api/reference#get-channel-information
void fetchChannels(