diff --git a/CHANGELOG.md b/CHANGELOG.md index 84dd05626..26fedd43b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Bugfix: Copy buttons in usercard now show properly in light mode (#3057) - Bugfix: Fixed comma appended to username completion when not at the beginning of the message. (#3060) - Bugfix: Fixed bug misplacing chat when zooming on Chrome with Chatterino Native Host extension (#1936) +- Bugfix: Channel point redemptions from ignored users are now properly blocked. (#3102) - Dev: Ubuntu packages are now available (#2936) - Dev: Disabled update checker on Flatpak. (#3051) - Dev: Add logging for HTTP requests (#2991) diff --git a/chatterino.pro b/chatterino.pro index b858cec90..633528629 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -159,6 +159,7 @@ SOURCES += \ src/controllers/highlights/HighlightModel.cpp \ src/controllers/highlights/HighlightPhrase.cpp \ src/controllers/highlights/UserHighlightModel.cpp \ + src/controllers/ignores/IgnoreController.cpp \ src/controllers/ignores/IgnoreModel.cpp \ src/controllers/moderationactions/ModerationAction.cpp \ src/controllers/moderationactions/ModerationActionModel.cpp \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e935e7366..31d7a1a98 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -88,6 +88,8 @@ set(SOURCE_FILES controllers/highlights/UserHighlightModel.cpp controllers/highlights/UserHighlightModel.hpp + controllers/ignores/IgnoreController.cpp + controllers/ignores/IgnoreController.hpp controllers/ignores/IgnoreModel.cpp controllers/ignores/IgnoreModel.hpp diff --git a/src/controllers/ignores/IgnoreController.cpp b/src/controllers/ignores/IgnoreController.cpp new file mode 100644 index 000000000..e36feead0 --- /dev/null +++ b/src/controllers/ignores/IgnoreController.cpp @@ -0,0 +1,63 @@ +#include "controllers/ignores/IgnoreController.hpp" + +#include "common/QLogging.hpp" +#include "controllers/ignores/IgnorePhrase.hpp" +#include "singletons/Settings.hpp" + +namespace chatterino { + +bool isIgnoredMessage(IgnoredMessageParameters &¶ms) +{ + if (!params.message.isEmpty()) + { + // TODO(pajlada): Do we need to check if the phrase is valid first? + auto phrases = getCSettings().ignoredMessages.readOnly(); + for (const auto &phrase : *phrases) + { + if (phrase.isBlock() && phrase.isMatch(params.message)) + { + qCDebug(chatterinoMessage) + << "Blocking message because it contains ignored phrase" + << phrase.getPattern(); + return true; + } + } + } + + if (!params.twitchUserID.isEmpty() && + getSettings()->enableTwitchBlockedUsers) + { + auto sourceUserID = params.twitchUserID; + + auto blocks = + getApp()->accounts->twitch.getCurrent()->accessBlockedUserIds(); + + if (auto it = blocks->find(sourceUserID); it != blocks->end()) + { + switch (static_cast( + getSettings()->showBlockedUsersMessages.getValue())) + { + case ShowIgnoredUsersMessages::IfModerator: + if (params.isMod || params.isBroadcaster) + { + return false; + } + break; + case ShowIgnoredUsersMessages::IfBroadcaster: + if (params.isBroadcaster) + { + return false; + } + break; + case ShowIgnoredUsersMessages::Never: + break; + } + + return true; + } + } + + return false; +} + +} // namespace chatterino diff --git a/src/controllers/ignores/IgnoreController.hpp b/src/controllers/ignores/IgnoreController.hpp index fed12f12c..4c2048621 100644 --- a/src/controllers/ignores/IgnoreController.hpp +++ b/src/controllers/ignores/IgnoreController.hpp @@ -1,7 +1,19 @@ #pragma once +#include + namespace chatterino { enum class ShowIgnoredUsersMessages { Never, IfModerator, IfBroadcaster }; +struct IgnoredMessageParameters { + QString message; + + QString twitchUserID; + bool isMod; + bool isBroadcaster; +}; + +bool isIgnoredMessage(IgnoredMessageParameters &¶ms); + } // namespace chatterino diff --git a/src/messages/SharedMessageBuilder.cpp b/src/messages/SharedMessageBuilder.cpp index 1235af3c6..cdc8e59f0 100644 --- a/src/messages/SharedMessageBuilder.cpp +++ b/src/messages/SharedMessageBuilder.cpp @@ -2,6 +2,7 @@ #include "Application.hpp" #include "common/QLogging.hpp" +#include "controllers/ignores/IgnoreController.hpp" #include "controllers/ignores/IgnorePhrase.hpp" #include "messages/Message.hpp" #include "messages/MessageElement.hpp" @@ -104,20 +105,9 @@ void SharedMessageBuilder::parse() bool SharedMessageBuilder::isIgnored() const { - // TODO(pajlada): Do we need to check if the phrase is valid first? - auto phrases = getCSettings().ignoredMessages.readOnly(); - for (const auto &phrase : *phrases) - { - if (phrase.isBlock() && phrase.isMatch(this->originalMessage_)) - { - qCDebug(chatterinoMessage) - << "Blocking message because it contains ignored phrase" - << phrase.getPattern(); - return true; - } - } - - return false; + return isIgnoredMessage({ + /*.message = */ this->originalMessage_, + }); } void SharedMessageBuilder::parseUsernameColor() diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 95b3f6944..94c458a55 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -286,7 +286,8 @@ void TwitchChannel::addChannelPointReward(const ChannelPointReward &reward) if (!reward.isUserInputRequired) { MessageBuilder builder; - TwitchMessageBuilder::appendChannelPointRewardMessage(reward, &builder); + TwitchMessageBuilder::appendChannelPointRewardMessage( + reward, &builder, this->isMod(), this->isBroadcaster()); this->addMessage(builder.release()); return; } diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index f79104799..97c36f0d7 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -114,44 +114,12 @@ TwitchMessageBuilder::TwitchMessageBuilder( bool TwitchMessageBuilder::isIgnored() const { - if (SharedMessageBuilder::isIgnored()) - { - return true; - } - - auto app = getApp(); - - if (getSettings()->enableTwitchBlockedUsers && - this->tags.contains("user-id")) - { - auto sourceUserID = this->tags.value("user-id").toString(); - - auto blocks = - app->accounts->twitch.getCurrent()->accessBlockedUserIds(); - - if (auto it = blocks->find(sourceUserID); it != blocks->end()) - { - switch (static_cast( - getSettings()->showBlockedUsersMessages.getValue())) - { - case ShowIgnoredUsersMessages::IfModerator: - if (this->channel->isMod() || - this->channel->isBroadcaster()) - return false; - break; - case ShowIgnoredUsersMessages::IfBroadcaster: - if (this->channel->isBroadcaster()) - return false; - break; - case ShowIgnoredUsersMessages::Never: - break; - } - - return true; - } - } - - return false; + return isIgnoredMessage({ + /*.message = */ this->originalMessage_, + /*.twitchUserID = */ this->tags.value("user-id").toString(), + /*.isMod = */ this->channel->isMod(), + /*.isBroadcaster = */ this->channel->isBroadcaster(), + }); } void TwitchMessageBuilder::triggerHighlights() @@ -190,7 +158,9 @@ MessagePtr TwitchMessageBuilder::build() this->args.channelPointRewardId); if (reward) { - this->appendChannelPointRewardMessage(reward.get(), this); + this->appendChannelPointRewardMessage( + reward.get(), this, this->channel->isMod(), + this->channel->isBroadcaster()); } } @@ -1261,8 +1231,19 @@ Outcome TwitchMessageBuilder::tryParseCheermote(const QString &string) } void TwitchMessageBuilder::appendChannelPointRewardMessage( - const ChannelPointReward &reward, MessageBuilder *builder) + const ChannelPointReward &reward, MessageBuilder *builder, bool isMod, + bool isBroadcaster) { + if (isIgnoredMessage({ + /*.message = */ "", + /*.twitchUserID = */ reward.user.id, + /*.isMod = */ isMod, + /*.isBroadcaster = */ isBroadcaster, + })) + { + return; + } + builder->emplace(); QString redeemed = "Redeemed"; QStringList textList; diff --git a/src/providers/twitch/TwitchMessageBuilder.hpp b/src/providers/twitch/TwitchMessageBuilder.hpp index 3e14412b7..7cf68494a 100644 --- a/src/providers/twitch/TwitchMessageBuilder.hpp +++ b/src/providers/twitch/TwitchMessageBuilder.hpp @@ -46,7 +46,8 @@ public: MessagePtr build() override; static void appendChannelPointRewardMessage( - const ChannelPointReward &reward, MessageBuilder *builder); + const ChannelPointReward &reward, MessageBuilder *builder, bool isMod, + bool isBroadcaster); // Message in the /live chat for channel going live static void liveMessage(const QString &channelName,