Merge pull request #925 from apa420/apa-automod-implementation

Automod implementation
This commit is contained in:
pajlada
2019-01-22 22:45:34 +01:00
committed by GitHub
19 changed files with 524 additions and 80 deletions
+22
View File
@@ -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
+191 -1
View File
@@ -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()
{
+3
View File
@@ -112,6 +112,9 @@ public:
Signal<BanAction> userBanned;
Signal<UnbanAction> userUnbanned;
Signal<AutomodAction> automodMessage;
Signal<AutomodUserAction> automodUserMessage;
} moderation;
struct {
+12
View File
@@ -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) &&
+1
View File
@@ -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);
+45
View File
@@ -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();
+4
View File
@@ -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);