Files
Module-Rust/client/src/lib/safety.js
wtclaude dd9b8b2711
Some checks failed
PR Checks / client-build (pull_request) Successful in 51s
PR Checks / frozen-manifest (pull_request) Successful in 53s
PR Checks / server-tests (pull_request) Failing after -17s
feat(safety): report, block and hide chat lines (MODULE_API 1.21.0)
USER_SAFETY.md step 3, the module half of report, block and hide.

- server/safety.js registers the rust.chat report target (snapshot for one
  reader, null when they could not have seen the line; staff's hide and
  unhide) and the steam game identity (ownersOf from rust_account_links).
- The events feed filters chat per reader, in the query: lines from a
  blocked account's Steam ids, the reader's unlinked Steam-ID blocks and the
  lines they hid. Signed-in readers get canBlock on each chat line (false for
  their own and for staff-linked players). Lines staff hid for everyone are
  left out for everyone but staff, who get them with hidden: true.
- rust_events gains hidden_at and hidden_by (ALTER ... IF NOT EXISTS).
- POST /admin/rust/chat/:id/hide and /unhide (admin, moderator), logged.
- The feed's chat lines get a menu: Report, Hide for me, Block player,
  and for staff Hide for everyone / Show to everyone again.
- coreApi ^1.21.0; ci/core-ref.json pinned to the website#233 merge;
  routes.manifest.json and swagger-fragment.json regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-30 09:04:08 -05:00

57 lines
2.2 KiB
JavaScript

// ── Report, block and hide on a chat line: what the menu offers ────────────
//
// USER_SAFETY.md §4.2. Nothing here decides what a reader may SEE — the server
// already left out what they blocked or hid, and staff's hidden lines for
// everybody else (S11). This file only turns what the server said about a line
// into which buttons its menu shows, and it is pure so a DOM-less runner can ask
// all of it.
/** The report target a chat line is filed as. Registered by `server/safety.js`. */
export const CHAT_TARGET = 'rust.chat'
/**
* The reasons a report can give. Core's `content_reports.reason` enum, in the
* order and words core's own forum report uses, so a member reads one list
* wherever they report from.
*/
export const REPORT_REASONS = Object.freeze([
['abuse', 'Abusive or harassing'],
['spam', 'Spam'],
['sexual', 'Sexual content'],
['illegal', 'Illegal content'],
['impersonation', 'Impersonation'],
['other', 'Something else'],
])
/**
* The roles that hide a line for everyone: the two core's Reports queue is open
* to, and the two `POST /admin/rust/chat/:id/hide` admits. An editor writes
* content and moderates none.
*/
export const HIDE_ROLES = Object.freeze(['admin', 'moderator'])
/**
* What a chat line's menu offers this reader.
*
* signIn a signed-out reader gets one line telling them to sign in (S6)
* report any signed-in reader, on any line
* hide "Hide for me", likewise — a staff member's line included (S8)
* block only where the server said `canBlock` (S8, S13)
* staff 'hide' or 'unhide' for a reader who can hide for everyone (S10)
*
* @param {{ kind: string, canBlock?: boolean, hidden?: boolean }} line
* @param {{ role?: string } | null} user
*/
export function chatActions(line, user) {
if (!line || line.kind !== 'player.chat') return null
if (!user) return { signIn: true, report: false, hide: false, block: false, staff: null }
const canHideForAll = HIDE_ROLES.includes(user.role)
return {
signIn: false,
report: true,
hide: true,
block: line.canBlock === true,
staff: canHideForAll ? (line.hidden ? 'unhide' : 'hide') : null,
}
}