From 8064ba053f0ca0c5a95dd0a8f167b72667cffed7 Mon Sep 17 00:00:00 2001 From: borja Date: Sun, 7 Sep 2025 15:20:04 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20actualiza=20README.md,=20STATUS.md;=20a?= =?UTF-8?q?=C3=B1ade=20USER=5FGUIDE.md=20y=20.env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: aider (openrouter/openai/gpt-5) --- .env.example | 39 +++++++---- STATUS.md | 167 ++++++++++++++++++++++----------------------- docs/USER_GUIDE.md | 92 +++++++++++++++++++++++++ 3 files changed, 198 insertions(+), 100 deletions(-) create mode 100644 docs/USER_GUIDE.md diff --git a/.env.example b/.env.example index 39743a7..b8beb6b 100644 --- a/.env.example +++ b/.env.example @@ -1,27 +1,40 @@ # .env.example -# Evolution API +# Evolution API (requerido) EVOLUTION_API_URL="https://example-url.com" EVOLUTION_API_KEY="example-api-key" EVOLUTION_API_INSTANCE="example-instance" -# WhatsApp -WHATSAPP_COMMUNITY_ID="example-community-id@g.us" -CHATBOT_PHONE_NUMBER="1234567890" # Número normalizado del bot; evita auto-respuestas +# WhatsApp (requerido) +WHATSAPP_COMMUNITY_ID="example-community-id@g.us" # Comunidad principal para sincronizar grupos +CHATBOT_PHONE_NUMBER="1234567890" # Número normalizado del bot; evita auto-respuestas -# Webhook de este servicio -WEBHOOK_URL="http://your-service-internal-url:3007" # URL interna a la que Evolution API enviará webhooks +# Webhook de este servicio (requerido) +WEBHOOK_URL="http://your-service-internal-url:3007" # URL (idealmente interna) a la que Evolution API enviará webhooks PORT=3007 -# Runtime -NODE_ENV="production" +# Entorno +NODE_ENV="production" # production | development | test +TZ="Europe/Madrid" # Zona horaria usada para "hoy/mañana" y render de fechas -# Opcional: intervalo de sincronización de grupos en milisegundos (por defecto: 86400000 = 24h) -# - Usar menor durante desarrollo (p.ej. 60000 = 1 minuto) -# - Mínimo 10000ms (10s) forzado en development -# - Formato: número sin comillas +# Sincronización de grupos (opcional) +# Intervalo en milisegundos; por defecto 86400000 (24h). En desarrollo puede bajarse (mínimo recomendable 10000ms). # GROUP_SYNC_INTERVAL_MS=86400000 -# Rate limiting (opcional; desactivado en tests; por defecto 15/min) +# Notificaciones (opcional) +# Si se pone a "true", el bot enviará un breve resumen al grupo al crear una tarea (por defecto false). +# NOTIFY_GROUP_ON_CREATE=false + +# Rate limiting por usuario (opcional; desactivado en tests) +# Número de comandos por minuto por usuario (refill rate). Por defecto 15. # RATE_LIMIT_PER_MIN=15 +# Capacidad del bucket (por defecto igual a RATE_LIMIT_PER_MIN). # RATE_LIMIT_BURST=15 + +# Cola de respuestas (opcional — avanzado) +# Intentos máximos antes de marcar como failed (por defecto 6). +# RQ_MAX_ATTEMPTS=6 +# Backoff base en milisegundos para reintentos (por defecto 5000). +# RQ_BASE_BACKOFF_MS=5000 +# Backoff máximo en milisegundos (por defecto 3600000 = 1h). +# RQ_MAX_BACKOFF_MS=3600000 diff --git a/STATUS.md b/STATUS.md index f7edac3..cb674ed 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,96 +1,89 @@ -# Estado del Proyecto - Task Manager para WhatsApp +# Estado del Proyecto — Task Manager para WhatsApp -## ✅ Funcionalidades Completadas -- **Infraestructura Principal** - - Servidor webhook con health checks - - Dockerización y despliegue CapRover - - Gestión de dependencias con Bun -- **Base de Datos** - - Modelo de tareas y asignaciones - - Normalización de IDs de WhatsApp - - Transacciones atómicas - - Migrador up-only para SQLite con tabla `schema_migrations`, backup automático con `VACUUM INTO` y baseline automático si ya existe esquema - - Esquema de `response_queue` extendido con columna `metadata` -- **Sincronización de Grupos** - - Caché de grupos activos y validación en el servidor - - Sync periódico con Evolution API -- **Webhooks** - - Registro/verificación con Evolution API - - Manejo de eventos (MESSAGES_UPSERT) con normalización del nombre del evento - - Corrección: extracción robusta de remitente en DMs vs grupos para evitar 'Invalid sender ID' -- **Cola de Respuestas** - - Persistencia en DB y envío real a Evolution API - - Workers en background activos - - Soporte de menciones: persistencia en `metadata` y envío como `mentioned` en el payload - - Reintentos con backoff exponencial + jitter (4xx = fallo definitivo; 5xx/red = reintento hasta RQ_MAX_ATTEMPTS con `next_attempt_at`) -- **Comandos** - - `/tarea nueva` end-to-end: parseo de descripción y última fecha futura, extracción de asignados desde menciones y tokens `@...`, limpieza de la descripción, persistencia de tarea y asignaciones, y respuesta con menciones. - - Listados: `/t ver` con `grupo`, `mis`, `sin` y `todos`, con tope y resumen “… y X más”, siempre por DM. - - Completar: `/t x ` (alias: `hecho`, `completar`, `done`) con feedback compacto por DM. - - Tomar/Soltar: `/t tomar ` y `/t soltar ` implementados end-to-end con feedback compacto por DM (idempotentes). - - Fechas naturales: soporte de “hoy/mañana” en creación con TZ configurable (env TZ; por defecto Europe/Madrid). - - Ayuda por DM: “/t” y “/t ayuda” devuelven una guía breve; el bot no publica en grupos. -- **Contactos y Nombres** - - Servicio `ContactsService` con caché en memoria (TTL) y actualización por webhooks (CONTACTS_UPDATE/CHATS_UPDATE); fallback a Evolution API para obtener nombres. Se usa para mostrar nombres en los textos (con fallback a números). En entorno de test evita llamadas de red para acelerar y aislar la suite. -- **UX de Notificaciones** - - Confirmación por DM al creador (encabezado: 📝 _desc_, con líneas de fecha 📅 y responsable 🚫👤/👤) y DM a cada asignado (📬, excluye al creador); fechas vencidas marcadas con ⚠️. - - Notificación opcional al grupo controlada por `NOTIFY_GROUP_ON_CREATE` (false por defecto), incluyendo menciones para visibilidad. - - Política solo DM: el bot no publica respuestas en grupos; todos los mensajes de salida se envían por DM al autor (salvo la notificación opcional anterior). -- **Validaciones de Usuario** - - Integración completa de normalización y `ensureUserExists` en el flujo principal de mensajes - - Tests de integración para validaciones de usuarios -- **Testing** - - Suite de tests unitarios con DB en memoria para aislamiento -- **Recordatorios por DM** - - Preferencias por usuario en user_preferences (reminder_freq: off|daily|weekly; reminder_time; last_reminded_on). - - Servicio RemindersService con tick minucioso (desactivado en tests), evita duplicados por día y respeta TZ. - - Soporta daily y weekly (lunes 08:30); no envía si no hay tareas; mensaje compacto con “… y X más”. - - Comando “/t configurar daily|weekly|off” con confirmación por DM. - - Pruebas unitarias para RemindersService y configuración de recordatorios. +Estado general: listo para piloto con la junta directiva; 170 tests pasando. Riesgos operativos principales: CI/CD básico, red interna entre Evolution API y el bot, y backups/persistencia. -## ⚠️ Funcionalidades Pendientes -- **Gestión de Tareas** - - Eliminación opcional de tareas y mejoras de edición. -- **Cola de Respuestas** - - (Post-MVP) Observabilidad y métricas: contadores, latencias, tamaño de cola, endpoint /metrics. -- **Validaciones** - - Permisos de usuario (roles) y pertenencia a grupos (si se requiere política estricta). -- **Menciones y nombres** - - Refinar políticas de caché (TTL, invalidación) y ampliar compatibilidad de endpoints; en DM, WhatsApp no pinta chips de mención de terceros (limitación del cliente). +## Hecho (por áreas) +- Servidor webhook + - Endpoint /health, validación de entorno, extracción robusta de texto (conversation/extended/captions). + - Detección DM vs grupo y política “solo DM”. + - Registro/verificación de webhooks y sincronización de grupos activos con caché. + - Rate limiting por usuario (15/min por defecto; desactivado en tests; aviso con cooldown). +- Base de datos y migraciones + - Inicialización con PRAGMA FK y timestamps de alta precisión. + - Esquema: users, tasks, task_assignments, user_preferences, response_queue (con metadata). + - Migrador up-only con tabla schema_migrations; backup automático con VACUUM INTO; baseline si existe esquema previo. +- Cola de respuestas + - Persistente con workers en background, reintentos con backoff exponencial + jitter, recuperación de items processing tras reinicios, y limpieza/retención. + - 2xx=sent, 4xx=failed definitivo, 5xx/red=reintento; evita enviar al propio bot. +- Comandos + - Crear, listar (grupo/mis/sin/todos), completar, tomar, soltar; ayuda por DM. + - Fechas “hoy/mañana” con TZ configurable; formato dd/MM; vencidas con ⚠️. + - Menciones reales y tokens @…; reglas por defecto: grupo→sin responsable, DM→creador. +- Recordatorios por DM + - Preferencias por usuario (daily|weekly|off; hora con soporte en modelo/servicio), evita duplicados por día, weekly en lunes, respeta TZ, no envía si no hay tareas. +- Contactos y nombres + - Caché en memoria, actualización por webhooks, fallback a Evolution API (saltado en tests); nombres amigables en textos. +- Testing + - ~170 tests unitarios con SQLite en memoria; ResponseQueue (reintentos/cleanup), comandos (alias/fechas/listados/x/tomar/soltar), recordatorios, utilidades. -## ➡️ Próximos Pasos Prioritarios -1. Afinar recordatorios por DM (daily/weekly): hora configurable por usuario y pequeños ajustes de formato. -2. Refinar ContactsService (caché/nombres; TTL configurable; robustez ante fallos; sin red en tests). -3. Sincronización mínima de miembros (cacheada; no bloqueante). -4. Ampliar test suite (contactos, sync de miembros, ResponseQueue). +## Pendiente (priorizado) +- MVP operativo (bloqueantes/casi bloqueantes) + 1) CI/CD: pipeline mínimo (build + bun test + build/push imagen + despliegue CapRover). + 2) Persistencia/backup: volumen /app/data y backup diario del fichero SQLite. + 3) Seguridad/red: ejecutar en red interna con Evolution API; si no, proteger el webhook (IP allowlist/reverse proxy). + 4) Ensayo E2E en staging: registro de webhook, recepción de MESSAGES_UPSERT reales y envío de DMs. +- Post-MVP (mejoras) + - Observabilidad: /metrics con contadores de cola, errores y latencias. + - Orden por destinatario en ResponseQueue; idempotency_key opcional. + - Permisos/roles y pertenencia a grupos (si se requiere). + - Edición/eliminación de tareas. + - Política de caché de contactos (TTL configurable, invalidación más fina). + - Sincronización mínima de miembros (cacheada; no bloqueante). -## 🐞 Problemas conocidos -- En chats privados, WhatsApp no renderiza chips de mención para terceros; en grupos sí se resuelven al nombre local de cada receptor. El bot incluye nombres en el texto cuando los conoce y números como @dígitos para acción rápida; no hay reescritura por receptor. +## Roadmap y próximas iteraciones +- Iteración A — Operativa lista para piloto + - Entregables: pipeline CI (GitHub Actions), build de imagen, despliegue CapRover con volumen /app/data, backup diario configurado, checklist de red interna verificada. +- Iteración B — Observabilidad mínima + - Entregables: logs con contexto en puntos clave, plan de /metrics (pospuesto si no es crítico), guía de troubleshooting. +- Iteración C — Calidad de datos/UX + - Entregables: mejoras de caché de contactos, afinado de recordatorios (hora por usuario), pruebas adicionales de ResponseQueue y comandos. -## 🔧 Archivos Clave a Modificar -- `src/services/response-queue.ts` -- `src/services/command.ts` -- `src/tasks/service.ts` -- `src/server.ts` +## Checklist de readiness para piloto +- Infra + - [ ] App en CapRover con volumen /app/data. + - [ ] Variables de entorno configuradas; TZ correcta. + - [ ] Evol. API y bot en la misma red; /health OK. +- Operación + - [ ] Backups diarios de data/tasks.db y procedimiento de restauración. + - [ ] Logs accesibles; worker de cola activo. +- Funcional + - [ ] Bot añadido a los grupos; grupos activos sincronizados. + - [ ] Comandos base verificados en un grupo real (crear/ver/x/tomar/soltar/configurar). +- Comunicación/privacidad + - [ ] Aviso a la junta: cómo usar, qué se guarda, cómo desactivar recordatorios. -## Phase 4 — Desglose y estado -- Etapa 1 — Reintentos con backoff exponencial + jitter: COMPLETADA. -- Etapa 2 — Recuperación de items en `processing` (lease/expiración): COMPLETADA. -- Etapa 3 — Métricas y observabilidad: POSPUESTA (post-MVP). -- Etapa 4 — Limpieza/retención: COMPLETADA. +## Riesgos y mitigaciones +- Webhook expuesto públicamente + - Mitigación: red interna; si no es posible, IP allowlist/reverse proxy y rotación de claves. +- Pérdida de datos en SQLite + - Mitigación: volumen persistente + backups diarios + prueba de restore. +- TZ incorrecta y mensajes con fecha errónea + - Mitigación: fijar TZ en entorno, tests de humo con “hoy/mañana”. +- Fallos o latencia de Evolution API + - Mitigación: reintentos con backoff; logs de error; visibilidad en ResponseQueue. -## Commit history and status -- Latest status: All 170 unit tests passing; recordatorios por DM implementados (daily/weekly) con preferencia por usuario y comando “/t configurar”; soporte de fechas “hoy/mañana” con TZ configurable y formato dd/MM; ayuda por DM; listados ver grupo/mis/sin/todos; política solo DM; ACK al creador en una línea; notificación al grupo opcional desactivada; ContactsService evita llamadas de red en tests; nombres amigables integrados; rate limiting básico por usuario (15/min, configurable por env; desactivado en tests) implementado; formato de mensajes actualizado: cursiva en descripciones y “responsable” en lugar de “dueño”. +## Testing y cobertura +- Cubre: comandos, ResponseQueue (reintentos/cleanup), recordatorios (daily/weekly/TZ), utilidades, normalización de IDs, validaciones básicas en servidor. +- Falta: pruebas E2E reales contra Evolution API (recomendado antes del piloto). -## ▶️ Para continuar ahora -Propuesta inmediata: -- Afinar recordatorios por DM (daily/weekly): hora configurable por usuario; encabezados ⏰ y formato de mensajes ya actualizados. -- Refinar ContactsService (caché y nombres; TTL configurable; robustez ante fallos; sin red en tests). -- Sincronización mínima de miembros (cacheada; no bloqueante). -- Ampliar test suite (recordatorios, contactos, sync de miembros, ResponseQueue). +## Notas de despliegue/operación +- Migraciones up-only al arranque; backup con VACUUM INTO previo. +- Persistencia en data/; mapear a volumen y monitorizar tamaño; ejecutar VACUUM periódicamente si procede. +- Rotación de logs vía orquestador; considerar niveles/etiquetas para búsquedas. -Para que pueda proponer cambios de código, añade estos archivos a este chat: -- `src/services/command.ts` -- `src/tasks/service.ts` -- `src/services/response-queue.ts` -- `src/server.ts` +## Changelog breve +- Reintentos/backoff y recuperación de ResponseQueue: completado. +- Recordatorios por DM (daily/weekly) con preferencias: completado. +- Rate limiting por usuario: completado. +- Ayuda por DM y formato de mensajes unificado: completado. +- Limpieza/retención de historiales de cola: completado. diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md new file mode 100644 index 0000000..40f77f9 --- /dev/null +++ b/docs/USER_GUIDE.md @@ -0,0 +1,92 @@ +# Guía de uso — Task WhatsApp Chatbot + +Principios +- Prefijo de comandos: “/t” o “/tarea”. +- Respuestas “solo DM”: el bot no publica en grupos; siempre envía un mensaje directo al autor (salvo resumen opcional al crear si se activa). +- Fechas: puedes escribir “hoy” o “mañana” y también YYYY-MM-DD. La zona horaria se configura con la variable de entorno TZ (por defecto Europe/Madrid). +- Límite de uso: rate limit por usuario (15/min por defecto); si lo superas, verás un aviso (acotado a 1/min). + +Comandos y alias +- Crear + - Aliases: n, nueva, crear, + + - Ejemplos: + - /t nueva Acta de la reunión mañana + - /t n Carteles fiesta 2025-09-12 @600123456 + - /t + Preparar dossier @600111111 @600222222 + - Reglas: + - En grupo: si no mencionas a nadie → “sin responsable”. + - En DM: si no mencionas a nadie → se asigna al creador. +- Ver + - Aliases: ver, mostrar, listar, ls + - Scopes: + - grupo — pendientes del grupo desde el que invocas (incluye “sin responsable”). + - mis — tus pendientes (agregado de todos tus grupos). + - sin — pendientes sin responsable (según contexto). + - todos — visión general (según permisos futuros). + - Ejemplos: + - /t ver grupo + - /t ver mis +- Completar + - Aliases: x, hecho, completar, done + - Ejemplos: + - /t x 26 + - /t hecho 31 + - Notas: registra quién completa; no restringido solo a asignados (por fluidez). +- Tomar + - Aliases: tomar, claim + - Ejemplo: /t tomar 26 + - Idempotente: si ya eres asignado, lo indica sin error. +- Soltar + - Aliases: soltar, unassign + - Ejemplo: /t soltar 26 + - Idempotente: si no estabas asignado, lo indica sin error. La tarea puede quedar “sin responsable” si no quedan asignados. +- Configurar recordatorios + - Aliases: configurar, config + - Opciones: daily | weekly | off + - Ejemplos: + - /t configurar daily + - /t configurar weekly + - /t configurar off + - Notas: resumen diario/weekly por DM; weekly los lunes a la hora configurada (por defecto 08:30 si aplica); se evita duplicar en el mismo día y no se envía si no hay tareas. +- Ayuda + - Aliases: ayuda, help, ? + - Ejemplos: /t, /t ayuda + +Gramática y formato +- Menciones + - Acepta menciones reales del cliente y tokens @número en el texto. + - En DM, WhatsApp no muestra chips de mención de terceros; se incluye @número como texto para acción rápida. +- Fechas + - “hoy”, “mañana” o YYYY-MM-DD. La app usa TZ del servidor para interpretar y mostrar. +- Salida (mensajes) + - Formato compacto con emojis; descripciones en cursiva; fechas en dd/MM. + - Fechas vencidas marcadas con ⚠️. + - Ejemplos de cabeceras: + - 📝 26 _Acta de la reunión_ + - 📬 Tarea 26 — 📅 12/09 + +Ejemplos prácticos +- Crear en grupo sin menciones (queda sin responsable): + - /t nueva Revisión presupuesto mañana +- Crear en DM (se asigna a ti): + - /t nueva Preparar documento hoy +- Crear con varios asignados: + - /t nueva Carteles @600111111 @600222222 2025-10-10 +- Ver tus tareas: + - /t ver mis +- Completar: + - /t x 42 +- Tomar y soltar: + - /t tomar 42 + - /t soltar 42 +- Configurar recordatorios: + - /t configurar weekly + +Limitaciones y notas +- El bot no publica en grupos por diseño. +- La cola de respuestas no garantiza orden estricto por destinatario. +- En algunos clientes, las menciones en DM no se muestran como chips. +- Límite de 15 comandos/min por usuario (configurable). + +Contacto y soporte +- Si encuentras problemas o tienes ideas, abre un issue en el repositorio o contacta con el administrador de la instancia.