Merge pull request #925 from apa420/apa-automod-implementation
Automod implementation
This commit is contained in:
@@ -105,4 +105,26 @@ struct ModerationStateAction : PubSubAction {
|
||||
bool modded;
|
||||
};
|
||||
|
||||
struct AutomodAction : PubSubAction {
|
||||
using PubSubAction::PubSubAction;
|
||||
|
||||
ActionUser target;
|
||||
|
||||
QString message;
|
||||
|
||||
QString reason;
|
||||
|
||||
QString msgID;
|
||||
};
|
||||
|
||||
struct AutomodUserAction : PubSubAction {
|
||||
using PubSubAction::PubSubAction;
|
||||
|
||||
ActionUser target;
|
||||
|
||||
QString message;
|
||||
|
||||
qint8 type;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -520,6 +520,196 @@ PubSub::PubSub()
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["automod_rejected"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// Display the automod message and prompt the allow/deny
|
||||
AutomodAction action(data, roomID);
|
||||
|
||||
getCreatedByUser(data, action.source);
|
||||
getTargetUser(data, action.target);
|
||||
|
||||
try
|
||||
{
|
||||
const auto &args = getArgs(data);
|
||||
const auto &msgID = getMsgID(data);
|
||||
|
||||
if (args.Size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rj::getSafe(args[0], action.target.name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Size() >= 2)
|
||||
{
|
||||
if (!rj::getSafe(args[1], action.message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.Size() >= 3)
|
||||
{
|
||||
if (!rj::getSafe(args[2], action.reason))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rj::getSafe(msgID, action.msgID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->signals_.moderation.automodMessage.invoke(action);
|
||||
}
|
||||
catch (const std::runtime_error &ex)
|
||||
{
|
||||
log("Error parsing moderation action: {}", ex.what());
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["add_permitted_term"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// This term got a pass through automod
|
||||
AutomodUserAction action(data, roomID);
|
||||
getCreatedByUser(data, action.source);
|
||||
|
||||
try
|
||||
{
|
||||
const auto &args = getArgs(data);
|
||||
action.type = 1;
|
||||
|
||||
if (args.Size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rj::getSafe(args[0], action.message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->signals_.moderation.automodUserMessage.invoke(action);
|
||||
}
|
||||
catch (const std::runtime_error &ex)
|
||||
{
|
||||
log("Error parsing moderation action: {}", ex.what());
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["add_blocked_term"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// A term has been added
|
||||
AutomodUserAction action(data, roomID);
|
||||
getCreatedByUser(data, action.source);
|
||||
|
||||
try
|
||||
{
|
||||
const auto &args = getArgs(data);
|
||||
action.type = 2;
|
||||
|
||||
if (args.Size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rj::getSafe(args[0], action.message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->signals_.moderation.automodUserMessage.invoke(action);
|
||||
}
|
||||
catch (const std::runtime_error &ex)
|
||||
{
|
||||
log("Error parsing moderation action: {}", ex.what());
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["delete_permitted_term"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// This term got deleted
|
||||
AutomodUserAction action(data, roomID);
|
||||
getCreatedByUser(data, action.source);
|
||||
|
||||
try
|
||||
{
|
||||
const auto &args = getArgs(data);
|
||||
action.type = 3;
|
||||
|
||||
if (args.Size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rj::getSafe(args[0], action.message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->signals_.moderation.automodUserMessage.invoke(action);
|
||||
}
|
||||
catch (const std::runtime_error &ex)
|
||||
{
|
||||
log("Error parsing moderation action: {}", ex.what());
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["delete_blocked_term"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// This term got deleted
|
||||
AutomodUserAction action(data, roomID);
|
||||
|
||||
getCreatedByUser(data, action.source);
|
||||
|
||||
try
|
||||
{
|
||||
const auto &args = getArgs(data);
|
||||
action.type = 4;
|
||||
|
||||
if (args.Size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rj::getSafe(args[0], action.message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->signals_.moderation.automodUserMessage.invoke(action);
|
||||
}
|
||||
catch (const std::runtime_error &ex)
|
||||
{
|
||||
log("Error parsing moderation action: {}", ex.what());
|
||||
}
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["modified_automod_properties"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// The automod settings got modified
|
||||
AutomodUserAction action(data, roomID);
|
||||
getCreatedByUser(data, action.source);
|
||||
action.type = 5;
|
||||
this->signals_.moderation.automodUserMessage.invoke(action);
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["denied_automod_message"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// This message got denied by a moderator
|
||||
// qDebug() << QString::fromStdString(rj::stringify(data));
|
||||
};
|
||||
|
||||
this->moderationActionHandlers["approved_automod_message"] =
|
||||
[this](const auto &data, const auto &roomID) {
|
||||
// This message got approved by a moderator
|
||||
// qDebug() << QString::fromStdString(rj::stringify(data));
|
||||
};
|
||||
|
||||
this->websocketClient.set_access_channels(websocketpp::log::alevel::all);
|
||||
this->websocketClient.clear_access_channels(
|
||||
websocketpp::log::alevel::frame_payload);
|
||||
@@ -539,7 +729,7 @@ PubSub::PubSub()
|
||||
|
||||
// Add an initial client
|
||||
this->addClient();
|
||||
}
|
||||
} // namespace chatterino
|
||||
|
||||
void PubSub::addClient()
|
||||
{
|
||||
|
||||
@@ -112,6 +112,9 @@ public:
|
||||
|
||||
Signal<BanAction> userBanned;
|
||||
Signal<UnbanAction> userUnbanned;
|
||||
|
||||
Signal<AutomodAction> automodMessage;
|
||||
Signal<AutomodUserAction> automodUserMessage;
|
||||
} moderation;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -23,6 +23,18 @@ const rapidjson::Value &getArgs(const rapidjson::Value &data)
|
||||
return args;
|
||||
}
|
||||
|
||||
const rapidjson::Value &getMsgID(const rapidjson::Value &data)
|
||||
{
|
||||
if (!data.HasMember("msg_id"))
|
||||
{
|
||||
throw std::runtime_error("Missing member msg_id");
|
||||
}
|
||||
|
||||
const auto &msgID = data["msg_id"];
|
||||
|
||||
return msgID;
|
||||
}
|
||||
|
||||
bool getCreatedByUser(const rapidjson::Value &data, ActionUser &user)
|
||||
{
|
||||
return rj::getSafe(data, "created_by", user.name) &&
|
||||
|
||||
@@ -12,6 +12,7 @@ class TwitchAccount;
|
||||
struct ActionUser;
|
||||
|
||||
const rapidjson::Value &getArgs(const rapidjson::Value &data);
|
||||
const rapidjson::Value &getMsgID(const rapidjson::Value &data);
|
||||
|
||||
bool getCreatedByUser(const rapidjson::Value &data, ActionUser &user);
|
||||
|
||||
|
||||
@@ -413,6 +413,51 @@ AccessGuard<const TwitchAccount::TwitchAccountEmoteData>
|
||||
return this->emotes_.accessConst();
|
||||
}
|
||||
|
||||
// AutoModActions
|
||||
void TwitchAccount::autoModAllow(const QString msgID)
|
||||
{
|
||||
QString url("https://api.twitch.tv/kraken/chat/twitchbot/approve");
|
||||
|
||||
NetworkRequest req(url, NetworkRequestType::Post);
|
||||
req.setRawHeader("Content-Type", "application/json");
|
||||
|
||||
auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8();
|
||||
qDebug() << qba;
|
||||
|
||||
req.setRawHeader("Content-Length", QByteArray::number(qba.size()));
|
||||
req.setPayload(qba);
|
||||
req.setCaller(QThread::currentThread());
|
||||
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
|
||||
|
||||
req.onError([=](int errorCode) {
|
||||
log("[TwitchAccounts::autoModAllow] Error {}", errorCode);
|
||||
return true;
|
||||
});
|
||||
|
||||
req.execute();
|
||||
}
|
||||
|
||||
void TwitchAccount::autoModDeny(const QString msgID)
|
||||
{
|
||||
QString url("https://api.twitch.tv/kraken/chat/twitchbot/deny");
|
||||
|
||||
NetworkRequest req(url, NetworkRequestType::Post);
|
||||
req.setRawHeader("Content-Type", "application/json");
|
||||
auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8();
|
||||
qDebug() << qba;
|
||||
|
||||
req.setRawHeader("Content-Length", QByteArray::number(qba.size()));
|
||||
req.setPayload(qba);
|
||||
req.setCaller(QThread::currentThread());
|
||||
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
|
||||
|
||||
req.onError([=](int errorCode) {
|
||||
log("[TwitchAccounts::autoModDeny] Error {}", errorCode);
|
||||
return true;
|
||||
});
|
||||
req.execute();
|
||||
}
|
||||
|
||||
void TwitchAccount::parseEmotes(const rapidjson::Document &root)
|
||||
{
|
||||
auto emoteData = this->emotes_.access();
|
||||
|
||||
@@ -108,6 +108,10 @@ public:
|
||||
void loadEmotes();
|
||||
AccessGuard<const TwitchAccountEmoteData> accessEmotes() const;
|
||||
|
||||
// Automod actions
|
||||
void autoModAllow(const QString msgID);
|
||||
void autoModDeny(const QString msgID);
|
||||
|
||||
private:
|
||||
void parseEmotes(const rapidjson::Document &document);
|
||||
void loadEmoteSetData(std::shared_ptr<EmoteSet> emoteSet);
|
||||
|
||||
Reference in New Issue
Block a user