-
-
Notifications
You must be signed in to change notification settings - Fork 455
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
382 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#include "controllers/commands/builtin/twitch/Warn.hpp" | ||
|
||
#include "Application.hpp" | ||
#include "common/QLogging.hpp" | ||
#include "controllers/accounts/AccountController.hpp" | ||
#include "controllers/commands/CommandContext.hpp" | ||
#include "controllers/commands/common/ChannelAction.hpp" | ||
#include "messages/MessageBuilder.hpp" | ||
#include "providers/twitch/api/Helix.hpp" | ||
#include "providers/twitch/TwitchAccount.hpp" | ||
#include "providers/twitch/TwitchChannel.hpp" | ||
|
||
namespace { | ||
|
||
using namespace chatterino; | ||
|
||
void warnUserByID(const ChannelPtr &channel, const QString &channelID, | ||
const QString &sourceUserID, const QString &targetUserID, | ||
const QString &reason, const QString &displayName) | ||
{ | ||
using Error = HelixWarnUserError; | ||
|
||
getHelix()->warnUser( | ||
channelID, sourceUserID, targetUserID, reason, | ||
[] { | ||
// No response for warns, they're emitted over pubsub instead | ||
}, | ||
[channel, displayName](auto error, auto message) { | ||
QString errorMessage = QString("Failed to warn user - "); | ||
switch (error) | ||
{ | ||
case Error::ConflictingOperation: { | ||
errorMessage += "There was a conflicting warn operation on " | ||
"this user. Please try again."; | ||
} | ||
break; | ||
|
||
case Error::Forwarded: { | ||
errorMessage += message; | ||
} | ||
break; | ||
|
||
case Error::Ratelimited: { | ||
errorMessage += "You are being ratelimited by Twitch. Try " | ||
"again in a few seconds."; | ||
} | ||
break; | ||
|
||
case Error::CannotWarnUser: { | ||
errorMessage += | ||
QString("You cannot warn %1.").arg(displayName); | ||
} | ||
break; | ||
|
||
case Error::UserMissingScope: { | ||
// TODO(pajlada): Phrase MISSING_REQUIRED_SCOPE | ||
errorMessage += "Missing required scope. " | ||
"Re-login with your " | ||
"account and try again."; | ||
} | ||
break; | ||
|
||
case Error::UserNotAuthorized: { | ||
// TODO(pajlada): Phrase MISSING_PERMISSION | ||
errorMessage += "You don't have permission to " | ||
"perform that action."; | ||
} | ||
break; | ||
|
||
case Error::Unknown: { | ||
errorMessage += "An unknown error has occurred."; | ||
} | ||
break; | ||
} | ||
|
||
channel->addMessage(makeSystemMessage(errorMessage)); | ||
}); | ||
} | ||
|
||
} // namespace | ||
|
||
namespace chatterino::commands { | ||
|
||
QString sendWarn(const CommandContext &ctx) | ||
{ | ||
const auto command = QStringLiteral("/warn"); | ||
const auto usage = QStringLiteral( | ||
R"(Usage: "/warn [options...] <username> <reason>" - Warn a user via their username. Reason is required and will be shown to the target user and other moderators. Options: --channel <channel> to override which channel the warn takes place in (can be specified multiple times).)"); | ||
const auto actions = parseChannelAction(ctx, command, usage, false, true); | ||
|
||
if (!actions.has_value()) | ||
{ | ||
if (ctx.channel != nullptr) | ||
{ | ||
ctx.channel->addMessage(makeSystemMessage(actions.error())); | ||
} | ||
else | ||
{ | ||
qCWarning(chatterinoCommands) | ||
<< "Error parsing command:" << actions.error(); | ||
} | ||
|
||
return ""; | ||
} | ||
|
||
assert(!actions.value().empty()); | ||
|
||
auto currentUser = getIApp()->getAccounts()->twitch.getCurrent(); | ||
if (currentUser->isAnon()) | ||
{ | ||
ctx.channel->addMessage( | ||
makeSystemMessage("You must be logged in to warn someone!")); | ||
return ""; | ||
} | ||
|
||
for (const auto &action : actions.value()) | ||
{ | ||
const auto &reason = action.reason; | ||
if (reason.isEmpty()) | ||
{ | ||
ctx.channel->addMessage( | ||
makeSystemMessage("Failed to warn, you must specify a reason")); | ||
break; | ||
} | ||
|
||
QStringList userLoginsToFetch; | ||
QStringList userIDs; | ||
if (action.target.id.isEmpty()) | ||
{ | ||
assert(!action.target.login.isEmpty() && | ||
"Warn Action target username AND user ID may not be " | ||
"empty at the same time"); | ||
userLoginsToFetch.append(action.target.login); | ||
} | ||
else | ||
{ | ||
// For hydration | ||
userIDs.append(action.target.id); | ||
} | ||
if (action.channel.id.isEmpty()) | ||
{ | ||
assert(!action.channel.login.isEmpty() && | ||
"Warn Action channel username AND user ID may not be " | ||
"empty at the same time"); | ||
userLoginsToFetch.append(action.channel.login); | ||
} | ||
else | ||
{ | ||
// For hydration | ||
userIDs.append(action.channel.id); | ||
} | ||
|
||
if (!userLoginsToFetch.isEmpty()) | ||
{ | ||
// At least 1 user ID needs to be resolved before we can take action | ||
// userIDs is filled up with the data we already have to hydrate the action channel & action target | ||
getHelix()->fetchUsers( | ||
userIDs, userLoginsToFetch, | ||
[channel{ctx.channel}, actionChannel{action.channel}, | ||
actionTarget{action.target}, currentUser, reason, | ||
userLoginsToFetch](const auto &users) mutable { | ||
if (!actionChannel.hydrateFrom(users)) | ||
{ | ||
channel->addMessage(makeSystemMessage( | ||
QString("Failed to warn, bad channel name: %1") | ||
.arg(actionChannel.login))); | ||
return; | ||
} | ||
if (!actionTarget.hydrateFrom(users)) | ||
{ | ||
channel->addMessage(makeSystemMessage( | ||
QString("Failed to warn, bad target name: %1") | ||
.arg(actionTarget.login))); | ||
return; | ||
} | ||
|
||
warnUserByID(channel, actionChannel.id, | ||
currentUser->getUserId(), actionTarget.id, | ||
reason, actionTarget.displayName); | ||
}, | ||
[channel{ctx.channel}, userLoginsToFetch] { | ||
channel->addMessage(makeSystemMessage( | ||
QString("Failed to warn, bad username(s): %1") | ||
.arg(userLoginsToFetch.join(", ")))); | ||
}); | ||
} | ||
else | ||
{ | ||
// If both IDs are available, we do no hydration & just use the id as the display name | ||
warnUserByID(ctx.channel, action.channel.id, | ||
currentUser->getUserId(), action.target.id, reason, | ||
action.target.id); | ||
} | ||
} | ||
|
||
return ""; | ||
} | ||
|
||
} // namespace chatterino::commands |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
|
||
class QString; | ||
|
||
namespace chatterino { | ||
|
||
struct CommandContext; | ||
|
||
} // namespace chatterino | ||
|
||
namespace chatterino::commands { | ||
|
||
/// /warn | ||
QString sendWarn(const CommandContext &ctx); | ||
|
||
} // namespace chatterino::commands |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.