Added clip creation support 🎬 (#2271)

You can create clips with `/clip` command, `Alt+X` keybind or `Create a clip` option in split header's context menu. This requires a new authentication scope so re-authentication will be required to use it.

Co-authored-by: Leon Richardt <leon.richardt@gmail.com>
Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
Paweł
2021-01-17 14:47:34 +01:00
committed by GitHub
parent 0542b81a03
commit cfcac99ae6
12 changed files with 253 additions and 8 deletions
+108 -1
View File
@@ -35,8 +35,19 @@
namespace chatterino {
namespace {
constexpr int TITLE_REFRESH_PERIOD = 10;
constexpr char MAGIC_MESSAGE_SUFFIX[] = u8" \U000E0000";
constexpr int TITLE_REFRESH_PERIOD = 10;
constexpr int CLIP_CREATION_COOLDOWN = 5000;
const QString CLIPS_LINK("https://clips.twitch.tv/%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.");
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.");
const QString LOGIN_PROMPT_TEXT("Click here to add your account again.");
const Link ACCOUNTS_LINK(Link::OpenAccountsPage, QString());
// convertClearchatToNotice takes a Communi::IrcMessage that is a CLEARCHAT command and converts it to a readable NOTICE message
// This has historically been done in the Recent Messages API, but this functionality is being moved to Chatterino instead
@@ -938,6 +949,102 @@ void TwitchChannel::refreshCheerEmotes()
.execute();
}
void TwitchChannel::createClip()
{
if (!this->isLive())
{
this->addMessage(makeSystemMessage(
"Cannot create clip while the channel is offline!"));
return;
}
if (QTime().currentTime() < this->timeNextClipCreationAllowed_ ||
this->isClipCreationInProgress)
{
return;
}
this->addMessage(makeSystemMessage("Creating clip..."));
this->isClipCreationInProgress = true;
getHelix()->createClip(
this->roomId(),
// successCallback
[this](const HelixClip &clip) {
MessageBuilder builder;
builder.message().flags.set(MessageFlag::System);
builder.emplace<TimestampElement>();
// text
builder.emplace<TextElement>("Clip created!",
MessageElementFlag::Text,
MessageColor::System);
// clip link
builder
.emplace<TextElement>("Copy link to clipboard",
MessageElementFlag::Text,
MessageColor::Link)
->setLink(Link(Link::CopyToClipboard, CLIPS_LINK.arg(clip.id)));
// separator text
builder.emplace<TextElement>("or", MessageElementFlag::Text,
MessageColor::System);
// edit link
builder
.emplace<TextElement>("edit it in browser.",
MessageElementFlag::Text,
MessageColor::Link)
->setLink(Link(Link::Url, clip.editUrl));
this->addMessage(builder.release());
},
// failureCallback
[this](auto error) {
MessageBuilder builder;
builder.message().flags.set(MessageFlag::System);
builder.emplace<TimestampElement>();
switch (error)
{
case HelixClipError::ClipsDisabled: {
builder.emplace<TextElement>(
CLIPS_FAILURE_CLIPS_DISABLED_TEXT,
MessageElementFlag::Text, MessageColor::System);
}
break;
case HelixClipError::UserNotAuthenticated: {
builder.emplace<TextElement>(
CLIPS_FAILURE_NOT_AUTHENTICATED_TEXT,
MessageElementFlag::Text, MessageColor::System);
builder
.emplace<TextElement>(LOGIN_PROMPT_TEXT,
MessageElementFlag::Text,
MessageColor::Link)
->setLink(ACCOUNTS_LINK);
}
break;
// This would most likely happen if the service is down, or if the JSON payload returned has changed format
case HelixClipError::Unknown:
default: {
builder.emplace<TextElement>(
CLIPS_FAILURE_UNKNOWN_ERROR_TEXT,
MessageElementFlag::Text, MessageColor::System);
}
break;
}
this->addMessage(builder.release());
},
// finallyCallback - this will always execute, so clip creation won't ever be stuck
[this] {
this->timeNextClipCreationAllowed_ =
QTime().currentTime().addMSecs(CLIP_CREATION_COOLDOWN);
this->isClipCreationInProgress = false;
});
}
boost::optional<EmotePtr> TwitchChannel::twitchBadge(
const QString &set, const QString &version) const
{