Commit Graph
11 Commits
Author SHA1 Message Date
legop3 70f71b2d1e green mode slop 1 2026-08-08 23:59:47 -04:00
legop3 6c69c583c5 moving audio gain perms around 2026-08-07 22:34:04 -04:00
legop3 9702cf0f82 gruh i hate fun!! 2026-08-07 15:54:28 -04:00
legop3 1aecab66e7 Merge pull request #19 from Saul5662/feat/fun-commands
feat(commands): add a fun command category with 18 public `rs` commands
2026-07-29 01:55:28 -04:00
Saul5662andClaude Opus 5 46bbe5c531 fix(commands): resolve duplicate nicknames in rs gain, add a help subcommand
`rs gain grant Saul` failed with "Selector matched multiple records. Suggestions:
Saul, cu_a28...33ab5c, Saul, cu_5a5...b6add3." Nicknames are not unique — one
person re-verifying from a new browser produces a second verified record with the
same name — so an exact nickname match can legitimately return several records,
and the shared resolver refuses on ambiguity.

That refusal is correct for deter, kick, and verify, where acting on the wrong of
two plausible targets is a moderation mistake. It is wrong for gain: granting a
volume ceiling to the wrong account belonging to the same person is recoverable.
So the disambiguation is local to this command and resolvers.js is untouched.

Order of preference on an exact match with several hits:

1. The account that is currently online, since that is who the admin is reacting
   to. Sockets are deduped to user ids first, so extra tabs do not matter.
2. Otherwise the first stored record.

Either way the reply says which happened and how many accounts shared the name.
A selector with no exact match still goes through the shared fuzzy resolver, so
typo tolerance and the existing error text are unchanged.

Also adds `rs gain help`, which lists the subcommands and explains the selector
and the online-wins rule. The previous unknown-subcommand fallback listed the
subcommands inline; it now shares the same help text.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 05:08:25 +01:00
Saul5662andClaude Opus 5 a2fbbc100e feat(commands): add a fun command category with 18 public rs commands
Adds a `fun` category to the operator command registry, reachable identically
from site chat and Discord:

- text: bonk, hug, slap, 8ball, roll, coin, ship, rate, uwu, wanted
- counters: bonkboard, pet, snitch
- hardware: honk, boo, spin, disco, vibecheck

Supporting pieces:

- `permission: 'public'` in the registry. The dispatcher previously decided
  non-admin access with a hardcoded chain of `action !== '...'` comparisons, so
  every new public command needed a dispatcher edit. That chain is replaced by a
  registry lookup plus SELF_GATED_ACTIONS, which names the commands that enforce
  their own permissions internally (goal/reason are read-public write-admin;
  verify/deter reject non-lockdown-admins themselves). Existing behavior for
  every pre-existing command is unchanged.
- `cooldowns.js`, a per-actor per-command in-memory gate. Site chat's own rate
  limit is per-socket-per-message and does not bound a specific command, so
  without this one person could turn `rs honk` into a siren. Site chat rebuilds
  its router per message, so the gate is created at module scope there and
  injected.
- `funStatsService`, a small JSON store for the persistent tallies. Counters are
  keyed by an actor key spanning transports (`user:<id>` / `discord:<id>`), and a
  Discord id has no row in `users`, so `user_feature_state` could not hold them
  without violating its foreign key.

Safety notes:

- `issueCommand` is the raw rover transport and performs none of the ownership,
  deterrence, or private-safety checks the socket `command` handler applies, so
  honk and spin re-check `canDrive` themselves and spin re-applies
  `applyPrivateDriveSafety`. Both are therefore site-chat only: a Discord message
  has no socket and can never satisfy those checks.
- `boo` speaks a canned taunt rather than caller-supplied text, so it cannot
  become an unmoderated TTS channel aimed at whoever is nearest a rover.
- `disco` obeys the existing room-light lock and the homeAssistant feature gate.
- The whole fun category is suspended in lockdown mode.
- Mute and deterrence already stop command-shaped chat before the router runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 04:51:40 +01:00
Saul5662andClaude 09c1257578 feat(commands): add 'rs gain' to grant the VIP audio gain boost
Admins can now run 'rs gain list|grant <vip>|revoke <vip>' from web chat or
Discord. Grant matches only against the verified list and revoke only
against current holders, so a nickname shared with an unverified visitor
reports not-found rather than resolving to someone ineligible. The action
joins the moderation set so lockdown narrows it to lockdown admins.

Also extracts the ceiling math into audioLevelsService/gainMath.js and
covers both it and the command with node:test suites.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-29 04:07:44 +01:00
legop3 b26daed93f better banning, new deter mute, replay discord fixes. 2026-07-21 22:50:12 -04:00
legop3 cacd125fcb chat history and other stuffs, light commands replay fixes 2026-07-18 13:10:08 -04:00
legop3 385e7c25fa fixins 2026-07-16 16:45:51 -04:00
legop3 3a8a2ebb13 the big 2026-07-15 00:35:39 -04:00