mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
feat: add setting to hide blocked term automod messages (#5690)
This commit is contained in:
parent
d92b24b8a1
commit
46c1f18ae7
13 changed files with 88 additions and 35 deletions
|
@ -36,6 +36,7 @@
|
||||||
- Minor: Added `--login <username>` CLI argument to specify which account to start logged in as. (#5626)
|
- Minor: Added `--login <username>` CLI argument to specify which account to start logged in as. (#5626)
|
||||||
- Minor: When blocking a channel, Chatterino will now warn you about that action. (#5615)
|
- Minor: When blocking a channel, Chatterino will now warn you about that action. (#5615)
|
||||||
- Minor: Indicate when subscriptions and resubscriptions are for multiple months. (#5642)
|
- Minor: Indicate when subscriptions and resubscriptions are for multiple months. (#5642)
|
||||||
|
- Minor: Added a setting to control whether or not to show "Blocked Term" automod messages. (#5690)
|
||||||
- Minor: Proxy URL information is now included in the `/debug-env` command. (#5648)
|
- Minor: Proxy URL information is now included in the `/debug-env` command. (#5648)
|
||||||
- Minor: Make raid entry message usernames clickable. (#5651)
|
- Minor: Make raid entry message usernames clickable. (#5651)
|
||||||
- Minor: Tabs unhighlight when their content is read in other tabs. (#5649)
|
- Minor: Tabs unhighlight when their content is read in other tabs. (#5649)
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting);
|
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting);
|
||||||
|
@ -148,6 +152,9 @@ struct IsChatterinoSettingT : std::false_type {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsChatterinoSettingT<ChatterinoSetting<T>> : std::true_type {
|
struct IsChatterinoSettingT<ChatterinoSetting<T>> : std::true_type {
|
||||||
};
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct IsChatterinoSettingT<EnumStringSetting<T>> : std::true_type {
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept IsChatterinoSetting = IsChatterinoSettingT<T>::value;
|
concept IsChatterinoSetting = IsChatterinoSettingT<T>::value;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "providers/twitch/api/Helix.hpp"
|
#include "providers/twitch/api/Helix.hpp"
|
||||||
#include "providers/twitch/ChannelPointReward.hpp"
|
#include "providers/twitch/ChannelPointReward.hpp"
|
||||||
#include "providers/twitch/PubSubActions.hpp"
|
#include "providers/twitch/PubSubActions.hpp"
|
||||||
|
#include "providers/twitch/pubsubmessages/AutoMod.hpp"
|
||||||
#include "providers/twitch/TwitchAccount.hpp"
|
#include "providers/twitch/TwitchAccount.hpp"
|
||||||
#include "providers/twitch/TwitchBadge.hpp"
|
#include "providers/twitch/TwitchBadge.hpp"
|
||||||
#include "providers/twitch/TwitchBadges.hpp"
|
#include "providers/twitch/TwitchBadges.hpp"
|
||||||
|
@ -1637,6 +1638,12 @@ std::pair<MessagePtr, MessagePtr> MessageBuilder::makeAutomodMessage(
|
||||||
{
|
{
|
||||||
MessageBuilder builder, builder2;
|
MessageBuilder builder, builder2;
|
||||||
|
|
||||||
|
if (action.reasonCode == PubSubAutoModQueueMessage::Reason::BlockedTerm)
|
||||||
|
{
|
||||||
|
builder.message().flags.set(MessageFlag::AutoModBlockedTerm);
|
||||||
|
builder2.message().flags.set(MessageFlag::AutoModBlockedTerm);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Builder for AutoMod message with explanation
|
// Builder for AutoMod message with explanation
|
||||||
builder.message().id = "automod_" + action.msgID;
|
builder.message().id = "automod_" + action.msgID;
|
||||||
|
|
|
@ -52,6 +52,8 @@ enum class MessageFlag : std::int64_t {
|
||||||
Action = (1LL << 36),
|
Action = (1LL << 36),
|
||||||
/// The message is sent in a different source channel as part of a Shared Chat session
|
/// The message is sent in a different source channel as part of a Shared Chat session
|
||||||
SharedMessage = (1LL << 37),
|
SharedMessage = (1LL << 37),
|
||||||
|
/// AutoMod message that showed up due to containing a blocked term in the channel
|
||||||
|
AutoModBlockedTerm = (1LL << 38),
|
||||||
};
|
};
|
||||||
using MessageFlags = FlagsEnum<MessageFlag>;
|
using MessageFlags = FlagsEnum<MessageFlag>;
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,9 @@ void MessageLayout::actuallyLayout(const MessageLayoutContext &ctx)
|
||||||
|
|
||||||
bool hideModerated = getSettings()->hideModerated;
|
bool hideModerated = getSettings()->hideModerated;
|
||||||
bool hideModerationActions = getSettings()->hideModerationActions;
|
bool hideModerationActions = getSettings()->hideModerationActions;
|
||||||
|
bool hideBlockedTermAutomodMessages =
|
||||||
|
getSettings()->showBlockedTermAutomodMessages.getEnum() ==
|
||||||
|
ShowModerationState::Never;
|
||||||
bool hideSimilar = getSettings()->hideSimilar;
|
bool hideSimilar = getSettings()->hideSimilar;
|
||||||
bool hideReplies = !ctx.flags.has(MessageElementFlag::RepliedMessage);
|
bool hideReplies = !ctx.flags.has(MessageElementFlag::RepliedMessage);
|
||||||
|
|
||||||
|
@ -154,9 +157,21 @@ void MessageLayout::actuallyLayout(const MessageLayoutContext &ctx)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideBlockedTermAutomodMessages &&
|
||||||
|
this->message_->flags.has(MessageFlag::AutoModBlockedTerm))
|
||||||
|
{
|
||||||
|
// NOTE: This hides the message but it will make the message re-appear if moderation message hiding is no longer active, and the layout is re-laid-out.
|
||||||
|
// This is only the case for the moderation messages that don't get filtered during creation.
|
||||||
|
// We should decide which is the correct method & apply that everywhere
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->message_->flags.has(MessageFlag::Timeout) ||
|
if (this->message_->flags.has(MessageFlag::Timeout) ||
|
||||||
this->message_->flags.has(MessageFlag::Untimeout))
|
this->message_->flags.has(MessageFlag::Untimeout))
|
||||||
{
|
{
|
||||||
|
// NOTE: This hides the message but it will make the message re-appear if moderation message hiding is no longer active, and the layout is re-laid-out.
|
||||||
|
// This is only the case for the moderation messages that don't get filtered during creation.
|
||||||
|
// We should decide which is the correct method & apply that everywhere
|
||||||
if (hideModerationActions ||
|
if (hideModerationActions ||
|
||||||
(getSettings()->streamerModeHideModActions &&
|
(getSettings()->streamerModeHideModActions &&
|
||||||
getApp()->getStreamerMode()->isEnabled()))
|
getApp()->getStreamerMode()->isEnabled()))
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "providers/twitch/pubsubmessages/AutoMod.hpp"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
@ -143,6 +145,7 @@ struct AutomodAction : PubSubAction {
|
||||||
QString message;
|
QString message;
|
||||||
|
|
||||||
QString reason;
|
QString reason;
|
||||||
|
PubSubAutoModQueueMessage::Reason reasonCode;
|
||||||
|
|
||||||
QString msgID;
|
QString msgID;
|
||||||
};
|
};
|
||||||
|
|
|
@ -349,40 +349,6 @@ PubSub::PubSub(const QString &host, std::chrono::seconds pingInterval)
|
||||||
this->moderation.raidCanceled.invoke(action);
|
this->moderation.raidCanceled.invoke(action);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
// This handler is no longer required as we use the automod-queue topic now
|
|
||||||
this->moderationActionHandlers["automod_rejected"] =
|
|
||||||
[this](const auto &data, const auto &roomID) {
|
|
||||||
AutomodAction action(data, roomID);
|
|
||||||
|
|
||||||
action.source.id = data.value("created_by_user_id").toString();
|
|
||||||
action.source.login = data.value("created_by").toString();
|
|
||||||
|
|
||||||
action.target.id = data.value("target_user_id").toString();
|
|
||||||
|
|
||||||
const auto args = data.value("args").toArray();
|
|
||||||
|
|
||||||
if (args.isEmpty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
action.msgID = data.value("msg_id").toString();
|
|
||||||
|
|
||||||
if (action.msgID.isEmpty())
|
|
||||||
{
|
|
||||||
// Missing required msg_id parameter
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
action.target.login = args[0].toString();
|
|
||||||
action.message = args[1].toString(); // May be omitted
|
|
||||||
action.reason = args[2].toString(); // May be omitted
|
|
||||||
|
|
||||||
this->moderation.autoModMessageBlocked.invoke(action);
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
this->moderationActionHandlers["automod_message_rejected"] =
|
this->moderationActionHandlers["automod_message_rejected"] =
|
||||||
[this](const auto &data, const auto &roomID) {
|
[this](const auto &data, const auto &roomID) {
|
||||||
AutomodInfoAction action(data, roomID);
|
AutomodInfoAction action(data, roomID);
|
||||||
|
|
|
@ -494,6 +494,7 @@ void TwitchIrcServer::initialize()
|
||||||
|
|
||||||
action.msgID = msg.messageID;
|
action.msgID = msg.messageID;
|
||||||
action.message = msg.messageText;
|
action.message = msg.messageText;
|
||||||
|
action.reasonCode = msg.reason;
|
||||||
|
|
||||||
// this message also contains per-word automod data, which could be implemented
|
// this message also contains per-word automod data, which could be implemented
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@ PubSubAutoModQueueMessage::PubSubAutoModQueueMessage(const QJsonObject &root)
|
||||||
this->type = oType.value();
|
this->type = oType.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->reason =
|
||||||
|
qmagicenum::enumCast<Reason>(data.value("reason_code").toString())
|
||||||
|
.value_or(Reason::INVALID);
|
||||||
|
|
||||||
auto contentClassification =
|
auto contentClassification =
|
||||||
data.value("content_classification").toObject();
|
data.value("content_classification").toObject();
|
||||||
|
|
||||||
|
|
|
@ -13,15 +13,24 @@ struct PubSubAutoModQueueMessage {
|
||||||
|
|
||||||
INVALID,
|
INVALID,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Reason {
|
||||||
|
AutoMod,
|
||||||
|
BlockedTerm,
|
||||||
|
|
||||||
|
INVALID,
|
||||||
|
};
|
||||||
|
|
||||||
QString typeString;
|
QString typeString;
|
||||||
Type type = Type::INVALID;
|
Type type = Type::INVALID;
|
||||||
|
Reason reason = Reason::INVALID;
|
||||||
|
|
||||||
QJsonObject data;
|
QJsonObject data;
|
||||||
|
|
||||||
QString status;
|
QString status;
|
||||||
|
|
||||||
QString contentCategory;
|
QString contentCategory;
|
||||||
int contentLevel;
|
int contentLevel{};
|
||||||
|
|
||||||
QString messageID;
|
QString messageID;
|
||||||
QString messageText;
|
QString messageText;
|
||||||
|
@ -51,3 +60,20 @@ constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
|
||||||
return default_tag;
|
return default_tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
|
||||||
|
chatterino::PubSubAutoModQueueMessage::Reason>(
|
||||||
|
chatterino::PubSubAutoModQueueMessage::Reason value) noexcept
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case chatterino::PubSubAutoModQueueMessage::Reason::AutoMod:
|
||||||
|
return "AutoModCaughtMessageReason";
|
||||||
|
case chatterino::PubSubAutoModQueueMessage::Reason::BlockedTerm:
|
||||||
|
return "BlockedTermCaughtMessageReason";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return default_tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -69,6 +69,13 @@ enum class ChatSendProtocol : int {
|
||||||
Helix = 2,
|
Helix = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ShowModerationState : int {
|
||||||
|
// Always show this moderation-related item
|
||||||
|
Always = 0,
|
||||||
|
// Never show this moderation-related item
|
||||||
|
Never = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum StreamerModeSetting {
|
enum StreamerModeSetting {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
Enabled = 1,
|
Enabled = 1,
|
||||||
|
@ -345,6 +352,10 @@ public:
|
||||||
IntSetting timeoutStackStyle = {
|
IntSetting timeoutStackStyle = {
|
||||||
"/moderation/timeoutStackStyle",
|
"/moderation/timeoutStackStyle",
|
||||||
static_cast<int>(TimeoutStackStyle::Default)};
|
static_cast<int>(TimeoutStackStyle::Default)};
|
||||||
|
EnumStringSetting<ShowModerationState> showBlockedTermAutomodMessages = {
|
||||||
|
"/moderation/showBlockedTermAutomodMessages",
|
||||||
|
ShowModerationState::Always,
|
||||||
|
};
|
||||||
|
|
||||||
/// Highlighting
|
/// Highlighting
|
||||||
// BoolSetting enableHighlights = {"/highlighting/enabled", true};
|
// BoolSetting enableHighlights = {"/highlighting/enabled", true};
|
||||||
|
|
|
@ -140,6 +140,8 @@ WindowManager::WindowManager(const Paths &paths, Settings &settings,
|
||||||
this->forceLayoutChannelViewsListener.add(settings.enableRedeemedHighlight);
|
this->forceLayoutChannelViewsListener.add(settings.enableRedeemedHighlight);
|
||||||
this->forceLayoutChannelViewsListener.add(settings.colorUsernames);
|
this->forceLayoutChannelViewsListener.add(settings.colorUsernames);
|
||||||
this->forceLayoutChannelViewsListener.add(settings.boldUsernames);
|
this->forceLayoutChannelViewsListener.add(settings.boldUsernames);
|
||||||
|
this->forceLayoutChannelViewsListener.add(
|
||||||
|
settings.showBlockedTermAutomodMessages);
|
||||||
|
|
||||||
this->layoutChannelViewsListener.add(settings.timestampFormat);
|
this->layoutChannelViewsListener.add(settings.timestampFormat);
|
||||||
this->layoutChannelViewsListener.add(fonts.fontChanged);
|
this->layoutChannelViewsListener.add(fonts.fontChanged);
|
||||||
|
|
|
@ -1171,6 +1171,14 @@ void GeneralPage::initLayout(GeneralPageView &layout)
|
||||||
layout.addIntInput("Usercard scrollback limit (requires restart)",
|
layout.addIntInput("Usercard scrollback limit (requires restart)",
|
||||||
s.scrollbackUsercardLimit, 100, 100000, 100);
|
s.scrollbackUsercardLimit, 100, 100000, 100);
|
||||||
|
|
||||||
|
layout.addDropdownEnumClass<ShowModerationState>(
|
||||||
|
"Show blocked term automod messages",
|
||||||
|
qmagicenum::enumNames<ShowModerationState>(),
|
||||||
|
s.showBlockedTermAutomodMessages,
|
||||||
|
"Show messages that are blocked by AutoMod for containing a public "
|
||||||
|
"blocked term in the current channel.",
|
||||||
|
{});
|
||||||
|
|
||||||
layout.addDropdown<int>(
|
layout.addDropdown<int>(
|
||||||
"Stack timeouts", {"Stack", "Stack until timeout", "Don't stack"},
|
"Stack timeouts", {"Stack", "Stack until timeout", "Don't stack"},
|
||||||
s.timeoutStackStyle,
|
s.timeoutStackStyle,
|
||||||
|
|
Loading…
Reference in a new issue