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.
 
 
 
 
 
borja 714c7a6c4e feat: habilita /t y /tarea con parsing de fechas y respuestas compactas
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
2 months ago
data feat: mover base de datos a carpeta data 2 months ago
docs feat: habilita /t y /tarea con parsing de fechas y respuestas compactas 2 months ago
src feat: habilita /t y /tarea con parsing de fechas y respuestas compactas 2 months ago
tests/unit fix: añadir metadata a response_queue y unificar ack en CommandService 2 months ago
.env.example docs: actualizar .env.example con variables de Evolution, bot y webhook 2 months ago
.gitignore feat: mover base de datos a carpeta data 2 months 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: documentar plan UX MVP e iteraciones en README 2 months ago
STATUS.md docs: actualizar README.md y STATUS.md y eliminar fallo de test 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 añado 100 segundos de delay en startup porque si no no me da tiempo a trastear, quiero ver si encuentro la comunidad adecuada en la db 4 months ago
tsconfig.json Initial commit 7 months ago

README.md

Task WhatsApp Chatbot

A WhatsApp chatbot for task management, designed to work with Evolution API in a secure internal network environment.

📌 Overview

This service provides a WhatsApp interface for task management within WhatsApp groups. It:

  • Listens for /tarea commands in WhatsApp groups via Evolution API webhooks.
  • Stores tasks, users, and groups in a SQLite database.
  • Synchronizes group information periodically from the Evolution API.
  • Manages user permissions and group membership (partially implemented).
  • Integrates with Evolution API for WhatsApp connectivity.
  • Sends direct messages to acknowledge the creator and notify each assignee; includes mentions with phone numbers for quick action.
  • Optional: group notification on task creation controlled by NOTIFY_GROUP_ON_CREATE (default false), including proper mentions for visibility.

🔐 Security Model

  • Internal Networking: The webhook should ideally only accept connections from Evolution API via internal Docker networking (configuration dependent).
  • Environment Variables: Sensitive configuration (API keys, URLs) is managed through environment variables.
  • Group Restrictions: Designed to operate within pre-approved WhatsApp groups (validation logic pending integration).
  • Input Validation: Basic validation exists for webhook structure; needs enhancement for command arguments and user/group IDs.

🧱 Architecture

graph TD
    A[Webhook Received] --> B{Valid Payload?}
    B -->|No| C[Ignore]
    B -->|Yes| D{Normalize IDs & Check Group Active?}
    D -->|No| C[Ignore/Log]
    D -->|Yes| E[Ensure User Exists in DB]
    E --> G{/tarea Command?}
    G -->|No| C
    G -->|Yes| J[Process Command Logic]
    J -- Success/Error --> K[Queue Response(s)]
    K --> L[Process Queue & Send Response via API]

    subgraph Database Interaction
        E --> DB[(SQLite DB)]
        J --> DB
    end
    subgraph Evolution API
        L --> EA((Evolution API))
        EA -- Webhook --> A
    end

(Diagram updated for planned flow)

Decisiones de diseño de la cola de respuestas (MVP)

  1. Persistencia: 100% persistente (tabla única).
  2. Worker: continuo en background.
  3. Locking: status=processing (sin lease).
  4. Orden: sin orden estricto por chat.
  5. Reintentos: sin reintentos en MVP.
  6. Errores: 4xx = fallo definitivo; 5xx/red = fallo (sin reintentos).
  7. Idempotencia: no.
  8. Esquema DB: tabla única response_queue.
  9. Transporte: envío desde ResponseQueue (fetch directo a Evolution API).
  10. Concurrencia: N workers globales.
  11. Integración: encolar y worker continuo (arranca con el servidor).
  12. Configuración: defaults fijos (sin nuevas env vars por ahora).
  13. Limpieza: sin limpieza/retención de historiales (por ahora).
  14. Seguridad: no enviar al número del bot (CHATBOT_PHONE_NUMBER).
  15. Pruebas: unitarias de cola con mocks de fetch.

