# Task WhatsApp Chatbot Un chatbot de WhatsApp para gestionar tareas en grupos, integrado con Evolution API. Diseño “solo DM”: el bot no publica en grupos; todas las respuestas se envían por mensaje directo al autor (opcionalmente puede enviarse un breve resumen al grupo al crear, configurable). ## Cómo se usa (mini guía para usuarios) - Principios - Comandos con prefijo “/t” o “/tarea”. - En grupo: el bot responde por DM al autor (no escribe en el grupo). - Fechas en formato dd/MM en mensajes; puedes escribir “hoy” o “mañana” al crear; la zona horaria se controla con la variable de entorno TZ (por defecto Europe/Madrid). - Comandos y alias principales - Crear: “/t nueva Acta reunión mañana @600123456” - Ver pendientes del grupo: “/t ver grupo” - Ver tus pendientes: “/t ver mis” - Completar: “/t x 26” (alias: hecho, completar, done) - Tomar: “/t tomar 26” - Soltar: “/t soltar 26” - Configurar recordatorios: “/t configurar daily|weekly|off” - Ayuda: “/t” o “/t ayuda” - Notas y reglas - Si creas en grupo y no mencionas a nadie: queda “sin responsable”. - Si creas por DM y no mencionas a nadie: se asigna al creador. - En DM, WhatsApp no muestra chips de mención de terceros; se incluye @número como texto para acción rápida. - Guía completa con alias, reglas y ejemplos: docs/USER_GUIDE.md ## Características - Crear, listar, completar, tomar/soltar tareas; ayuda por DM. - Recordatorios por DM (daily/weekly) por usuario; evita duplicados y respeta TZ. - Cola de respuestas persistente con reintentos (backoff exponencial + jitter) y recuperación tras reinicios. - Nombres amigables vía caché de contactos (sin llamadas de red en tests). - Sincronización de miembros de grupos (snapshot periódica + webhooks incrementales; tolerante a fallos). - Mensajes compactos con emojis y cursiva; fechas dd/MM; vencidas con ⚠️. - Observabilidad mínima: /metrics (Prometheus por defecto, JSON opcional) y /health detallado. ## Requisitos - Evolution API accesible (recomendado: misma red interna Docker). - Bun para desarrollo local; Docker/CapRover para despliegue. - SQLite embebido con persistencia en data/. ## Variables de entorno - Requeridas - EVOLUTION_API_URL: URL de Evolution API (p.ej., http://evolution-api:3000). - EVOLUTION_API_KEY: API key de Evolution. - EVOLUTION_API_INSTANCE: nombre de la instancia en Evolution. - WHATSAPP_COMMUNITY_ID: comunidad principal desde la que sincronizar grupos (jid @g.us). - CHATBOT_PHONE_NUMBER: número normalizado del bot (evita auto-respuestas). - WEBHOOK_URL: URL (interna) donde Evolution enviará webhooks. - PORT: puerto del servidor webhook (p.ej., 3007). - Opcionales — comportamiento - TZ: zona horaria para “hoy/mañana” y render de fechas; por defecto Europe/Madrid. - NOTIFY_GROUP_ON_CREATE: si “true”, envía resumen al grupo al crear (por defecto false). - GROUP_SYNC_INTERVAL_MS: intervalo de sync de grupos; por defecto 24h (mín 10s en desarrollo). - GROUP_MEMBERS_SYNC_INTERVAL_MS: intervalo de sync de miembros; por defecto 6h (mín 10s en desarrollo). - MAX_MEMBERS_SNAPSHOT_AGE_MS: edad máxima (ms) para considerar "fresca" la snapshot de miembros; por defecto 24h. - GROUP_MEMBERS_ENFORCE: si "true", aplica validación estricta de membresía cuando la snapshot es fresca; por defecto false. - REMINDERS_INCLUDE_UNASSIGNED_FROM_MEMBERSHIP: si "true", añade sección "sin responsable" en recordatorios solo de tus grupos con membresía activa; por defecto false. - RATE_LIMIT_PER_MIN: límite por usuario (tokens/min); por defecto 15. - RATE_LIMIT_BURST: capacidad del bucket; por defecto = RATE_LIMIT_PER_MIN. - Opcionales — cola de respuestas - RQ_MAX_ATTEMPTS: reintentos máximos; por defecto 6. - RQ_BASE_BACKOFF_MS: backoff base en ms; por defecto 5000. - RQ_MAX_BACKOFF_MS: backoff máximo en ms; por defecto 3600000. - Opcionales — migraciones - MIGRATOR_CHECKSUM_STRICT: si "false" desactiva validación estricta de checksum de migraciones; por defecto "true". - MIGRATIONS_LOG_PATH: ruta del fichero de log de migraciones; por defecto data/migrations.log. - Opcionales — métricas y mantenimiento - METRICS_ENABLED: "true"|"false" para habilitar /metrics; por defecto true (desactivado en test). - METRICS_FORMAT: "prom"|"json"; por defecto "prom". - GROUP_MEMBERS_INACTIVE_RETENTION_DAYS: días para purgar miembros inactivos; 180 por defecto; 0 desactiva. - FORCE_SCHEDULERS: "true" para forzar arranque de jobs en NODE_ENV=test. - Entorno - NODE_ENV: production | development | test. Consulta .env.example para un listado comentado con valores de ejemplo. ## Puesta en marcha (local) - bun install - Copia .env.example a .env y ajústalo. - bun run dev (arranca servidor con recarga). - bun test (ejecuta pruebas con SQLite en memoria). ## Despliegue con Docker/CapRover - Crea una app y configura: - Variables de entorno (ver arriba). - Health check: GET /health. - Volumen persistente: mapea /app/data a un volumen (persistencia de SQLite). - Red interna con Evolution API (ideal: no exponer públicamente el webhook). - El worker de la cola arranca con el servidor (en NODE_ENV=test se desactiva). - Plan operativo mínimo (CI/CD, healthcheck y backups): ver docs/CI-CD-PLAN.md (decisiones pendientes marcadas). ## Seguridad y buenas prácticas - Mantén WEBHOOK_URL accesible desde Evolution API preferiblemente en red interna; si se expone, restringe IPs o usa reverse proxy/firewall. - Gestiona secretos (API keys) como variables en el orquestador. - Configura backups periódicos del fichero data/tasks.db (las migraciones hacen VACUUM INTO, pero no sustituyen un backup programado). ## Limitaciones conocidas - Sin orden garantizado por destinatario en la cola. - /metrics básico sin histogramas ni etiquetas; mejoras futuras. - Permisos/roles y validación estricta de pertenencia a grupos no implementados. ## Roadmap - Próximos pasos y estado detallado: ver STATUS.md. ## Testing - Ejecuta la suite con “bun test”. Llama a Evolution API solo fuera de test. ## Contribución - PRs bienvenidas. Añade pruebas, ejecuta “bun test” y describe los cambios. 6) Permisos y pertenencia a grupos - Objetivo: control de quién puede qué, y pertenencia válida. - Implica: roles y/o verificación de pertenencia; posibles migraciones y sincronización de miembros. 7) Historial de tareas (auditoría ligera) - Objetivo: trazabilidad de cambios. - Implica: tabla task_events; eventos en crear/asignar/tomar/soltar/completar; consulta “historial”. 8) Rate limiting (operación segura) — completado - Objetivo: proteger ante abuso o loops. - Implementado: token bucket por usuario con límites configurables (RATE_LIMIT_PER_MIN, RATE_LIMIT_BURST) y aviso con cooldown. 9) Sincronización de miembros (opcional) - Objetivo: conocer miembros activos por grupo para features avanzadas. - Implica: endpoints Evolution API para miembros; cache/migraciones. 10) Métricas y observabilidad - Objetivo: visibilidad con bajo coste. - Implementado: /metrics (Prometheus/JSON) con counters/gauges y /health detallado; pendiente: histogramas/latencias y logging estructurado avanzado. ## 🔑 Key Considerations & Caveats * **WhatsApp ID Normalization:** Crucial for consistently identifying users and groups. Needs careful implementation to handle edge cases. (Utility function exists). * **Response Latency:** Sending responses requires an API call back to Evolution. Ensure the `ResponseQueue` processing is efficient. * **Cola de respuestas:** Persistente en DB; con reintentos (backoff exponencial + jitter), recuperación tras reinicios y limpieza/retención configurables. * **Group Sync:** The current full sync might be slow or rate-limited with many groups. Delta updates are recommended long-term. * **Error Handling:** Failures in command processing or response sending should be logged clearly and potentially reported back to the user. Database operations should use transactions for atomicity (especially task+assignment creation). * **State Management:** The current design is stateless. Complex interactions might require state persistence later. * **Security:** Ensure group/user validation logic is robust once integrated. ## 🧪 Testing ### Running Tests ```bash bun test ``` ### Test Coverage - Database initialization and basic operations (`db.test.ts`). - Webhook validation (basic) (`webhook-manager.test.ts`). - Command parsing (basic structure) (`command.test.ts`). - Environment checks (`server.test.ts`). - Basic error handling (`server.test.ts`). - WhatsApp ID normalization (`whatsapp.test.ts`). - Group sync operations (`group-sync.test.ts`). - Webhook handlers de membresías (alta/baja/cambio de rol) (`group-sync.*.test.ts`). - **Needed:** Tests for `ensureUserExists` integration, `isGroupActive` integration, `CommandService` logic, `ResponseQueue` processing (mocking API), `TaskService` operations. - All 170 unit tests passing. Added unit tests for CommandService (date parsing "hoy/mañana", DM help, dd/MM formatting, default assignment rules) y para RemindersService (daily/weekly, duplicados por día, hora/TZ, “… y X más”) y configuración de recordatorios. ## 🧑‍💻 Contributing 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/implement-user-validation`) 3. Add/update tests for new functionality 4. Ensure tests pass (`bun test`) 5. Submit a pull request ## 📚 Documentation For detailed API documentation and architecture decisions, see the [docs/](docs/) directory (if created). --- ## 📐 Diseño UX acordado (MVP y siguientes iteraciones) Este apartado documenta las decisiones de UX aprobadas para el MVP y su evolución inmediata. Objetivo: mínima fricción, cero ruido en grupos y mensajes compactos. ### Principios - Silencio en grupos: el bot NO publica mensajes en grupos. Cuando alguien usa un comando en un grupo, el bot responde solo por DM al autor, sin dejar mensaje en el grupo. - Homogeneidad: mismos comandos y comportamiento tanto en la comunidad “Casa” como en la del AMPA. - Mensajes compactos: máximo 2–3 líneas, usando emojis y formato WhatsApp (negritas, monoespacio) para legibilidad. - Aprendizaje progresivo: alias cortos y ayuda accesible por DM. ### Comando base y alias - Prefijo admitido: “/t” y “/tarea”. - Subcomandos y sinónimos (aceptar cualquiera, mapear a una acción canónica): - Crear: n, nueva, crear, + - Ver: ver, mostrar, listar, ls - Completar: x, hecho, completar, done - Tomar: tomar, claim - Soltar: soltar, unassign - Ayuda: ayuda, help, ? - Configurar: configurar, config ### Gramática de “crear tarea” - Texto libre: descripción. - Fecha: soportar tokens “hoy” y “mañana” (MVP). Futuro: +2d, +1w, lun/mar/… - Menciones: “@…” y menciones reales del cliente. - Asignación por defecto: - En grupos: si no hay menciones → tarea queda “sin responsable”. - En DM: si no hay menciones → asignada al creador. - Comandos de gestión de asignación: - /t tomar → el usuario se asigna la tarea. - /t soltar → elimina su asignación, devolviendo la tarea a “sin responsable” si no quedan asignados. ### Listados - /t ver grupo → devuelve por DM las pendientes del grupo desde el que se invoca (incluye sección “sin responsable”). - /t ver mis → devuelve por DM las pendientes del usuario agregadas de todos sus grupos. - Listas extensas: mostrar top N (p. ej., 10) y resumen “y X más…”. ### Completar - /t x (alias: /t hecho , /t completar ) - Registro de quién completó. Por ahora no se restringe a asignados (permite fluidez); política configurable en el futuro. - Confirmación solo por DM. ### Ayuda y onboarding - “/t” sin parámetros o “ayuda” → siempre por DM, con guía corta y 2–3 ejemplos. - En grupos: no se escribe nada en el grupo; únicamente el DM al autor. ### Mensajes: plantillas compactas - Confirmación al crear (DM al creador): - 📝 26 _Acta de la reunión_ - 📅 12/09 - 🚫👤 sin responsable (Junta AMPA) — o — 👤 @Juan - DM a asignados: - 📬 Tarea 26 — 📅 12/09 - _Acta de la reunión_ - Grupo: Junta AMPA - Completar: /t x 26 - Listado (enviado por DM): - Junta AMPA - 26) _Acta…_ — 📅 12/09 — 👤 @Juan - 27) _Carteles fiesta_ — 📅 10/09 — 🚫👤 sin responsable - … y 3 más - Completar (feedback por DM): - ✅ 26 completada — _Acta…_ - Gracias, Juan. ### Preferencias (MVP) - Única preferencia: frecuencia de recordatorios por DM: daily | off. - MVP sin web: el usuario escribe “configurar” por DM y el bot le ofrece elegir “diario” u “off”. - Por defecto: off (evitar spam). Futuro: hora y zona horaria configurables; magic link a web de configuración. ### Recordatorios - Resumen diario por DM (si el usuario eligió “diario”): - ⏰ Recordatorio diario — hoy 12/09 - 26) _Acta…_ — 📅 12/09 — Junta AMPA - 31) _Pagar comedor_ — hoy — Casa - 33) _…_ — 📅 15/09 — Casa - Completar: /t x - Un solo DM con secciones por comunidad para evitar múltiples mensajes. ### No objetivos del MVP - No asignar por defecto a “todo el grupo” (evita DMs masivos y responsabilidad difusa). - No canal “Tareas” compartido por defecto (riesgo de ruido). Se considerará en el futuro solo si hay demanda y opt‑in. ### Plan de implementación (iteraciones) - Iteración A — UX base y silencios - Alias de comandos y sinónimos en CommandService. - Respuestas de todos los comandos únicamente por DM (incluido cuando se invocan en grupos). - Mensajes compactos con plantillas. - Soporte de “hoy/mañana”. - Default sin dueño en grupos; asignar al creador en DMs. - Nuevos comandos: tomar y soltar. - Ayuda por DM. - Iteración B — Listados y completar - /t ver grupo, /t ver mis. - /t x con registro de quién completa. - Tests para alias, hoy/mañana, ver y x. - Iteración C — Recordatorios - Preferencia reminder_freq (daily|off) por usuario via “configurar” por DM. - Job diario que envía el resumen (solo “tus tareas” en MVP). - Iteración D — (Opcional) Miembros de grupo - Sincronizar miembros si se necesita incluir “sin responsable” por grupo en recordatorios. ### Cambios técnicos asociados (resumen) - src/services/command.ts - Mapeo de sinónimos a acciones canónicas. - Parser de “hoy/mañana”. - Subcomandos: ver grupo|mis, x, tomar, soltar. - Render de mensajes compactos. - src/server.ts - Detección de contexto grupo vs DM; nunca responder en grupo (solo DM al autor). - src/tasks/service.ts - Permitir tareas sin asignaciones. - Métodos: claimTask(user_id), unassignTask(user_id), completeTask(id, completed_by). - src/services/response-queue.ts - Envío de DMs para ayuda, confirmaciones, listados y recordatorios. - (Futuro) Preferencias - Tabla user_preferences(user_id PK, reminder_freq TEXT, updated_at). - “configurar” por DM en MVP; más adelante, web con magic link (user_tokens). ### Testing sugerido - Alias de comandos y “/t” sin parámetros → DM de ayuda. - Crear en grupo sin menciones → sin responsable; no hay mensaje en el grupo; DM al autor. - Crear en DM sin menciones → asignada al creador. - “hoy/mañana” en fechas. - ver grupo y ver mis → DM con paginación/resumen. - completar, tomar y soltar → reglas y feedback por DM.