fix(safety): team notifications skip members who block the author
#233 left this open: the forum hid a blocked author's posts from a member, but the member was still pushed, put in the inbox and emailed about them. - teamNotify.forumPost excludes every member who blocks the post's author, or the member who started the thread (the forum 404s that thread for them). One recipient list, so push, the inbox and email skip the same people. userSafety.blockersOf answers it, and a staff author is blocked by nobody (S8). A failed lookup notifies without it. - The daily digest applies each recipient's forumFilter at send time: blocked authors, blocked thread starters, hidden threads and posts. digestPostsSince now also returns the thread's created_by. - A reply's notify payload carries threadAuthorUserId. The Team activity feed needed nothing: forum posts are never written to it (membership, renames and module game events only). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -42,6 +42,7 @@ const templates = require('../engagement/templates')
|
||||
const emailChannel = require('../engagement/emailChannel')
|
||||
const mailer = require('./mailer')
|
||||
const notify = require('./teamNotify')
|
||||
const safety = require('../model/safety/userSafety.model')
|
||||
const { DELETED_PLAYER } = require('./displayAuthor')
|
||||
const log = require('./logger')('team-digest')
|
||||
|
||||
@@ -114,7 +115,17 @@ async function digestRule() {
|
||||
async function sendOne(team, recipient, rule, now) {
|
||||
const scopeKey = notify.scopeKey(team)
|
||||
const since = clampSince(recipient.last_digest_at, now)
|
||||
const posts = await teamNotify.digestPostsSince(team.id, since, MAX_ITEMS)
|
||||
const all = await teamNotify.digestPostsSince(team.id, since, MAX_ITEMS)
|
||||
// What the forum would leave out for THIS recipient stays out of their mail too:
|
||||
// posts by an account they block, posts in a thread whose starter they block, and
|
||||
// anything they hid (USER_SAFETY.md §4.1). Same filter, read at send time like
|
||||
// the rest of the digest.
|
||||
const filter = await safety.forumFilter(recipient.user_id)
|
||||
const posts = all.filter((p) =>
|
||||
!filter.hidden.team_forum_post.has(Number(p.id))
|
||||
&& !filter.hidden.team_forum_thread.has(Number(p.thread_id))
|
||||
&& !(p.author_user_id != null && filter.blockedUserIds.has(Number(p.author_user_id)))
|
||||
&& !(p.thread_created_by != null && filter.blockedUserIds.has(Number(p.thread_created_by))))
|
||||
// Nothing new for THIS recipient — which is not the same as nothing new for the
|
||||
// Team, because each recipient has their own `since`. No mail, and no stamp: a
|
||||
// stamp here would move the window past posts they have not been told about.
|
||||
|
||||
Reference in New Issue
Block a user