WhatsApp chatbot that works with an Evolution API server to provide task management to a WhatsApp Community.
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.
 
 
 
 
 
brobert dd909c2917 añade doc de envs a gitignore 1 month ago
data feat: mover base de datos a carpeta data 2 months ago
docs docs: añade plan mínimo de CI/CD y actualiza estado/README 2 months ago
src fix: ignorar mensajes de grupos inactivos en modo test 2 months ago
tests/unit refactor: quitar cursivas de descripciones y añadir saltos entre grupos 2 months ago
.env.example feat: agregar verificación de membresía y filtrado por snapshot 2 months ago
.gitignore añade doc de envs a gitignore 1 month ago
Dockerfile añade sqlite3 a la lista de lo que instala la imagen para poder trastear la base de datos 2 months ago
README.md docs: añade plan mínimo de CI/CD y actualiza estado/README 2 months ago
STATUS.md (no commit message provided) 2 months ago
bun.lock añade bun lock y package.json 7 months ago
captain-definition feat: add CapRover deployment files and env var validation 7 months ago
index.ts fix: Pasa instancia de db correctamente a initializeDatabase 4 months ago
package.json añade bun lock y package.json 7 months ago
startup.sh sleep 1 segundo 1 month ago
tsconfig.json Initial commit 7 months ago

README.md

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.
  1. 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.
  1. Historial de tareas (auditoría ligera)
  • Objetivo: trazabilidad de cambios.
  • Implica: tabla task_events; eventos en crear/asignar/tomar/soltar/completar; consulta “historial”.
  1. 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.
  1. Sincronización de miembros (opcional)
  • Objetivo: conocer miembros activos por grupo para features avanzadas.
  • Implica: endpoints Evolution API para miembros; cache/migraciones.
  1. 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

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/ 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 23 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 23 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
        1. Acta…📅 12/09 — 👤 @Juan
        1. 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
        1. Acta…📅 12/09 — Junta AMPA
        1. Pagar comedor — hoy — Casa
        1. 📅 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 optin.

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.