From 0b2480d715dfe6a06a5d769da76ebaedc957ec64 Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 01:02:04 +0100 Subject: [PATCH 1/7] Added a bunch of stuff, we now collect all the pubsub automod messages and also displays a caught message to a mod --- resources/resources_autogenerated.qrc | 152 ++++++++++++------------- resources/twitch/automod.png | Bin 0 -> 305 bytes src/Application.cpp | 18 +++ src/autogenerated/ResourcesAutogen.cpp | 1 + src/autogenerated/ResourcesAutogen.hpp | 4 +- src/messages/Message.hpp | 1 + src/messages/MessageBuilder.cpp | 45 ++++++++ src/messages/MessageBuilder.hpp | 6 +- src/messages/layouts/MessageLayout.cpp | 4 + src/providers/twitch/PubsubActions.hpp | 10 ++ src/providers/twitch/PubsubClient.cpp | 85 ++++++++++++++ src/providers/twitch/PubsubClient.hpp | 2 + 12 files changed, 249 insertions(+), 79 deletions(-) create mode 100644 resources/twitch/automod.png diff --git a/resources/resources_autogenerated.qrc b/resources/resources_autogenerated.qrc index 9ec2b2a0a..fcf0b5dac 100644 --- a/resources/resources_autogenerated.qrc +++ b/resources/resources_autogenerated.qrc @@ -1,77 +1,77 @@ - - chatterino2.icns - contributors.txt - emoji.json - emojidata.txt - error.png - icon.ico - icon.png - pajaDank.png - tlds.txt - avatars/fourtf.png - avatars/pajlada.png - buttons/addSplit.png - buttons/addSplitDark.png - buttons/ban.png - buttons/banRed.png - buttons/emote.svg - buttons/emoteDark.svg - buttons/menuDark.png - buttons/menuLight.png - buttons/mod.png - buttons/modModeDisabled.png - buttons/modModeDisabled2.png - buttons/modModeEnabled.png - buttons/modModeEnabled2.png - buttons/timeout.png - buttons/unban.png - buttons/unmod.png - buttons/update.png - buttons/updateError.png - examples/moving.gif - examples/splitting.gif - licenses/boost_boost.txt - licenses/emoji-data-source.txt - licenses/fmt_bsd2.txt - licenses/libcommuni_BSD3.txt - licenses/openssl.txt - licenses/pajlada_settings.txt - licenses/pajlada_signals.txt - licenses/qt_lgpl-3.0.txt - licenses/rapidjson.txt - licenses/websocketpp.txt - qss/settings.qss - settings/about.svg - settings/aboutlogo.png - settings/accounts.svg - settings/behave.svg - settings/commands.svg - settings/emote.svg - settings/notifications.svg - settings/theme.svg - sounds/ping2.wav - split/down.png - split/left.png - split/move.png - split/right.png - split/up.png - twitch/admin.png - twitch/broadcaster.png - twitch/cheer1.png - twitch/globalmod.png - twitch/moderator.png - twitch/prime.png - twitch/staff.png - twitch/subscriber.png - twitch/turbo.png - twitch/verified.png - settings/ignore.svg - settings/keybinds.svg - settings/moderation.svg - settings/notification2.svg - settings/browser.svg - settings/externaltools.svg - settings/advanced.svg - - + chatterino2.icns + contributors.txt + emoji.json + emojidata.txt + error.png + icon.ico + icon.png + pajaDank.png + tlds.txt + avatars/fourtf.png + avatars/pajlada.png + buttons/addSplit.png + buttons/addSplitDark.png + buttons/ban.png + buttons/banRed.png + buttons/emote.svg + buttons/emoteDark.svg + buttons/menuDark.png + buttons/menuLight.png + buttons/mod.png + buttons/modModeDisabled.png + buttons/modModeDisabled2.png + buttons/modModeEnabled.png + buttons/modModeEnabled2.png + buttons/timeout.png + buttons/unban.png + buttons/unmod.png + buttons/update.png + buttons/updateError.png + examples/moving.gif + examples/splitting.gif + licenses/boost_boost.txt + licenses/emoji-data-source.txt + licenses/fmt_bsd2.txt + licenses/libcommuni_BSD3.txt + licenses/openssl.txt + licenses/pajlada_settings.txt + licenses/pajlada_signals.txt + licenses/qt_lgpl-3.0.txt + licenses/rapidjson.txt + licenses/websocketpp.txt + qss/settings.qss + settings/about.svg + settings/aboutlogo.png + settings/accounts.svg + settings/advanced.svg + settings/behave.svg + settings/browser.svg + settings/commands.svg + settings/emote.svg + settings/externaltools.svg + settings/ignore.svg + settings/keybinds.svg + settings/moderation.svg + settings/notification2.svg + settings/notifications.svg + settings/theme.svg + sounds/ping2.wav + split/down.png + split/left.png + split/move.png + split/right.png + split/up.png + twitch/admin.png + twitch/automod.png + twitch/broadcaster.png + twitch/cheer1.png + twitch/globalmod.png + twitch/moderator.png + twitch/prime.png + twitch/staff.png + twitch/subscriber.png + twitch/turbo.png + twitch/verified.png + + \ No newline at end of file diff --git a/resources/twitch/automod.png b/resources/twitch/automod.png new file mode 100644 index 0000000000000000000000000000000000000000..01174644f8f353dacd7896898bd289a25ad32bbe GIT binary patch literal 305 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|#^NA%Cx&(BWL^R}uRUEHLo5W7 zO(Ktfo!`jS(8-n7&@0izmdPPu)L@`^pvjxjoLk>{S(vT!iXf|qldr0cC6~o#r~LT! z+&E0P=SI?5PpyW9F6-MJrvwYRUVi=lykwQ$RD(Cw+ZbJCjvUOokoJ8xk5G(}M3*Cz z{yy8p4|iAgDYlzli>s~gS}35_;LW$%F+EPc;pO24g(nkDGfppF%2WUE??D3=6}Cx- z*)~Xh`SCioZEE@Q#1-tFjZZc(u3>8w@!J=5y5Pf2u^n;((kgA-3B9H>lGNDL+G6I4 z8I*sTD%Do+(82w{lw-PD&LfMxZN7$f8xN)nFtqmhb1Q literal 0 HcmV?d00001 diff --git a/src/Application.cpp b/src/Application.cpp index 107f0b05f..23d983fd5 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -234,6 +234,24 @@ void Application::initPubsub() postToThread([chan, msg] { chan->addMessage(msg); }); }); + this->twitch.pubsub->signals_.moderation.automodMessage.connect( + [&](const auto &action) { + auto chan = + this->twitch.server->getChannelOrEmptyByID(action.roomID); + + if (chan->isEmpty()) + { + return; + } + + auto p = makeAutomodMessage(action); + + postToThread([chan, p] { + chan->addMessage(p.first); + chan->addMessage(p.second); + }); + }); + this->twitch.pubsub->start(); auto RequestModerationActions = [=]() { diff --git a/src/autogenerated/ResourcesAutogen.cpp b/src/autogenerated/ResourcesAutogen.cpp index ee25daf1f..34cf039ef 100644 --- a/src/autogenerated/ResourcesAutogen.cpp +++ b/src/autogenerated/ResourcesAutogen.cpp @@ -32,6 +32,7 @@ Resources2::Resources2() this->split.right = QPixmap(":/split/right.png"); this->split.up = QPixmap(":/split/up.png"); this->twitch.admin = QPixmap(":/twitch/admin.png"); + this->twitch.automod = QPixmap(":/twitch/automod.png"); this->twitch.broadcaster = QPixmap(":/twitch/broadcaster.png"); this->twitch.cheer1 = QPixmap(":/twitch/cheer1.png"); this->twitch.globalmod = QPixmap(":/twitch/globalmod.png"); diff --git a/src/autogenerated/ResourcesAutogen.hpp b/src/autogenerated/ResourcesAutogen.hpp index 075c801eb..fbbb2fbf3 100644 --- a/src/autogenerated/ResourcesAutogen.hpp +++ b/src/autogenerated/ResourcesAutogen.hpp @@ -3,8 +3,7 @@ namespace chatterino { -class Resources2 : public Singleton -{ +class Resources2 : public Singleton { public: Resources2(); @@ -45,6 +44,7 @@ public: } split; struct { QPixmap admin; + QPixmap automod; QPixmap broadcaster; QPixmap cheer1; QPixmap globalmod; diff --git a/src/messages/Message.hpp b/src/messages/Message.hpp index cc716dd2f..572615a04 100644 --- a/src/messages/Message.hpp +++ b/src/messages/Message.hpp @@ -28,6 +28,7 @@ enum class MessageFlag : uint16_t { PubSub = (1 << 11), Subscription = (1 << 12), Notification = (1 << 13), + AutoMod = (1 << 14), }; using MessageFlags = FlagsEnum; diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 7ea91fcfa..f2e8bae86 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -1,6 +1,8 @@ #include "MessageBuilder.hpp" +//#include "Application.hpp" #include "common/LinkParser.hpp" +//#include "messages/Image.hpp" #include "messages/Message.hpp" #include "messages/MessageElement.hpp" #include "providers/twitch/PubsubActions.hpp" @@ -11,6 +13,7 @@ #include "util/IrcHelpers.hpp" #include +//#include namespace chatterino { @@ -19,6 +22,48 @@ MessagePtr makeSystemMessage(const QString &text) return MessageBuilder(systemMessage, text).release(); } +std::pair makeAutomodMessage( + const AutomodAction &action) +{ + auto builder = MessageBuilder(); + + builder.emplace(); + builder.message().flags.set(MessageFlag::PubSub); + + // Crashes the program atm + // builder.emplace( + // Image::fromPixmap(getApp()->resources->twitch.automod), + // MessageElementFlag::BadgeChannelAuthority) + // ->setTooltip("AutoMod"); + builder.emplace( + "AutoMod:", MessageElementFlag::NonBoldUsername, + MessageColor(QColor("green"))); + builder.emplace( + ("Held a message for reason: " + action.reason + + ". Allow will post it in chat."), + MessageElementFlag::Text, MessageColor::Text); + builder.message().flags.set(MessageFlag::AutoMod); + + auto message1 = builder.release(); + + builder = MessageBuilder(); + builder.emplace(); + builder.message().flags.set(MessageFlag::PubSub); + + builder + .emplace(action.target.name + ":", + MessageElementFlag::NonBoldUsername, + MessageColor(QColor("red"))) + ->setLink({Link::UserInfo, action.target.name}); + builder.emplace(action.message, MessageElementFlag::Text, + MessageColor::Text); + builder.message().flags.set(MessageFlag::AutoMod); + + auto message2 = builder.release(); + + return std::make_pair(message1, message2); +} + MessageBuilder::MessageBuilder() : message_(std::make_shared()) { diff --git a/src/messages/MessageBuilder.hpp b/src/messages/MessageBuilder.hpp index b09b82ed2..a0171cb2b 100644 --- a/src/messages/MessageBuilder.hpp +++ b/src/messages/MessageBuilder.hpp @@ -4,10 +4,12 @@ #include #include +#include namespace chatterino { struct BanAction; struct UnbanAction; +struct AutomodAction; struct Message; using MessagePtr = std::shared_ptr; @@ -19,6 +21,8 @@ const SystemMessageTag systemMessage{}; const TimeoutMessageTag timeoutMessage{}; MessagePtr makeSystemMessage(const QString &text); +std::pair makeAutomodMessage( + const AutomodAction &action); struct MessageParseArgs { bool disablePingSounds = false; @@ -29,6 +33,7 @@ struct MessageParseArgs { }; class MessageBuilder + { public: MessageBuilder(); @@ -63,5 +68,4 @@ public: private: std::shared_ptr message_; }; - } // namespace chatterino diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index cf1be4a72..7137c9666 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -268,6 +268,10 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/, { backgroundColor = app->themes->messages.backgrounds.alternate; } + else if (this->message_->flags.has(MessageFlag::AutoMod)) + { + backgroundColor = app->themes->messages.backgrounds.automod; + } painter.fillRect(buffer->rect(), backgroundColor); diff --git a/src/providers/twitch/PubsubActions.hpp b/src/providers/twitch/PubsubActions.hpp index 8b2bfecfb..bb116d937 100644 --- a/src/providers/twitch/PubsubActions.hpp +++ b/src/providers/twitch/PubsubActions.hpp @@ -105,4 +105,14 @@ struct ModerationStateAction : PubSubAction { bool modded; }; +struct AutomodAction : PubSubAction { + using PubSubAction::PubSubAction; + + ActionUser target; + + QString message; + + QString reason; +}; + } // namespace chatterino diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index 6bc866700..50e7b0396 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -520,6 +520,91 @@ 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); + + qDebug() << "test1111"; + try + { + const auto &args = getArgs(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; + } + } + + this->signals_.moderation.automodMessage.invoke(action); + } + catch (const std::runtime_error &ex) + { + log("Error parsing moderation action: {}", ex.what()); + } + }; + + this->moderationActionHandlers["denied_automod_message"] = + [this](const auto &data, const auto &roomID) { + // This message got denied by a moderator + qDebug() << "test2222"; + }; + + this->moderationActionHandlers["add_blocked_term"] = + [this](const auto &data, const auto &roomID) { + // A term has been added + qDebug() << "test3333"; + }; + + this->moderationActionHandlers["approved_automod_message"] = + [this](const auto &data, const auto &roomID) { + // This message got approved by a moderator + qDebug() << "test5555"; + }; + + this->moderationActionHandlers["add_permitted_term"] = + [this](const auto &data, const auto &roomID) { + // This term got a pass through automod + qDebug() << "test6666"; + }; + this->moderationActionHandlers["modified_automod_properties"] = + [this](const auto &data, const auto &roomID) { + // The automod settings got modified + qDebug() << "test4444"; + }; + this->moderationActionHandlers["delete_blocked_term"] = + [this](const auto &data, const auto &roomID) { + // This term got deleted + qDebug() << "test7777"; + }; + this->moderationActionHandlers["delete_permitted_term"] = + [this](const auto &data, const auto &roomID) { + // This term got deleted + qDebug() << "test8888"; + }; this->websocketClient.set_access_channels(websocketpp::log::alevel::all); this->websocketClient.clear_access_channels( websocketpp::log::alevel::frame_payload); diff --git a/src/providers/twitch/PubsubClient.hpp b/src/providers/twitch/PubsubClient.hpp index f3cc10f15..403abcaaa 100644 --- a/src/providers/twitch/PubsubClient.hpp +++ b/src/providers/twitch/PubsubClient.hpp @@ -112,6 +112,8 @@ public: Signal userBanned; Signal userUnbanned; + + Signal automodMessage; } moderation; struct { From 7067b0503d15fab942445d8b292d6d9b346b9c8b Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 14:45:59 +0100 Subject: [PATCH 2/7] Added more functionality and clickable deny and accept buttons that don't do anything, this also fixes the issue with the background not working properly --- src/Application.cpp | 5 ++--- src/messages/Link.hpp | 2 ++ src/messages/MessageBuilder.cpp | 30 ++++++++++++++++++-------- src/messages/layouts/MessageLayout.cpp | 2 +- src/providers/twitch/PubsubActions.hpp | 2 ++ src/providers/twitch/PubsubClient.cpp | 9 +++++++- src/providers/twitch/PubsubHelpers.cpp | 12 +++++++++++ src/providers/twitch/PubsubHelpers.hpp | 1 + src/providers/twitch/TwitchAccount.cpp | 2 ++ src/providers/twitch/TwitchAccount.hpp | 6 ++++++ src/widgets/helper/ChannelView.cpp | 7 ++++++ 11 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 23d983fd5..6c7efabf9 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -244,9 +244,8 @@ void Application::initPubsub() return; } - auto p = makeAutomodMessage(action); - - postToThread([chan, p] { + postToThread([chan, action] { + auto p = makeAutomodMessage(action); chan->addMessage(p.first); chan->addMessage(p.second); }); diff --git a/src/messages/Link.hpp b/src/messages/Link.hpp index 38000982f..52a52444b 100644 --- a/src/messages/Link.hpp +++ b/src/messages/Link.hpp @@ -17,6 +17,8 @@ public: InsertText, ShowMessage, UserAction, + AutoModAllow, + AutoModDeny, }; Link(); diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index f2e8bae86..9df5fc279 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -1,8 +1,8 @@ #include "MessageBuilder.hpp" -//#include "Application.hpp" +#include "Application.hpp" #include "common/LinkParser.hpp" -//#include "messages/Image.hpp" +#include "messages/Image.hpp" #include "messages/Message.hpp" #include "messages/MessageElement.hpp" #include "providers/twitch/PubsubActions.hpp" @@ -13,7 +13,7 @@ #include "util/IrcHelpers.hpp" #include -//#include +#include namespace chatterino { @@ -30,18 +30,30 @@ std::pair makeAutomodMessage( builder.emplace(); builder.message().flags.set(MessageFlag::PubSub); - // Crashes the program atm - // builder.emplace( - // Image::fromPixmap(getApp()->resources->twitch.automod), - // MessageElementFlag::BadgeChannelAuthority) - // ->setTooltip("AutoMod"); + builder + .emplace( + Image::fromPixmap(getApp()->resources->twitch.automod), + MessageElementFlag::BadgeChannelAuthority) + ->setTooltip("AutoMod"); builder.emplace( "AutoMod:", MessageElementFlag::NonBoldUsername, - MessageColor(QColor("green"))); + MessageColor(QColor("blue"))); builder.emplace( ("Held a message for reason: " + action.reason + ". Allow will post it in chat."), MessageElementFlag::Text, MessageColor::Text); + builder + .emplace(" Allow", MessageElementFlag::Text, + MessageColor(QColor("green")), + FontStyle::ChatMediumBold) + ->setLink({Link::AutoModAllow, action.msgID}); + builder + .emplace(" Deny", MessageElementFlag::Text, + MessageColor(QColor("red")), + FontStyle::ChatMediumBold) + ->setLink({Link::AutoModDeny, action.msgID}); + builder.emplace(action.msgID, MessageElementFlag::Text, + MessageColor::Text); builder.message().flags.set(MessageFlag::AutoMod); auto message1 = builder.release(); diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index 7137c9666..06af7c790 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -270,7 +270,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/, } else if (this->message_->flags.has(MessageFlag::AutoMod)) { - backgroundColor = app->themes->messages.backgrounds.automod; + backgroundColor = QColor("#404040"); } painter.fillRect(buffer->rect(), backgroundColor); diff --git a/src/providers/twitch/PubsubActions.hpp b/src/providers/twitch/PubsubActions.hpp index bb116d937..03013ff4c 100644 --- a/src/providers/twitch/PubsubActions.hpp +++ b/src/providers/twitch/PubsubActions.hpp @@ -113,6 +113,8 @@ struct AutomodAction : PubSubAction { QString message; QString reason; + + QString msgID; }; } // namespace chatterino diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index 50e7b0396..c60665882 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -532,6 +532,8 @@ PubSub::PubSub() try { const auto &args = getArgs(data); + const auto &msgID = getMsgID(data); + // qDebug() << QString::fromStdString(rj::stringify(data)); if (args.Size() < 1) { @@ -559,6 +561,11 @@ PubSub::PubSub() } } + if (!rj::getSafe(msgID, action.msgID)) + { + return; + } + this->signals_.moderation.automodMessage.invoke(action); } catch (const std::runtime_error &ex) @@ -624,7 +631,7 @@ PubSub::PubSub() // Add an initial client this->addClient(); -} +} // namespace chatterino void PubSub::addClient() { diff --git a/src/providers/twitch/PubsubHelpers.cpp b/src/providers/twitch/PubsubHelpers.cpp index cda4b8788..b30c47c0f 100644 --- a/src/providers/twitch/PubsubHelpers.cpp +++ b/src/providers/twitch/PubsubHelpers.cpp @@ -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) && diff --git a/src/providers/twitch/PubsubHelpers.hpp b/src/providers/twitch/PubsubHelpers.hpp index 7ea540ad8..ad8c52130 100644 --- a/src/providers/twitch/PubsubHelpers.hpp +++ b/src/providers/twitch/PubsubHelpers.hpp @@ -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); diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index f6337d0c6..2b2e62498 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -413,6 +413,8 @@ AccessGuard return this->emotes_.accessConst(); } +// AutoModActions + void TwitchAccount::parseEmotes(const rapidjson::Document &root) { auto emoteData = this->emotes_.access(); diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index 1ea718b73..bc53e0b24 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -108,6 +108,12 @@ public: void loadEmotes(); AccessGuard accessEmotes() const; + // Automod actions + void autoModAllow(const QString msgID, + std::function successCallback); + void autoModDeny(const QString msgID, + std::function successCallback); + private: void parseEmotes(const rapidjson::Document &document); void loadEmoteSetData(std::shared_ptr emoteSet); diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 91bfed93b..135c9cc44 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1671,6 +1671,13 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, } break; + case Link::AutoModAllow: + { + } + case Link::AutoModDeny: + { + } + default:; } } From 7aa798f924f9d719c64cd93db291da9f5332f5f9 Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 14:47:04 +0100 Subject: [PATCH 3/7] Forgot to add some small stuff --- src/providers/twitch/TwitchAccount.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 2b2e62498..4bfae4354 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -414,6 +414,15 @@ AccessGuard } // AutoModActions +void TwitchAccount::autoModAllow(const QString msgID, + std::function successCallback) +{ +} + +void TwitchAccount::autoModDeny(const QString msgID, + std::function successCallback) +{ +} void TwitchAccount::parseEmotes(const rapidjson::Document &root) { From cc5528ec18125f0d4a753cd9a19cb18c5fde8cb9 Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 16:07:31 +0100 Subject: [PATCH 4/7] smol commit --- src/providers/twitch/TwitchAccount.cpp | 41 +++++++++++++++++++++++--- src/providers/twitch/TwitchAccount.hpp | 6 ++-- src/widgets/helper/ChannelView.cpp | 3 ++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 4bfae4354..c9a691975 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -414,14 +414,47 @@ AccessGuard } // AutoModActions -void TwitchAccount::autoModAllow(const QString msgID, - std::function successCallback) +void TwitchAccount::autoModAllow(const QString msgID) { + QString url("https://api.twitch.tv/kraken/chat/twitchbot/approve"); + + NetworkRequest req(url); + auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); + qDebug() << qba; + req.setPayload(qba); + req.setCaller(QThread::currentThread()); + req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + + req.onError([=](int errorCode) { + qDebug() << "you just got an error 4HEad" << errorCode; + return true; + }); + + req.onReplyCreated([=](QNetworkReply *reply) -> void { + // + // + return; + }); + + req.execute(); } -void TwitchAccount::autoModDeny(const QString msgID, - std::function successCallback) +void TwitchAccount::autoModDeny(const QString msgID) { + QString url("https://api.twitch.tv/kraken/chat/twitchbot/deny"); + + NetworkRequest req(url); + auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); + qDebug() << qba; + req.setPayload(qba); + req.setCaller(QThread::currentThread()); + req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken()); + + req.onError([=](int errorCode) { + qDebug() << "you just got an error 4HEad" << errorCode; + return true; + }); + req.execute(); } void TwitchAccount::parseEmotes(const rapidjson::Document &root) diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index bc53e0b24..e5db1749d 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -109,10 +109,8 @@ public: AccessGuard accessEmotes() const; // Automod actions - void autoModAllow(const QString msgID, - std::function successCallback); - void autoModDeny(const QString msgID, - std::function successCallback); + void autoModAllow(const QString msgID); + void autoModDeny(const QString msgID); private: void parseEmotes(const rapidjson::Document &document); diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 135c9cc44..1f4aa2d88 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -2,6 +2,7 @@ #include "Application.hpp" #include "common/Common.hpp" +#include "controllers/accounts/AccountController.hpp" #include "debug/Benchmark.hpp" #include "debug/Log.hpp" #include "messages/Emote.hpp" @@ -1673,9 +1674,11 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, case Link::AutoModAllow: { + getApp()->accounts->twitch.getCurrent()->autoModAllow(link.value); } case Link::AutoModDeny: { + getApp()->accounts->twitch.getCurrent()->autoModDeny(link.value); } default:; From e9bd9ddb8eb487d85201162696e0347248bca822 Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 16:28:25 +0100 Subject: [PATCH 5/7] smoler commit --- src/common/NetworkRequest.cpp | 10 ++++++++++ src/providers/twitch/TwitchAccount.cpp | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index 524693c17..b4192e8e6 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -147,6 +147,12 @@ void NetworkRequest::execute() } break; + case NetworkRequestType::Post: + { + this->doRequest(); + } + break; + default: { log("[Execute] Unhandled request type"); @@ -217,6 +223,10 @@ void NetworkRequest::doRequest() return NetworkManager::accessManager.deleteResource( data->request_); + case NetworkRequestType::Post: + return NetworkManager::accessManager.post(data->request_, + data->payload_); + default: return nullptr; } diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index c9a691975..afe02784b 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -418,7 +418,12 @@ void TwitchAccount::autoModAllow(const QString msgID) { QString url("https://api.twitch.tv/kraken/chat/twitchbot/approve"); - NetworkRequest req(url); + NetworkRequest req(url, NetworkRequestType::Post); + req.setRawHeader("Content-type", "application/json"); + /*req.setRawHeader curl - i - H 'Client-ID: abcd' - + H 'Accept: application/vnd.twitchtv.v5+json' - + H 'Authorization: OAuth efgh' - + H "Content-type: application/json" --data '{"msg_id":"msgid"}';*/ auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); qDebug() << qba; req.setPayload(qba); @@ -443,7 +448,8 @@ void TwitchAccount::autoModDeny(const QString msgID) { QString url("https://api.twitch.tv/kraken/chat/twitchbot/deny"); - NetworkRequest req(url); + NetworkRequest req(url, NetworkRequestType::Post); + req.setRawHeader("Content-type", "application/json"); auto qba = (QString("{\"msg_id\":\"") + msgID + "\"}").toUtf8(); qDebug() << qba; req.setPayload(qba); From cd5c373e017a7526cb319f01abb8e934976ba083 Mon Sep 17 00:00:00 2001 From: apa420 Date: Sun, 20 Jan 2019 17:03:45 +0100 Subject: [PATCH 6/7] smol commit, idk if I will continue this --- src/providers/twitch/PubsubActions.hpp | 8 ++++++++ src/providers/twitch/PubsubClient.cpp | 10 ++++++++++ src/providers/twitch/PubsubClient.hpp | 1 + src/providers/twitch/TwitchAccount.cpp | 23 +++++++++-------------- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/providers/twitch/PubsubActions.hpp b/src/providers/twitch/PubsubActions.hpp index 03013ff4c..5f1dcce48 100644 --- a/src/providers/twitch/PubsubActions.hpp +++ b/src/providers/twitch/PubsubActions.hpp @@ -117,4 +117,12 @@ struct AutomodAction : PubSubAction { QString msgID; }; +struct AutomodUserAction : PubSubAction { + using PubSubAction::PubSubAction; + + ActionUser target; + + QString message; +}; + } // namespace chatterino diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index c60665882..e2ce1b9e2 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -577,40 +577,50 @@ PubSub::PubSub() this->moderationActionHandlers["denied_automod_message"] = [this](const auto &data, const auto &roomID) { // This message got denied by a moderator + AutomodUserAction action(data, roomID); + + getCreatedByUser(data, action.source); qDebug() << "test2222"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->moderationActionHandlers["add_blocked_term"] = [this](const auto &data, const auto &roomID) { // A term has been added qDebug() << "test3333"; + 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() << "test5555"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->moderationActionHandlers["add_permitted_term"] = [this](const auto &data, const auto &roomID) { // This term got a pass through automod qDebug() << "test6666"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->moderationActionHandlers["modified_automod_properties"] = [this](const auto &data, const auto &roomID) { // The automod settings got modified qDebug() << "test4444"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->moderationActionHandlers["delete_blocked_term"] = [this](const auto &data, const auto &roomID) { // This term got deleted qDebug() << "test7777"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->moderationActionHandlers["delete_permitted_term"] = [this](const auto &data, const auto &roomID) { // This term got deleted qDebug() << "test8888"; + qDebug() << QString::fromStdString(rj::stringify(data)); }; this->websocketClient.set_access_channels(websocketpp::log::alevel::all); this->websocketClient.clear_access_channels( diff --git a/src/providers/twitch/PubsubClient.hpp b/src/providers/twitch/PubsubClient.hpp index 403abcaaa..9e2def087 100644 --- a/src/providers/twitch/PubsubClient.hpp +++ b/src/providers/twitch/PubsubClient.hpp @@ -114,6 +114,7 @@ public: Signal userUnbanned; Signal automodMessage; + Signal automodUserMessage; } moderation; struct { diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index afe02784b..1d798f8ce 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -419,28 +419,21 @@ 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"); - /*req.setRawHeader curl - i - H 'Client-ID: abcd' - - H 'Accept: application/vnd.twitchtv.v5+json' - - H 'Authorization: OAuth efgh' - - H "Content-type: application/json" --data '{"msg_id":"msgid"}';*/ + 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) { - qDebug() << "you just got an error 4HEad" << errorCode; + log("[TwitchAccounts::autoModAllow] Error {}", errorCode); return true; }); - req.onReplyCreated([=](QNetworkReply *reply) -> void { - // - // - return; - }); - req.execute(); } @@ -449,15 +442,17 @@ 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"); + 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) { - qDebug() << "you just got an error 4HEad" << errorCode; + log("[TwitchAccounts::autoModDeny] Error {}", errorCode); return true; }); req.execute(); From 143422560349f3c4c2a3b0ecd9213877a6efd67d Mon Sep 17 00:00:00 2001 From: apa420 Date: Mon, 21 Jan 2019 18:33:57 +0100 Subject: [PATCH 7/7] Implemented AutoMod and write pubsub automod messages TODO: implement that the AutoMod message gets deleted if dealt with \nFixes #887 --- src/Application.cpp | 15 +++ src/messages/MessageBuilder.cpp | 50 +++++++- src/messages/MessageBuilder.hpp | 2 + src/providers/twitch/PubsubActions.hpp | 2 + src/providers/twitch/PubsubClient.cpp | 158 +++++++++++++++++++------ src/widgets/helper/ChannelView.cpp | 2 + 6 files changed, 190 insertions(+), 39 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 6c7efabf9..2870c6ed6 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -251,6 +251,21 @@ void Application::initPubsub() }); }); + this->twitch.pubsub->signals_.moderation.automodUserMessage.connect( + [&](const auto &action) { + auto chan = + this->twitch.server->getChannelOrEmptyByID(action.roomID); + + if (chan->isEmpty()) + { + return; + } + + auto msg = MessageBuilder(action).release(); + + postToThread([chan, msg] { chan->addMessage(msg); }); + }); + this->twitch.pubsub->start(); auto RequestModerationActions = [=]() { diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 9df5fc279..9a4b1a00d 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -40,10 +40,10 @@ std::pair makeAutomodMessage( MessageColor(QColor("blue"))); builder.emplace( ("Held a message for reason: " + action.reason + - ". Allow will post it in chat."), + ". Allow will post it in chat. "), MessageElementFlag::Text, MessageColor::Text); builder - .emplace(" Allow", MessageElementFlag::Text, + .emplace("Allow", MessageElementFlag::Text, MessageColor(QColor("green")), FontStyle::ChatMediumBold) ->setLink({Link::AutoModAllow, action.msgID}); @@ -52,8 +52,9 @@ std::pair makeAutomodMessage( MessageColor(QColor("red")), FontStyle::ChatMediumBold) ->setLink({Link::AutoModDeny, action.msgID}); - builder.emplace(action.msgID, MessageElementFlag::Text, - MessageColor::Text); + // builder.emplace(action.msgID, + // MessageElementFlag::Text, + // MessageColor::Text); builder.message().flags.set(MessageFlag::AutoMod); auto message1 = builder.release(); @@ -236,6 +237,47 @@ MessageBuilder::MessageBuilder(const UnbanAction &action) this->message().searchText = text; } +MessageBuilder::MessageBuilder(const AutomodUserAction &action) + : MessageBuilder() +{ + this->emplace(); + this->message().flags.set(MessageFlag::System); + + QString text; + if (action.type == 1) + { + text = QString("%1 added %2 as a permitted term on AutoMod.") + .arg(action.source.name) + .arg(action.message); + } + else if (action.type == 2) + { + text = QString("%1 added %2 as a blocked term on AutoMod.") + .arg(action.source.name) + .arg(action.message); + } + else if (action.type == 3) + { + text = QString("%1 removed %2 as a permitted term term on AutoMod.") + .arg(action.source.name) + .arg(action.message); + } + else if (action.type == 4) + { + text = QString("%1 removed %2 as a blocked term on AutoMod.") + .arg(action.source.name) + .arg(action.message); + } + else if (action.type == 5) + { + text = QString("%1 modified the AutoMod properties.") + .arg(action.source.name); + } + + this->emplace(text, MessageElementFlag::Text, + MessageColor::System); +} + Message *MessageBuilder::operator->() { return this->message_.get(); diff --git a/src/messages/MessageBuilder.hpp b/src/messages/MessageBuilder.hpp index a0171cb2b..8fe7915e2 100644 --- a/src/messages/MessageBuilder.hpp +++ b/src/messages/MessageBuilder.hpp @@ -10,6 +10,7 @@ namespace chatterino { struct BanAction; struct UnbanAction; struct AutomodAction; +struct AutomodUserAction; struct Message; using MessagePtr = std::shared_ptr; @@ -44,6 +45,7 @@ public: bool multipleTimes); MessageBuilder(const BanAction &action, uint32_t count = 1); MessageBuilder(const UnbanAction &action); + MessageBuilder(const AutomodUserAction &action); Message *operator->(); Message &message(); diff --git a/src/providers/twitch/PubsubActions.hpp b/src/providers/twitch/PubsubActions.hpp index 5f1dcce48..6377b6d4e 100644 --- a/src/providers/twitch/PubsubActions.hpp +++ b/src/providers/twitch/PubsubActions.hpp @@ -123,6 +123,8 @@ struct AutomodUserAction : PubSubAction { ActionUser target; QString message; + + qint8 type; }; } // namespace chatterino diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index e2ce1b9e2..f5fb54255 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -528,12 +528,10 @@ PubSub::PubSub() getCreatedByUser(data, action.source); getTargetUser(data, action.target); - qDebug() << "test1111"; try { const auto &args = getArgs(data); const auto &msgID = getMsgID(data); - // qDebug() << QString::fromStdString(rj::stringify(data)); if (args.Size() < 1) { @@ -574,54 +572,144 @@ PubSub::PubSub() } }; - this->moderationActionHandlers["denied_automod_message"] = + this->moderationActionHandlers["add_permitted_term"] = [this](const auto &data, const auto &roomID) { - // This message got denied by a moderator + // This term got a pass through automod AutomodUserAction action(data, roomID); - getCreatedByUser(data, action.source); - qDebug() << "test2222"; - qDebug() << QString::fromStdString(rj::stringify(data)); + + 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 - qDebug() << "test3333"; - qDebug() << QString::fromStdString(rj::stringify(data)); + 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() << "test5555"; - qDebug() << QString::fromStdString(rj::stringify(data)); + // qDebug() << QString::fromStdString(rj::stringify(data)); }; - this->moderationActionHandlers["add_permitted_term"] = - [this](const auto &data, const auto &roomID) { - // This term got a pass through automod - qDebug() << "test6666"; - qDebug() << QString::fromStdString(rj::stringify(data)); - }; - this->moderationActionHandlers["modified_automod_properties"] = - [this](const auto &data, const auto &roomID) { - // The automod settings got modified - qDebug() << "test4444"; - qDebug() << QString::fromStdString(rj::stringify(data)); - }; - this->moderationActionHandlers["delete_blocked_term"] = - [this](const auto &data, const auto &roomID) { - // This term got deleted - qDebug() << "test7777"; - qDebug() << QString::fromStdString(rj::stringify(data)); - }; - this->moderationActionHandlers["delete_permitted_term"] = - [this](const auto &data, const auto &roomID) { - // This term got deleted - qDebug() << "test8888"; - 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); diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 1f4aa2d88..682a976d7 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1676,6 +1676,8 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, { getApp()->accounts->twitch.getCurrent()->autoModAllow(link.value); } + break; + case Link::AutoModDeny: { getApp()->accounts->twitch.getCurrent()->autoModDeny(link.value);