Arquitectura de la cola persistente (MVP)

  • Estados: queued | processing | sent | failed.
  • Campos actuales por mensaje: id (PK), recipient, message, status, attempts (0), last_error (nullable), metadata (nullable), created_at, updated_at.
  • Índices recomendados: (status, created_at) para seleccionar pendientes rápidamente.
  • Sin orden estricto por chat; el envío puede intercalarse entre destinatarios.
  • Concurrencia: N workers globales operando en bucle, cada uno toma mensajes en estado queued y los marca processing. Estado: la tabla response_queue ya está creada e incluida en los tests de DB.

Flujo del worker continuo (MVP)

  • Se inicia al arrancar el servidor (desactivado en tests).
  • Ciclo: seleccionar hasta un pequeño batch de mensajes queued, marcar processing, enviar a Evolution API, marcar sent o failed según respuesta.
  • Sin reintentos; logs mínimos y no sensibles.

Limitaciones explícitas del MVP

  • Sin backoff ni reintentos.
  • Sin orden garantizado por chat.
  • Sin idempotencia ni limpieza automática.
  • Sin lease; en caso de crash podrían quedar mensajes en processing que requerirán recuperación manual en una iteración futura.

Plan incremental posterior

  • Añadir reintentos con backoff exponencial y jitter.
  • Garantizar orden por chat (serialización por recipient).
  • Introducir lease (lease_until) para tolerancia a fallos y recuperación.
  • Limpieza/retención y métricas/observabilidad.
  • Opcional: idempotencia e índices adicionales.

Current Status (as of latest commit)

Implemented

  • Webhook server setup (src/server.ts) receiving Evolution API events.
  • Database schema definition and initialization (src/db.ts), including lightweight migration to add response_queue.metadata.
  • Group synchronization service (src/services/group-sync.ts) to fetch/store/cache groups. Includes active group caching and isGroupActive checks in server.
  • Webhook registration and verification with Evolution API (src/services/webhook-manager.ts).
  • WhatsApp ID normalization utility (src/utils/whatsapp.ts).
  • User creation/update function (src/db.ts::ensureUserExists) integrated into the main flow.
  • Command handling for /tarea nueva end-to-end (src/services/command.ts):
    • Parses description and selects the last future date (YYYY-MM-DD) as due date.
    • Extracts assignees from explicit mentions and plain-text @tokens; defaults to creator only when none found.
    • Cleans description to remove @mentions tokens.
    • Persists task and assignments atomically via TaskService.
    • Builds response with assignment list and includes Evolution API “mentioned” JIDs via ResponseQueue.
  • Task persistence service (src/tasks/service.ts) with created_by and assignment inserts in a transaction; supports DB injection for tests.
  • Response queue persistente con workers en background y envío vía Evolution API (src/services/response-queue.ts), persistiendo metadata { mentioned: [...] } y enviándola como mentioned en el payload.
  • Contacts service and friendly names: ContactsService resolves display names via webhooks (CONTACTS_UPDATE/CHATS_UPDATE) and Evolution API fallback; used to render names in outgoing texts (falls back to numbers). Skips network calls under NODE_ENV=test for fast and isolated unit tests.
  • Notification UX: Always send DM acknowledgment to the creator in a single line (format: Tarea creada: "description"), DM to each assignee (excluding the creator); optional group notification controlled by NOTIFY_GROUP_ON_CREATE (default false) with proper mentions.
  • Environment variable validation (src/server.ts, src/services/webhook-manager.ts).
  • Health check endpoint (/health).
  • Database isolation in unit tests: Using in-memory instances to avoid conflicts.

Incomplete / Missing Core Functionality

  • Additional commands: /tarea mostrar (list) y /tarea completar.
  • ResponseQueue reliability: reintentos con backoff, recuperación de processing, métricas y limpieza/retención.
  • ContactsService improvements (optional): refine caching policy and endpoints; basic friendly-name resolution is already implemented and used in outgoing texts.
  • Database migrations system (beyond current lightweight on-boot checks).
  • More robust error handling and observability around API/DB operations.

