From 470805acf673999c6b766621a0dee510d0976f81 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Fri, 21 Jul 2023 13:22:56 +0100 Subject: Allow hiding silenced users messages instead of blocking. Implements part 1 of #1606. --- src/modules/m_silence.cpp | 64 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) (limited to 'src/modules/m_silence.cpp') diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp index 321dbeb86..91a2d4c8a 100644 --- a/src/modules/m_silence.cpp +++ b/src/modules/m_silence.cpp @@ -21,6 +21,7 @@ #include "inspircd.h" +#include "clientprotocolmsg.h" #include "modules/ctctags.h" #include "modules/isupport.h" @@ -46,7 +47,10 @@ public: // Exclude users who match this flags ("x"). SF_EXEMPT = 1, - // 2, 4, 8, 16 are reserved for future use. + // Hide the contents of the message when sent to the silencer ("H"). + SF_HIDE_SILENCER = 2, + + // 4, 8, 16 are reserved for future use. // Matches a NOTICE targeted at a channel ("n"). SF_NOTICE_CHANNEL = 32, @@ -122,6 +126,9 @@ public: case 'd': out |= SF_DEFAULT; break; + case 'H': + out |= SF_HIDE_SILENCER; + break; case 'i': out |= SF_INVITE; break; @@ -164,6 +171,8 @@ public: out.push_back('C'); if (flags & SF_CTCP_CHANNEL) out.push_back('c'); + if (flags & SF_HIDE_SILENCER) + out.push_back('H'); if (flags & SF_INVITE) out.push_back('i'); if (flags & SF_NOTICE_USER) @@ -411,17 +420,21 @@ private: bool exemptservice; CommandSilence cmd; - ModResult BuildChannelExempts(User* source, Channel* channel, SilenceEntry::SilenceFlags flag, CUList& exemptions) + void BuildChannelExempts(User* source, Channel* channel, SilenceEntry::SilenceFlags flag, CUList& exemptions, CUList& hides) { for (const auto& [user, _] : channel->GetUsers()) { - if (!CanReceiveMessage(source, user, flag)) + uint32_t flags; + if (!CanReceiveMessage(source, user, flag, &flags)) + { exemptions.insert(user); + if (user != source && flags & SilenceEntry::SF_HIDE_SILENCER) + hides.insert(user); + } } - return MOD_RES_PASSTHRU; } - bool CanReceiveMessage(User* source, User* target, SilenceEntry::SilenceFlags flag) + bool CanReceiveMessage(User* source, User* target, SilenceEntry::SilenceFlags flag, uint32_t* flags = nullptr) { // Servers handle their own clients. if (!IS_LOCAL(target)) @@ -440,12 +453,23 @@ private: continue; if (InspIRCd::Match(source->GetMask(), entry.mask)) + { + if (flags) + *flags = entry.flags; + return entry.flags & SilenceEntry::SF_EXEMPT; + } } return true; } + void HideMessage(std::string& message) + { + InspIRCd::StripColor(message); + message.insert(0, "\x1DSilenced\x1D: \00315,15"); + } + public: ModuleSilence() : Module(VF_VENDOR | VF_OPTCOMMON, "Adds the /SILENCE command which allows users to ignore other users on server-side.") @@ -490,7 +514,20 @@ public: else if (details.type == MessageType::PRIVMSG) flag = SilenceEntry::SF_PRIVMSG_CHANNEL; - return BuildChannelExempts(user, target.Get(), flag, details.exemptions); + CUList hides; + BuildChannelExempts(user, target.Get(), flag, details.exemptions, hides); + if (!hides.empty()) + { + // In this mode we just strip formatting and hide the message. + std::string message = details.text; + HideMessage(message); + + // Servers handle their own users so this cast will always work. + ClientProtocol::Messages::Privmsg msg(user, target.Get(), message, details.type, target.status); + for (auto* hideuser : hides) + static_cast(hideuser)->Send(ServerInstance->GetRFCEvents().privmsg, msg); + } + return MOD_RES_PASSTHRU; } case MessageTarget::TYPE_USER: { @@ -501,9 +538,16 @@ public: else if (details.type == MessageType::PRIVMSG) flag = SilenceEntry::SF_PRIVMSG_USER; - if (!CanReceiveMessage(user, target.Get(), flag)) + uint32_t flags; + if (!CanReceiveMessage(user, target.Get(), flag, &flags)) { details.echo_original = true; + if (flags & SilenceEntry::SF_HIDE_SILENCER) + { + // In this mode we just strip formatting and hide the message. + HideMessage(details.text); + break; + } return MOD_RES_DENY; } break; @@ -518,7 +562,11 @@ public: ModResult OnUserPreTagMessage(User* user, const MessageTarget& target, CTCTags::TagMessageDetails& details) override { if (target.type == MessageTarget::TYPE_CHANNEL) - return BuildChannelExempts(user, target.Get(), SilenceEntry::SF_TAGMSG_CHANNEL, details.exemptions); + { + CUList unused; + BuildChannelExempts(user, target.Get(), SilenceEntry::SF_TAGMSG_CHANNEL, details.exemptions, unused); + return MOD_RES_PASSTHRU; + } if (target.type == MessageTarget::TYPE_USER && !CanReceiveMessage(user, target.Get(), SilenceEntry::SF_TAGMSG_USER)) { -- cgit v1.3.1-10-gc9f91