mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
Merge pull request #19 from Saul5662/feat/fun-commands
feat(commands): add a fun command category with 18 public `rs` commands
This commit is contained in:
@@ -13,9 +13,22 @@ const { createLightsCommand } = require('./commands/lights');
|
||||
const { createKickCommand } = require('./commands/kick');
|
||||
const { createLiftCommand } = require('./commands/lift');
|
||||
const { createNeatoCommand } = require('./commands/neato');
|
||||
const { createFunTextCommands } = require('./commands/funText');
|
||||
const { createFunStatsCommands } = require('./commands/funStats');
|
||||
const { createFunRoverCommands } = require('./commands/funRover');
|
||||
const { createCooldownGate } = require('./cooldowns');
|
||||
const { getCommandConfig } = require('./config');
|
||||
const { buildCommandRegistry } = require('./registry');
|
||||
|
||||
/*
|
||||
Commands that enforce their own permissions inside their handler rather than at
|
||||
the dispatcher. `goal` and `reason` are readable by anyone but only writable by
|
||||
an admin; `verify` and `deter` reject non-lockdown-admins themselves so they can
|
||||
explain which role is missing. Listing them here preserves that behavior now
|
||||
that the general non-admin gate is driven by registry metadata.
|
||||
*/
|
||||
const SELF_GATED_ACTIONS = new Set(['', 'status', 'help', 'replay', 'bridge', 'goal', 'reason', 'verify', 'deter']);
|
||||
|
||||
function createCommandHandlers(deps) {
|
||||
const {
|
||||
getMode,
|
||||
@@ -56,6 +69,20 @@ function createCommandHandlers(deps) {
|
||||
const handleLiftCommand = createLiftCommand(deps);
|
||||
const handleNeatoCommand = createNeatoCommand(deps);
|
||||
|
||||
/*
|
||||
Fun commands share one cooldown gate. Web chat rebuilds this router per
|
||||
message, so an injected gate is what makes the cooldowns actually shared
|
||||
across a user's messages; a gate created here would be discarded every time
|
||||
and rate limit nothing. Falling back to a local gate keeps the router usable
|
||||
on its own (and in tests) without making every caller supply one.
|
||||
*/
|
||||
const cooldowns = deps.commandCooldowns || createCooldownGate();
|
||||
const funHandlers = {
|
||||
...createFunTextCommands({ ...deps, cooldowns }),
|
||||
...createFunStatsCommands({ ...deps, cooldowns }),
|
||||
...createFunRoverCommands({ ...deps, cooldowns }),
|
||||
};
|
||||
|
||||
function stripCommandPrefix(content) {
|
||||
const trimmed = String(content || '').trim();
|
||||
const lower = trimmed.toLowerCase();
|
||||
@@ -101,6 +128,8 @@ function createCommandHandlers(deps) {
|
||||
// lockdown admin while the entire server is in lockdown.
|
||||
const moderationActions = new Set(['lock', 'unlock', 'mode', 'goal', 'reason', 'verify', 'deter', 'gain', 'lights', 'kick', 'lift', 'neato']);
|
||||
const isAccessModeCommand = commandDefinition?.permission === 'access-mode';
|
||||
const isPublicCommand = commandDefinition?.permission === 'public';
|
||||
const isFunCommand = commandDefinition?.category === 'fun';
|
||||
|
||||
// Feature commands are public activities while access is open or managed
|
||||
// by turns. In admin mode they follow the same admin-only boundary as rover
|
||||
@@ -112,12 +141,17 @@ function createCommandHandlers(deps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAccessModeCommand && !isAdmin && action !== '' && action !== 'status' && action !== 'help' && action !== 'replay' && action !== 'bridge' && action !== 'goal' && action !== 'reason' && action !== 'verify' && action !== 'deter') {
|
||||
if (!isAccessModeCommand && !isPublicCommand && !isAdmin && !SELF_GATED_ACTIONS.has(action)) {
|
||||
await request.reply({ content: 'Only admins can run that command.', allowedMentions: { parse: [], repliedUser: false } });
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === MODES.LOCKDOWN && moderationActions.has(action) && !isLockdownAdmin) {
|
||||
/*
|
||||
Lockdown exists to make the server quiet and controlled, so the whole fun
|
||||
category is suspended alongside the moderation-sensitive actions rather than
|
||||
leaving a horn command reachable by anyone while the fleet is locked down.
|
||||
*/
|
||||
if (mode === MODES.LOCKDOWN && (moderationActions.has(action) || isFunCommand) && !isLockdownAdmin) {
|
||||
await request.reply({ content: 'Lockdown mode: only lockdown admins can run that command.', allowedMentions: { parse: [], repliedUser: false } });
|
||||
return;
|
||||
}
|
||||
@@ -158,6 +192,7 @@ function createCommandHandlers(deps) {
|
||||
case 'gain':
|
||||
return handleGainCommand(request, tokens);
|
||||
default:
|
||||
if (funHandlers[action]) return funHandlers[action](request, tokens);
|
||||
return request.reply(formatHelp({ commandPrefix, timeStatusCommand, includeDiscord: request.transport === 'discord', isFeatureEnabled: deps.isFeatureEnabled }));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user