You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.6 KiB
TypeScript

/**
* Router de comandos (Etapa 3)
* Maneja 'configurar' y 'web', y delega el resto al código actual (null → fallback).
* Nota: No importar CommandService aquí para evitar ciclos de import.
*/
import type { Database } from 'bun:sqlite';
import { ACTION_ALIASES } from './shared';
import { handleConfigurar } from './handlers/configurar';
import { handleWeb } from './handlers/web';
import { handleVer } from './handlers/ver';
import { handleCompletar } from './handlers/completar';
import { handleTomar } from './handlers/tomar';
import { handleSoltar } from './handlers/soltar';
import { handleNueva } from './handlers/nueva';
type NuevaCtx = Parameters<typeof handleNueva>[0];
type VerCtx = Parameters<typeof handleVer>[0];
type CompletarCtx = Parameters<typeof handleCompletar>[0];
type TomarCtx = Parameters<typeof handleTomar>[0];
type SoltarCtx = Parameters<typeof handleSoltar>[0];
type ConfigurarCtx = Parameters<typeof handleConfigurar>[0];
type WebCtx = Parameters<typeof handleWeb>[0];
import { ResponseQueue } from '../response-queue';
import { isGroupId } from '../../utils/whatsapp';
import { Metrics } from '../metrics';
function getQuickHelp(): string {
return [
'Guía rápida:',
'- Ver tus tareas: `/t mias`',
'- Ver todas: `/t todas`',
'- Crear: `/t n Descripción 2028-11-26 @Ana`',
'- Completar: `/t x 123`',
'- Tomar: `/t tomar 12`',
'- Configurar recordatorios: `/t configurar diario|l-v|semanal|off [HH:MM]`',
'- Web: `/t web`'
].join('\n');
}
function getFullHelp(): string {
return [
'Ayuda avanzada:',
'Comandos y alias:',
' · Crear: `n`, `nueva`, `crear`, `+`',
' · Ver: `ver`, `listar`, `mostrar`, `ls` (scopes: `mis` | `todas`)',
' · Completar: `x`, `hecho`, `completar`, `done`',
' · Tomar: `tomar`, `claim`',
' · Soltar: `soltar`, `unassign`',
'Preferencias:',
' · `/t configurar diario|l-v|semanal|off [HH:MM]`',
'Fechas:',
' · `YYYY-MM-DD` o `YY-MM-DD` → `20YY-MM-DD` (ej.: 27-09-04)',
' · Palabras: `hoy`, `mañana`',
'Acceso web:',
' · `/t web`',
'Atajos:',
' · `/t mias`',
' · `/t todas`'
].join('\n');
}
function buildUnknownHelp(): string {
const header = '❓ COMANDO NO RECONOCIDO';
const cta = 'Prueba `/t ayuda`';
return [header, cta, '', getQuickHelp()].join('\n');
}
export type RoutedMessage = {
recipient: string;
message: string;
mentions?: string[];
};
export type RouteContext = {
sender: string;
groupId: string;
message: string;
mentions: string[];
messageId?: string;
participant?: string;
fromMe?: boolean;
};
export async function route(context: RouteContext, deps?: { db: Database }): Promise<RoutedMessage[] | null> {
const trimmed = (context.message || '').trim();
const tokens = trimmed.split(/\s+/);
const rawAction = (tokens[1] || '').toLowerCase();
const action = ACTION_ALIASES[rawAction] || rawAction;
// Ayuda (no requiere DB)
if (action === 'ayuda') {
// Métrica de alias "info" (compatibilidad con legacy)
try {
if (rawAction === 'info' || rawAction === '?') {
Metrics.inc('commands_alias_used_total', 1, { action: 'info' });
}
} catch {}
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
const isAdvanced = (tokens[2] || '').toLowerCase() === 'avanzada';
const message = isAdvanced
? getFullHelp()
: [getQuickHelp(), '', 'Ayuda avanzada: `/t ayuda avanzada`'].join('\n');
return [{
recipient: context.sender,
message
}];
}
// Requiere db inyectada para poder operar (CommandService la inyecta)
const database = deps?.db;
if (!database) return null;
if (action === 'nueva') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return await handleNueva(context as unknown as NuevaCtx, { db: database });
}
if (action === 'ver') {
// Métricas de alias (mias/todas) como en el código actual
try {
if (rawAction === 'mias' || rawAction === 'mías') {
Metrics.inc('commands_alias_used_total', 1, { action: 'mias' });
} else if (rawAction === 'todas' || rawAction === 'todos') {
Metrics.inc('commands_alias_used_total', 1, { action: 'todas' });
}
} catch {}
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
// En grupo: transición a DM
if (isGroupId(context.groupId)) {
try { Metrics.inc('ver_dm_transition_total'); } catch {}
return [{
recipient: context.sender,
message: 'No respondo en grupos. Tus tareas: /t mias · Todas: /t todas · Info: /t info · Web: /t web'
}];
}
return await handleVer(context as unknown as VerCtx);
}
if (action === 'completar') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return await handleCompletar(context as unknown as CompletarCtx);
}
if (action === 'tomar') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return await handleTomar(context as unknown as TomarCtx);
}
if (action === 'soltar') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return await handleSoltar(context as unknown as SoltarCtx);
}
if (action === 'configurar') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return handleConfigurar(context as unknown as ConfigurarCtx, { db: database });
}
if (action === 'web') {
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
return await handleWeb(context as unknown as WebCtx, { db: database });
}
// Desconocido → ayuda rápida
try { Metrics.inc('commands_unknown_total'); } catch {}
return [{
recipient: context.sender,
message: buildUnknownHelp()
}];
}