DEV: Add topic_tracking_state_publish_unread_scope modifier (#37236)

This modifier allows plugins to customize the TopicUser scope used when
publishing unread notifications via MessageBus.

Plugins can use this to filter which users receive unread notifications,
for example to exclude users who haven't visited the site in a certain
time period.

```
# in plugin.rb
DiscoursePluginRegistry.register_modifier(self, :topic_tracking_state_publish_unread_scope) do |scope, post|
  scope.joins(:user).where.not(user: { last_seen_at: nil })
end
```
This commit is contained in:
Natalie Tay
2026-01-21 17:59:33 +08:00
committed by GitHub
parent 24bf2c4e72
commit 2dff501fbd
2 changed files with 31 additions and 0 deletions
+6
View File
@@ -149,6 +149,12 @@ class TopicTrackingState
# this is why they are excluded from the initial scope.
scope =
TopicUser.tracking(post.topic_id).includes(user: :user_stat).where.not(user_id: post.user_id)
scope =
DiscoursePluginRegistry.apply_modifier(
:topic_tracking_state_publish_unread_scope,
scope,
post,
)
group_ids =
if post.post_type == Post.types[:whisper]
+25
View File
@@ -272,6 +272,31 @@ RSpec.describe TopicTrackingState do
expect(messages).to eq([])
end
end
it "allows plugins to modify the scope via topic_tracking_state_publish_unread_scope modifier" do
user_to_exclude = Fabricate(:user)
Fabricate(:topic_user_watching, topic: topic, user: user_to_exclude)
messages = MessageBus.track_publish("/unread") { TopicTrackingState.publish_unread(post) }
expect(messages.first.user_ids).to include(user_to_exclude.id)
plugin = Plugin::Instance.new
modifier_block = Proc.new { |scope, _post| scope.where.not(user_id: user_to_exclude.id) }
DiscoursePluginRegistry.register_modifier(
plugin,
:topic_tracking_state_publish_unread_scope,
&modifier_block
)
messages = MessageBus.track_publish("/unread") { TopicTrackingState.publish_unread(post) }
expect(messages.first.user_ids).not_to include(user_to_exclude.id)
ensure
DiscoursePluginRegistry.unregister_modifier(
plugin,
:topic_tracking_state_publish_unread_scope,
&modifier_block
)
end
end
describe "#publish_muted" do