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.
|
|
4 weeks ago | |
|---|---|---|
| data | 2 months ago | |
| docs | 4 weeks ago | |
| src | 4 weeks ago | |
| tests | 4 weeks ago | |
| .env.example | 4 weeks ago | |
| .gitignore | 1 month ago | |
| Dockerfile | 2 months ago | |
| README.old.md | 4 weeks ago | |
| STATUS.md | 4 weeks ago | |
| bun.lock | 7 months ago | |
| captain-definition | 7 months ago | |
| index.ts | 4 months ago | |
| package.json | 7 months ago | |
| startup.sh | 1 month ago | |
| tsconfig.json | 7 months ago | |
README.old.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.
- 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.
- Historial de tareas (auditoría ligera)
- Objetivo: trazabilidad de cambios.
- Implica: tabla task_events; eventos en crear/asignar/tomar/soltar/completar; consulta “historial”.
- 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.
- Sincronización de miembros (opcional)
- Objetivo: conocer miembros activos por grupo para features avanzadas.
- Implica: endpoints Evolution API para miembros; cache/migraciones.
- 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
ResponseQueueprocessing 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
ensureUserExistsintegration,isGroupActiveintegration,CommandServicelogic,ResponseQueueprocessing (mocking API),TaskServiceoperations. - 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
- Fork the repository
- Create a feature branch (
git checkout -b feature/implement-user-validation) - Add/update tests for new functionality
- Ensure tests pass (
bun test) - 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 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
-
- Acta… — 📅 12/09 — 👤 @Juan
-
- Carteles fiesta — 📅 10/09 — 🚫👤 sin responsable
- … y 3 más
-
- Junta AMPA
- 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
-
- Acta… — 📅 12/09 — Junta AMPA
-
- Pagar comedor — hoy — Casa
-
- … — 📅 15/09 — Casa
-
- Completar: /t x
- ⏰ Recordatorio diario — hoy 12/09
- 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.