Known Issues

  • Mentions UX: In group chats, mentions are highlighted and each client resolves the chip to their local contact name; we include friendly names in text when available. In direct messages, WhatsApp does not render mention chips for third parties, so we include the number as @digits for quick action; no per-recipient name rewriting occurs.
  • Test suite: currently 1 failing test — “Database > Table Schemas > response_queue table should have required columns”.

🛠️ Setup

Environment Variables

(Ensure these are set correctly)

# Evolution API Connection
EVOLUTION_API_URL=http://evolution-api:3000 # Or your API URL
EVOLUTION_API_KEY=your-api-key
EVOLUTION_API_INSTANCE=main # Your instance name

# WhatsApp Specific
WHATSAPP_COMMUNITY_ID=your-community-id # ID of the main community to sync groups from
CHATBOT_PHONE_NUMBER=1234567890 # Bot's normalized phone number (e.g., for assigning tasks)

# Webhook Configuration
WEBHOOK_URL=http://your-service-internal-url:3007 # URL Evolution API calls *back* to this service
PORT=3007 # Port this service listens on

# Runtime Environment
NODE_ENV=production # Or development

# Optional
# GROUP_SYNC_INTERVAL_MS=3600000 # Sync interval in ms (default: 24h)
# NOTIFY_GROUP_ON_CREATE=false # If 'true', also post a brief summary with mentions to the group

Development Setup

# Install dependencies
bun install

# Copy .env.example to .env and fill in values
cp .env.example .env

# Start development server (watches for changes)
bun run dev

# Run tests
bun test

📅 Roadmap & Priorities (Updated Plan)

Phase 1: User & Group Foundation (Highest Priority - In Progress)

  • Create WhatsApp ID Normalization Utility: (src/utils/whatsapp.ts) Handle different ID formats.
  • Implement ensureUserExists: (src/db.ts) Add users to DB on first interaction.
  • Implement isGroupActive Check: (src/services/group-sync.ts, src/server.ts) Cache exists in group-sync.ts. Needs integration into src/server.ts.
  • Integrate Validation in Server: (src/server.ts) Use normalization, ensureUserExists, and active group check before processing commands.
  • Implement DB isolation in tests: (tests/unit/services/group-sync.test.ts) Use in-memory instances to avoid conflicts.

Phase 2: Refinar /tarea nueva (Alta prioridad)

  • Completar TaskService.createTask con created_by y asignaciones (incluyendo ensureUserExists para asignados) y transacción atómica.
  • Mejorar CommandService para parsear menciones y devolver el id de la tarea creada y resumen de asignados.

Phase 3: Comandos adicionales y refinamientos (Alta prioridad)

  • Implementar /tarea mostrar [group|mine] para listar pendientes.
  • Implementar /tarea completar <task_id> con validaciones básicas.
  • Soportar mensajes de texto extendido y captions de media (además de conversation).

Phase 4: Fiabilidad de la cola y observabilidad (Media)

  • Añadir reintentos con backoff exponencial y jitter.
  • Recuperar ítems en estado processing tras reinicios (lease o expiración y requeue).
  • Métricas y logging mejorado (contadores de enviados/fallidos, tiempos).
  • Limpieza/retención de historiales.

Phase 5: Advanced Features (Low Priority)

  • Add task reminders system.
  • Implement user permissions system.
  • Add rate limiting.
  • Create task history tracking.

🔑 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; pendiente añadir reintentos/backoff y limpieza/retención.
  • 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).
  • Needed: Tests for ensureUserExists integration, isGroupActive integration, CommandService logic, ResponseQueue processing (mocking API), TaskService operations.
  • All unit tests passing.

🧑‍💻 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 dueño”.
    • 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 dueño” si no quedan asignados.

Listados

  • /t ver grupo → devuelve por DM las pendientes del grupo desde el que se invoca (incluye sección “sin dueño”).
  • /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
    • 📅 2025-09-12
    • 👥 sin dueño (Junta AMPA) — o — 👤 @Juan
  • DM a asignados:
    • 🔔 Tarea 26 — 📅 2025-09-12
    • 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 dueño
      • … 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”):
    • Buenos días, Ana — hoy tienes 3 tareas:
        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 dueño” 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 dueño; 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.