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.
162 lines
5.6 KiB
TypeScript
162 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 info`';
|
|
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;
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Route helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function trackOnboarding(): void {
|
|
try { ResponseQueue.setOnboardingAggregatesMetrics(); } catch {}
|
|
}
|
|
|
|
function trackAlias(metric: string): void {
|
|
try { Metrics.inc('commands_alias_used_total', 1, { action: metric }); } catch {}
|
|
}
|
|
|
|
function trackUknown(): void {
|
|
try { Metrics.inc('commands_unknown_total'); } catch {}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Route dispatcher
|
|
// ---------------------------------------------------------------------------
|
|
|
|
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') {
|
|
if (rawAction === 'info' || rawAction === '?') trackAlias('info');
|
|
trackOnboarding();
|
|
|
|
const isAdvanced = (tokens[2] || '').toLowerCase() === 'avanzada';
|
|
const message = isAdvanced
|
|
? getFullHelp()
|
|
: [getQuickHelp(), '', 'Ayuda avanzada: `t ayuda avanzada`'].join('\n');
|
|
return [{ recipient: context.sender, message }];
|
|
}
|
|
|
|
// --- resto de comandos requieren DB ---
|
|
const database = deps?.db;
|
|
if (!database) return null;
|
|
|
|
// --- nueva ---
|
|
if (action === 'nueva') {
|
|
trackOnboarding();
|
|
return await handleNueva(context as unknown as NuevaCtx, { db: database });
|
|
}
|
|
|
|
// --- ver ---
|
|
if (action === 'ver') {
|
|
if (rawAction === 'mias' || rawAction === 'mías') trackAlias('mias');
|
|
else if (rawAction === 'todas' || rawAction === 'todos') trackAlias('todas');
|
|
trackOnboarding();
|
|
|
|
// 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);
|
|
}
|
|
|
|
// --- completar / tomar / soltar ---
|
|
if (action === 'completar') { trackOnboarding(); return await handleCompletar(context as unknown as CompletarCtx); }
|
|
if (action === 'tomar') { trackOnboarding(); return await handleTomar(context as unknown as TomarCtx); }
|
|
if (action === 'soltar') { trackOnboarding(); return await handleSoltar(context as unknown as SoltarCtx); }
|
|
|
|
// --- configurar / web ---
|
|
if (action === 'configurar') { trackOnboarding(); return handleConfigurar(context as unknown as ConfigurarCtx, { db: database }); }
|
|
if (action === 'web') { trackOnboarding(); return await handleWeb(context as unknown as WebCtx, { db: database }); }
|
|
|
|
// --- desconocido ---
|
|
trackUknown();
|
|
return [{ recipient: context.sender, message: buildUnknownHelp() }];
|
|
}
|