FIX: Moderator notifications when new post auto-silences a user (#35403)

When a user is auto-silenced because they receive enough spam flag, we notify moderators (given the notify_mods_when_user_silenced is enabled).

However, when a user is auto-silenced for other reasons, e.g. typing too fast, we don't send this notification.

This commit:

- Lifts the notification logic into a new UserSilencer#auto_silence method, which delegates 99% of its work to UserSilencer#silence.
- Uses this new method in places where users are auto-silenced.
This commit is contained in:
Ted Johansson
2025-10-15 16:07:56 +08:00
committed by GitHub
parent ea0555eedf
commit 69dfdf5084
5 changed files with 58 additions and 34 deletions
+6 -19
View File
@@ -57,24 +57,11 @@ class SpamRule::AutoSilence
end
def silence_user
Post.transaction do
silencer =
UserSilencer.new(
@user,
Discourse.system_user,
message: :too_many_spam_flags,
post_id: @post&.id,
)
if silencer.silence && SiteSetting.notify_mods_when_user_silenced
@group_message =
GroupMessage.create(
Group[:moderators].name,
:user_automatically_silenced,
user: @user,
limit_once_per: false,
)
end
end
UserSilencer.auto_silence(
@user,
Discourse.system_user,
message: :too_many_spam_flags,
post_id: @post&.id,
)
end
end
+26
View File
@@ -11,6 +11,10 @@ class UserSilencer
UserSilencer.new(user, by_user, opts).silence
end
def self.auto_silence(user, by_user = nil, opts = {})
UserSilencer.new(user, by_user, opts).auto_silence
end
def self.unsilence(user, by_user = nil, opts = {})
UserSilencer.new(user, by_user, opts).unsilence
end
@@ -59,6 +63,15 @@ class UserSilencer
end
end
def auto_silence
if silence
notify_moderators
true
else
false
end
end
def hide_posts
return unless @user.trust_level == TrustLevel[0]
@@ -87,4 +100,17 @@ class UserSilencer
StaffActionLogger.new(@by_user).log_unsilence_user(@user) if @by_user
end
end
private
def notify_moderators
return if !SiteSetting.notify_mods_when_user_silenced
GroupMessage.create(
Group[:moderators].name,
:user_automatically_silenced,
user: @user,
limit_once_per: false,
)
end
end
+3 -3
View File
@@ -178,21 +178,21 @@ class NewPostManager
I18n.with_locale(SiteSetting.default_locale) do
if is_fast_typer?(manager)
UserSilencer.silence(
UserSilencer.auto_silence(
manager.user,
Discourse.system_user,
keep_posts: true,
reason: I18n.t("user.new_user_typed_too_fast"),
)
elsif auto_silence?(manager) || matches_auto_silence_regex?(manager)
UserSilencer.silence(
UserSilencer.auto_silence(
manager.user,
Discourse.system_user,
keep_posts: true,
reason: I18n.t("user.content_matches_auto_silence_regex"),
)
elsif reason == :email_spam && is_first_post?(manager)
UserSilencer.silence(
UserSilencer.auto_silence(
manager.user,
Discourse.system_user,
keep_posts: true,
+17 -8
View File
@@ -258,17 +258,23 @@ RSpec.describe NewPostManager do
end
context "with a fast typer" do
before { user.update!(trust_level: 0) }
before do
user.update!(trust_level: 0)
SiteSetting.notify_mods_when_user_silenced = true
end
it "adds the silence reason in the system locale" do
manager = build_manager_with("this is new post content")
I18n.with_locale(:fr) do # Simulate french user
result = NewPostManager.default_handler(manager)
expect { NewPostManager.default_handler(manager) }.to change { user.silenced? }.to(
true,
).and change { user.silence_reason }.to(
I18n.t("user.new_user_typed_too_fast", locale: :en),
).and change {
Topic.where("subtype = 'system_message' AND title LIKE '%silenced%'").count
}.by(1)
end
expect(user.silenced?).to eq(true)
expect(user.silence_reason).to eq(I18n.t("user.new_user_typed_too_fast", locale: :en))
end
it "runs the watched words check before checking if the user is a fast typer" do
@@ -692,6 +698,8 @@ RSpec.describe NewPostManager do
let(:user) { Fabricate(:user, refresh_auto_groups: true) }
let(:admin) { Fabricate(:admin) }
before { SiteSetting.notify_mods_when_user_silenced = true }
it "silences users if its their first post" do
manager =
NewPostManager.new(
@@ -703,9 +711,10 @@ RSpec.describe NewPostManager do
first_post_checks: true,
)
result = manager.perform
expect(result.action).to eq(:enqueued)
expect(user.silenced?).to be(true)
expect { @result = manager.perform }.to change { user.silenced? }.to(true).and change {
Topic.where("subtype = 'system_message' AND title LIKE '%silenced%'").count
}.by(1)
expect(@result.action).to eq(:enqueued)
end
it "doesn't silence or enqueue exempt users" do
+6 -4
View File
@@ -118,14 +118,16 @@ RSpec.describe SpamRule::AutoSilence do
it "sends private message to moderators" do
SiteSetting.notify_mods_when_user_silenced = true
autosilence.silence_user
expect(autosilence.group_message).to be_present
expect { autosilence.silence_user }.to change {
Topic.where("subtype = 'system_message' AND title LIKE '%silenced%'").count
}.by(1)
end
it "doesn't send a pm to moderators if notify_mods_when_user_silenced is false" do
SiteSetting.notify_mods_when_user_silenced = false
autosilence.silence_user
expect(autosilence.group_message).to be_blank
expect { autosilence.silence_user }.not_to change {
Topic.where("subtype = 'system_message' AND title LIKE '%silenced%'").count
}
end
end
end