aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_silence.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2023-07-21 13:22:56 +0100
committerGravatar Sadie Powell2023-07-21 13:23:30 +0100
commit470805acf673999c6b766621a0dee510d0976f81 (patch)
treee23c463b475f419a2b44220c23760e2d27b395fb /src/modules/m_silence.cpp
parentAdd incremental backoff to the filter/permchannels/xline_db modules. (diff)
Allow hiding silenced users messages instead of blocking.
Implements part 1 of #1606.
Diffstat (limited to 'src/modules/m_silence.cpp')
-rw-r--r--src/modules/m_silence.cpp64
1 files changed, 56 insertions, 8 deletions
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<Channel>(), flag, details.exemptions);
+ CUList hides;
+ BuildChannelExempts(user, target.Get<Channel>(), 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<Channel>(), message, details.type, target.status);
+ for (auto* hideuser : hides)
+ static_cast<LocalUser*>(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<User>(), flag))
+ uint32_t flags;
+ if (!CanReceiveMessage(user, target.Get<User>(), 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<Channel>(), SilenceEntry::SF_TAGMSG_CHANNEL, details.exemptions);
+ {
+ CUList unused;
+ BuildChannelExempts(user, target.Get<Channel>(), SilenceEntry::SF_TAGMSG_CHANNEL, details.exemptions, unused);
+ return MOD_RES_PASSTHRU;
+ }
if (target.type == MessageTarget::TYPE_USER && !CanReceiveMessage(user, target.Get<User>(), SilenceEntry::SF_TAGMSG_USER))
{