feat(mute): auto-expiring timed mutes (LC-535) #509
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-535-timed-mutes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Timed mutes (LC-535). The global posting mute can now carry an expiry, so a moderator can mute someone for 15m / 1h / 8h / 24h / 7d instead of only permanently. The mute lifts itself when the clock passes it - no follow-up unmute needed.
This wires up the long-dormant
users.muted_untilcolumn, which existed but was never set (post_mutealways passedNone) and never enforced.How
0189ef3).User::mute_in_effect()decides at the posting gate whether a mute is still in force: a NULLmuted_untilis permanent, a past timestamp has lifted, an unparseable one fails safe to still-muted.db::auth::clear_expired_mutesnulls expired rows so the admin table and exports stay truthful, andspawn_mute_expiry_scannerruns that sweep every 60s (modeled on the custom-status expiry scanner).4e0c9d6). All seven "banned or muted cannot post" checks (message send, DM send, forward, gif, poll create/vote, api post) go throughmute_in_effect()instead of the rawis_mutedflag, so a timed mute stops blocking the moment it expires rather than only after the sweep nulls the row.d6492bb). The single Mute button becomes a duration<select>(15m / 1h / 8h / 24h / 7d / permanent);post_muteresolves the preset to amuted_untilexpiry, records it in the mod-log detail and theUserMutedbroadcast, and the row shows "Muted until <ts> UTC" for a timed mute. An unrecognised preset 400s rather than silently muting forever.f71dee5).clear_expired_mutesintegration coverage: a past mute is nulled and counted; permanent and future mutes are left in force with zero cleared. The expiry decision (mute_active) also has lib unit tests that run in CI.Notes
muted_untilalready exists.banned_until) are deliberately untouched - this ticket is scoped to mutes.🤖 Generated with Claude Code
https://claude.ai/code/session_015RTKivuxdzFXdDyHZmsgYe