elevenlabs-webhook-nodejs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +27 -0
- package/.dockerignore +6 -0
- package/.env.example +43 -0
- package/BEFORE-PRODUCTION.md +32 -0
- package/Dockerfile +23 -0
- package/SYSTEM_OVERVIEW.md +942 -0
- package/SYSTEM_STATUS.md +332 -0
- package/backup_script/main.py +146 -0
- package/baileys/.dockerignore +7 -0
- package/baileys/Dockerfile +13 -0
- package/baileys/README.md +412 -0
- package/baileys/index.js +499 -0
- package/baileys/package-lock.json +2532 -0
- package/baileys/package.json +25 -0
- package/baileys/server.js +96 -0
- package/baileys/src/config.js +55 -0
- package/baileys/src/middleware/api-key.js +16 -0
- package/baileys/src/routes/accounts.js +51 -0
- package/baileys/src/routes/chats.js +103 -0
- package/baileys/src/routes/webhooks.js +34 -0
- package/baileys/src/services/account-store.js +259 -0
- package/baileys/src/services/webhook-dispatcher.js +161 -0
- package/baileys/src/services/worker-manager.js +597 -0
- package/baileys/src/utils/jid.js +79 -0
- package/baileys/src/utils/logger.js +16 -0
- package/baileys/src/utils/use-mongodb-auth-state.js +122 -0
- package/baileys/worker.js +721 -0
- package/dist/app.d.ts +1 -0
- package/dist/app.js +84 -0
- package/dist/app.js.map +1 -0
- package/dist/config/agentPrompts.json +19 -0
- package/dist/config/database.d.ts +1 -0
- package/dist/config/database.js +26 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/env.d.ts +41 -0
- package/dist/config/env.js +81 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +73 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controllers/webhook.controller.d.ts +10 -0
- package/dist/controllers/webhook.controller.js +128 -0
- package/dist/controllers/webhook.controller.js.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.js +13 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/hooks/webhookValidator.d.ts +2 -0
- package/dist/hooks/webhookValidator.js +47 -0
- package/dist/hooks/webhookValidator.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/001_session-architecture.d.ts +3 -0
- package/dist/migrations/001_session-architecture.js +119 -0
- package/dist/migrations/001_session-architecture.js.map +1 -0
- package/dist/migrations/002_agent-ref.d.ts +3 -0
- package/dist/migrations/002_agent-ref.js +55 -0
- package/dist/migrations/002_agent-ref.js.map +1 -0
- package/dist/migrations/003_shift-schedule.d.ts +3 -0
- package/dist/migrations/003_shift-schedule.js +48 -0
- package/dist/migrations/003_shift-schedule.js.map +1 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.d.ts +3 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js +27 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js.map +1 -0
- package/dist/migrations/005_composite-baileys-chat-ids.d.ts +3 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js +47 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js.map +1 -0
- package/dist/migrations/migration.model.d.ts +18 -0
- package/dist/migrations/migration.model.js +45 -0
- package/dist/migrations/migration.model.js.map +1 -0
- package/dist/migrations/migration.routes.d.ts +2 -0
- package/dist/migrations/migration.routes.js +37 -0
- package/dist/migrations/migration.routes.js.map +1 -0
- package/dist/migrations/migration.runner.d.ts +19 -0
- package/dist/migrations/migration.runner.js +74 -0
- package/dist/migrations/migration.runner.js.map +1 -0
- package/dist/models/ConversationClaim.d.ts +13 -0
- package/dist/models/ConversationClaim.js +44 -0
- package/dist/models/ConversationClaim.js.map +1 -0
- package/dist/models/ConversationEvaluation.d.ts +23 -0
- package/dist/models/ConversationEvaluation.js +92 -0
- package/dist/models/ConversationEvaluation.js.map +1 -0
- package/dist/models/Summary.d.ts +37 -0
- package/dist/models/Summary.js +78 -0
- package/dist/models/Summary.js.map +1 -0
- package/dist/models/Transcription.d.ts +34 -0
- package/dist/models/Transcription.js +71 -0
- package/dist/models/Transcription.js.map +1 -0
- package/dist/models/WhatsAppRecipient.d.ts +23 -0
- package/dist/models/WhatsAppRecipient.js +53 -0
- package/dist/models/WhatsAppRecipient.js.map +1 -0
- package/dist/modules/admin/admin.routes.d.ts +2 -0
- package/dist/modules/admin/admin.routes.js +1966 -0
- package/dist/modules/admin/admin.routes.js.map +1 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js +158 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js.map +1 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js +204 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js.map +1 -0
- package/dist/modules/agents/agent.model.d.ts +38 -0
- package/dist/modules/agents/agent.model.js +92 -0
- package/dist/modules/agents/agent.model.js.map +1 -0
- package/dist/modules/agents/agent.routes.d.ts +2 -0
- package/dist/modules/agents/agent.routes.js +61 -0
- package/dist/modules/agents/agent.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.model.d.ts +76 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js +118 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.d.ts +2 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js +202 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.service.d.ts +53 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js +827 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js.map +1 -0
- package/dist/modules/auth/auth.model.d.ts +17 -0
- package/dist/modules/auth/auth.model.js +64 -0
- package/dist/modules/auth/auth.model.js.map +1 -0
- package/dist/modules/auth/auth.routes.d.ts +2 -0
- package/dist/modules/auth/auth.routes.js +202 -0
- package/dist/modules/auth/auth.routes.js.map +1 -0
- package/dist/modules/auth/auth.service.d.ts +28 -0
- package/dist/modules/auth/auth.service.js +183 -0
- package/dist/modules/auth/auth.service.js.map +1 -0
- package/dist/modules/auth/refresh-token.model.d.ts +13 -0
- package/dist/modules/auth/refresh-token.model.js +52 -0
- package/dist/modules/auth/refresh-token.model.js.map +1 -0
- package/dist/modules/billing/billing-alert.model.d.ts +16 -0
- package/dist/modules/billing/billing-alert.model.js +47 -0
- package/dist/modules/billing/billing-alert.model.js.map +1 -0
- package/dist/modules/billing/billing-period-snapshot.model.d.ts +35 -0
- package/dist/modules/billing/billing-period-snapshot.model.js +68 -0
- package/dist/modules/billing/billing-period-snapshot.model.js.map +1 -0
- package/dist/modules/billing/billing.model.d.ts +18 -0
- package/dist/modules/billing/billing.model.js +62 -0
- package/dist/modules/billing/billing.model.js.map +1 -0
- package/dist/modules/billing/billing.routes.d.ts +2 -0
- package/dist/modules/billing/billing.routes.js +63 -0
- package/dist/modules/billing/billing.routes.js.map +1 -0
- package/dist/modules/billing/billing.service.d.ts +69 -0
- package/dist/modules/billing/billing.service.js +498 -0
- package/dist/modules/billing/billing.service.js.map +1 -0
- package/dist/modules/billing/payment.model.d.ts +24 -0
- package/dist/modules/billing/payment.model.js +57 -0
- package/dist/modules/billing/payment.model.js.map +1 -0
- package/dist/modules/calls/call.model.d.ts +41 -0
- package/dist/modules/calls/call.model.js +97 -0
- package/dist/modules/calls/call.model.js.map +1 -0
- package/dist/modules/calls/call.routes.d.ts +2 -0
- package/dist/modules/calls/call.routes.js +103 -0
- package/dist/modules/calls/call.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.model.d.ts +45 -0
- package/dist/modules/campaigns/campaign.model.js +98 -0
- package/dist/modules/campaigns/campaign.model.js.map +1 -0
- package/dist/modules/campaigns/campaign.routes.d.ts +2 -0
- package/dist/modules/campaigns/campaign.routes.js +323 -0
- package/dist/modules/campaigns/campaign.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.service.d.ts +11 -0
- package/dist/modules/campaigns/campaign.service.js +86 -0
- package/dist/modules/campaigns/campaign.service.js.map +1 -0
- package/dist/modules/google-calendar/google-calendar.routes.d.ts +2 -0
- package/dist/modules/google-calendar/google-calendar.routes.js +32 -0
- package/dist/modules/google-calendar/google-calendar.routes.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call-config.model.d.ts +20 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js +68 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call.routes.d.ts +2 -0
- package/dist/modules/inbound-call/inbound-call.routes.js +243 -0
- package/dist/modules/inbound-call/inbound-call.routes.js.map +1 -0
- package/dist/modules/leads/lead.model.d.ts +24 -0
- package/dist/modules/leads/lead.model.js +54 -0
- package/dist/modules/leads/lead.model.js.map +1 -0
- package/dist/modules/leads/lead.routes.d.ts +2 -0
- package/dist/modules/leads/lead.routes.js +201 -0
- package/dist/modules/leads/lead.routes.js.map +1 -0
- package/dist/modules/plans/plan.model.d.ts +25 -0
- package/dist/modules/plans/plan.model.js +59 -0
- package/dist/modules/plans/plan.model.js.map +1 -0
- package/dist/modules/surveys/survey.model.d.ts +30 -0
- package/dist/modules/surveys/survey.model.js +75 -0
- package/dist/modules/surveys/survey.model.js.map +1 -0
- package/dist/modules/surveys/survey.routes.d.ts +2 -0
- package/dist/modules/surveys/survey.routes.js +153 -0
- package/dist/modules/surveys/survey.routes.js.map +1 -0
- package/dist/modules/tenants/tenant.model.d.ts +86 -0
- package/dist/modules/tenants/tenant.model.js +127 -0
- package/dist/modules/tenants/tenant.model.js.map +1 -0
- package/dist/modules/tenants/tenant.routes.d.ts +2 -0
- package/dist/modules/tenants/tenant.routes.js +65 -0
- package/dist/modules/tenants/tenant.routes.js.map +1 -0
- package/dist/modules/users/user.routes.d.ts +2 -0
- package/dist/modules/users/user.routes.js +106 -0
- package/dist/modules/users/user.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.d.ts +20 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js +85 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.d.ts +11 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js +360 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.routes.d.ts +2 -0
- package/dist/modules/webhooks/elevenlabs.routes.js +34 -0
- package/dist/modules/webhooks/elevenlabs.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.service.d.ts +6 -0
- package/dist/modules/webhooks/elevenlabs.service.js +512 -0
- package/dist/modules/webhooks/elevenlabs.service.js.map +1 -0
- package/dist/modules/webhooks/unipile.routes.d.ts +2 -0
- package/dist/modules/webhooks/unipile.routes.js +780 -0
- package/dist/modules/webhooks/unipile.routes.js.map +1 -0
- package/dist/modules/whatsapp/appointment.model.d.ts +27 -0
- package/dist/modules/whatsapp/appointment.model.js +58 -0
- package/dist/modules/whatsapp/appointment.model.js.map +1 -0
- package/dist/modules/whatsapp/operator-request.model.d.ts +29 -0
- package/dist/modules/whatsapp/operator-request.model.js +65 -0
- package/dist/modules/whatsapp/operator-request.model.js.map +1 -0
- package/dist/modules/whatsapp/stt-usage.model.d.ts +16 -0
- package/dist/modules/whatsapp/stt-usage.model.js +53 -0
- package/dist/modules/whatsapp/stt-usage.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js +55 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js +54 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-message.model.d.ts +30 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js +52 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-session.model.d.ts +33 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js +65 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp.routes.d.ts +2 -0
- package/dist/modules/whatsapp/whatsapp.routes.js +1237 -0
- package/dist/modules/whatsapp/whatsapp.routes.js.map +1 -0
- package/dist/plugins/cors.d.ts +3 -0
- package/dist/plugins/cors.js +11 -0
- package/dist/plugins/cors.js.map +1 -0
- package/dist/plugins/jwt.d.ts +3 -0
- package/dist/plugins/jwt.js +22 -0
- package/dist/plugins/jwt.js.map +1 -0
- package/dist/plugins/rawBody.d.ts +3 -0
- package/dist/plugins/rawBody.js +16 -0
- package/dist/plugins/rawBody.js.map +1 -0
- package/dist/plugins/rbac.d.ts +5 -0
- package/dist/plugins/rbac.js +29 -0
- package/dist/plugins/rbac.js.map +1 -0
- package/dist/routes/admin.routes.d.ts +2 -0
- package/dist/routes/admin.routes.js +169 -0
- package/dist/routes/admin.routes.js.map +1 -0
- package/dist/routes/health.routes.d.ts +2 -0
- package/dist/routes/health.routes.js +16 -0
- package/dist/routes/health.routes.js.map +1 -0
- package/dist/routes/webhook.routes.d.ts +2 -0
- package/dist/routes/webhook.routes.js +17 -0
- package/dist/routes/webhook.routes.js.map +1 -0
- package/dist/services/ai/base.ai.d.ts +19 -0
- package/dist/services/ai/base.ai.js +120 -0
- package/dist/services/ai/base.ai.js.map +1 -0
- package/dist/services/ai/gemini.service.d.ts +11 -0
- package/dist/services/ai/gemini.service.js +43 -0
- package/dist/services/ai/gemini.service.js.map +1 -0
- package/dist/services/ai/index.d.ts +2 -0
- package/dist/services/ai/index.js +26 -0
- package/dist/services/ai/index.js.map +1 -0
- package/dist/services/ai/openai.service.d.ts +11 -0
- package/dist/services/ai/openai.service.js +50 -0
- package/dist/services/ai/openai.service.js.map +1 -0
- package/dist/services/elevenlabs.service.d.ts +52 -0
- package/dist/services/elevenlabs.service.js +447 -0
- package/dist/services/elevenlabs.service.js.map +1 -0
- package/dist/services/google-calendar.service.d.ts +60 -0
- package/dist/services/google-calendar.service.js +494 -0
- package/dist/services/google-calendar.service.js.map +1 -0
- package/dist/services/inbound-call-schedule.service.d.ts +11 -0
- package/dist/services/inbound-call-schedule.service.js +162 -0
- package/dist/services/inbound-call-schedule.service.js.map +1 -0
- package/dist/services/netgsm.service.d.ts +41 -0
- package/dist/services/netgsm.service.js +89 -0
- package/dist/services/netgsm.service.js.map +1 -0
- package/dist/services/unipile.service.d.ts +41 -0
- package/dist/services/unipile.service.js +149 -0
- package/dist/services/unipile.service.js.map +1 -0
- package/dist/services/whatsapp-agent.service.d.ts +139 -0
- package/dist/services/whatsapp-agent.service.js +2055 -0
- package/dist/services/whatsapp-agent.service.js.map +1 -0
- package/dist/services/whatsapp.service.d.ts +26 -0
- package/dist/services/whatsapp.service.js +206 -0
- package/dist/services/whatsapp.service.js.map +1 -0
- package/dist/templates/index.d.ts +39 -0
- package/dist/templates/index.js +35 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/receptionist.d.ts +2 -0
- package/dist/templates/receptionist.js +39 -0
- package/dist/templates/receptionist.js.map +1 -0
- package/dist/templates/survey.d.ts +2 -0
- package/dist/templates/survey.js +41 -0
- package/dist/templates/survey.js.map +1 -0
- package/dist/types/index.d.ts +173 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.js +105 -0
- package/dist/utils/logger.js.map +1 -0
- package/docker-compose.nestjs.yml +89 -0
- package/docker-compose.yml +78 -0
- package/docs/AI_AGENT_ENHANCEMENT_PLAN.md +164 -0
- package/docs/API.md +1193 -0
- package/docs/API_ENDPOINTS.md +344 -0
- package/docs/ARCHITECTURE.md +305 -0
- package/docs/AUTH_API.md +252 -0
- package/docs/BILLING_SMS_ALERTS.md +94 -0
- package/docs/CHAT_ASSIGNMENT_SYSTEM.md +118 -0
- package/docs/CLIENT_TOOLS_AND_FEATURES.md +337 -0
- package/docs/ELEVENLABS_WEBHOOK_TOOLS.md +644 -0
- package/docs/FRONTEND_CHECKLIST.md +227 -0
- package/docs/IMPLEMENTATION_STATUS.md +470 -0
- package/docs/MIGRATION_GUIDE.md +96 -0
- package/docs/MISSINGS_REPORT.md +507 -0
- package/docs/NESTJS_MIGRATION_REFERENCE.md +5136 -0
- package/docs/PROJECT_DESCRIPTION.md +1038 -0
- package/docs/SCALING.md +148 -0
- package/docs/SESSION_SUMMARY_2026_03_17.md +135 -0
- package/docs/WHATSAPP_AGENT.md +1086 -0
- package/docs/architecture/00-SYSTEM-OVERVIEW.md +318 -0
- package/docs/architecture/01-DATABASE-SCHEMA.md +2564 -0
- package/docs/architecture/02-AUTHENTICATION.md +1040 -0
- package/docs/architecture/03-MULTI-CLINIC.md +742 -0
- package/docs/architecture/04-WHATSAPP-AGENT.md +608 -0
- package/docs/architecture/05-OPERATOR-WORKFLOW.md +444 -0
- package/docs/architecture/06-BAILEYS-MICROSERVICE.md +616 -0
- package/docs/architecture/07-APPOINTMENTS.md +849 -0
- package/docs/architecture/08-VOICE-CALLS.md +470 -0
- package/docs/architecture/09-OUTBOUND-CAMPAIGNS.md +542 -0
- package/docs/architecture/10-CLIENT-TOOLS.md +665 -0
- package/docs/architecture/11-BILLING.md +458 -0
- package/docs/architecture/12-SECURITY.md +216 -0
- package/docs/architecture/13-LOGGING-AUDIT.md +549 -0
- package/docs/architecture/14-META-BUSINESS-API.md +454 -0
- package/docs/architecture/15-AI-MODULE.md +479 -0
- package/docs/architecture/16-BACKGROUND-JOBS.md +469 -0
- package/docs/architecture/17-REALTIME-LIVECHAT.md +447 -0
- package/docs/architecture/18-FILE-STORAGE.md +410 -0
- package/docs/architecture/19-PATIENTS.md +1034 -0
- package/docs/architecture/20-TREATMENTS-AND-PLANS.md +774 -0
- package/docs/architecture/21-BEFORE-AFTER-PHOTOS.md +519 -0
- package/docs/database.md +456 -0
- package/docs/ornek-randevu-onay.csv +3 -0
- package/ecosystem.config.js +16 -0
- package/elevenlabs-convai-api-reference.md +1171 -0
- package/frontend/.dockerignore +2 -0
- package/frontend/Dockerfile +24 -0
- package/frontend/README.md +75 -0
- package/frontend/components.json +25 -0
- package/frontend/eslint.config.js +23 -0
- package/frontend/index.html +13 -0
- package/frontend/nginx.conf +37 -0
- package/frontend/package-lock.json +8709 -0
- package/frontend/package.json +71 -0
- package/frontend/public/favicon.svg +1 -0
- package/frontend/public/icons.svg +24 -0
- package/frontend/src/App.tsx +125 -0
- package/frontend/src/components/error-boundary.tsx +50 -0
- package/frontend/src/components/shared/activity-timeline.tsx +66 -0
- package/frontend/src/components/shared/appointment-calendar.css +80 -0
- package/frontend/src/components/shared/appointment-calendar.tsx +245 -0
- package/frontend/src/components/shared/chat-bubble.tsx +72 -0
- package/frontend/src/components/shared/combobox.tsx +119 -0
- package/frontend/src/components/shared/confirm-dialog.tsx +57 -0
- package/frontend/src/components/shared/data-table-pagination.tsx +97 -0
- package/frontend/src/components/shared/data-table-toolbar.tsx +39 -0
- package/frontend/src/components/shared/empty-state.tsx +27 -0
- package/frontend/src/components/shared/file-upload.tsx +140 -0
- package/frontend/src/components/shared/index.ts +20 -0
- package/frontend/src/components/shared/language-switcher.tsx +29 -0
- package/frontend/src/components/shared/notification-dropdown.tsx +115 -0
- package/frontend/src/components/shared/page-header.tsx +23 -0
- package/frontend/src/components/shared/stat-card.tsx +37 -0
- package/frontend/src/components/shared/status-badge.tsx +70 -0
- package/frontend/src/components/shared/status-dot.tsx +43 -0
- package/frontend/src/components/ui/alert-dialog.tsx +187 -0
- package/frontend/src/components/ui/alert.tsx +76 -0
- package/frontend/src/components/ui/avatar.tsx +109 -0
- package/frontend/src/components/ui/badge.tsx +52 -0
- package/frontend/src/components/ui/breadcrumb.tsx +125 -0
- package/frontend/src/components/ui/button.tsx +60 -0
- package/frontend/src/components/ui/calendar.tsx +219 -0
- package/frontend/src/components/ui/card.tsx +103 -0
- package/frontend/src/components/ui/chart.tsx +371 -0
- package/frontend/src/components/ui/checkbox.tsx +29 -0
- package/frontend/src/components/ui/collapsible.tsx +19 -0
- package/frontend/src/components/ui/command.tsx +194 -0
- package/frontend/src/components/ui/dialog.tsx +158 -0
- package/frontend/src/components/ui/dropdown-menu.tsx +268 -0
- package/frontend/src/components/ui/input-group.tsx +156 -0
- package/frontend/src/components/ui/input.tsx +20 -0
- package/frontend/src/components/ui/label.tsx +20 -0
- package/frontend/src/components/ui/pagination.tsx +130 -0
- package/frontend/src/components/ui/popover.tsx +90 -0
- package/frontend/src/components/ui/progress.tsx +83 -0
- package/frontend/src/components/ui/radio-group.tsx +36 -0
- package/frontend/src/components/ui/scroll-area.tsx +54 -0
- package/frontend/src/components/ui/select.tsx +199 -0
- package/frontend/src/components/ui/separator.tsx +23 -0
- package/frontend/src/components/ui/sheet.tsx +138 -0
- package/frontend/src/components/ui/sidebar.tsx +723 -0
- package/frontend/src/components/ui/skeleton.tsx +13 -0
- package/frontend/src/components/ui/sonner.tsx +47 -0
- package/frontend/src/components/ui/switch.tsx +30 -0
- package/frontend/src/components/ui/table.tsx +114 -0
- package/frontend/src/components/ui/tabs.tsx +82 -0
- package/frontend/src/components/ui/textarea.tsx +18 -0
- package/frontend/src/components/ui/toggle-group.tsx +89 -0
- package/frontend/src/components/ui/toggle.tsx +43 -0
- package/frontend/src/components/ui/tooltip.tsx +64 -0
- package/frontend/src/hooks/use-mobile.ts +19 -0
- package/frontend/src/i18n/index.ts +20 -0
- package/frontend/src/i18n/locales/en.json +786 -0
- package/frontend/src/i18n/locales/tr.json +786 -0
- package/frontend/src/index.css +134 -0
- package/frontend/src/layouts/admin-layout.tsx +111 -0
- package/frontend/src/layouts/app-header.tsx +130 -0
- package/frontend/src/layouts/app-layout.tsx +19 -0
- package/frontend/src/layouts/app-sidebar.tsx +212 -0
- package/frontend/src/layouts/auth-guard.tsx +31 -0
- package/frontend/src/layouts/mobile-sidebar.tsx +120 -0
- package/frontend/src/lib/api.ts +68 -0
- package/frontend/src/lib/hooks/use-appointments.ts +224 -0
- package/frontend/src/lib/hooks/use-availability-blocks.ts +83 -0
- package/frontend/src/lib/hooks/use-chats.ts +236 -0
- package/frontend/src/lib/hooks/use-clinic-detail.ts +171 -0
- package/frontend/src/lib/hooks/use-clinics.ts +37 -0
- package/frontend/src/lib/hooks/use-doctor-calendar.ts +80 -0
- package/frontend/src/lib/hooks/use-examinations.ts +89 -0
- package/frontend/src/lib/hooks/use-medical-history.ts +52 -0
- package/frontend/src/lib/hooks/use-patients.ts +296 -0
- package/frontend/src/lib/hooks/use-photo-sets.ts +118 -0
- package/frontend/src/lib/hooks/use-treatment-plans.ts +152 -0
- package/frontend/src/lib/hooks/use-treatments.ts +125 -0
- package/frontend/src/lib/hooks/use-users.ts +172 -0
- package/frontend/src/lib/utils.ts +6 -0
- package/frontend/src/main.tsx +17 -0
- package/frontend/src/pages/admin/agents/detail.tsx +774 -0
- package/frontend/src/pages/admin/agents/import.tsx +280 -0
- package/frontend/src/pages/admin/agents/index.tsx +245 -0
- package/frontend/src/pages/admin/ai-playground.tsx +543 -0
- package/frontend/src/pages/appointments/create-appointment-dialog.tsx +390 -0
- package/frontend/src/pages/appointments/index.tsx +860 -0
- package/frontend/src/pages/audit/index.tsx +24 -0
- package/frontend/src/pages/auth/login.tsx +194 -0
- package/frontend/src/pages/billing/index.tsx +24 -0
- package/frontend/src/pages/calendar/index.tsx +704 -0
- package/frontend/src/pages/calendar-connections/index.tsx +295 -0
- package/frontend/src/pages/calls/index.tsx +24 -0
- package/frontend/src/pages/campaigns/index.tsx +24 -0
- package/frontend/src/pages/chats/index.tsx +981 -0
- package/frontend/src/pages/clinics/index.tsx +224 -0
- package/frontend/src/pages/clinics/settings.tsx +412 -0
- package/frontend/src/pages/components-showcase.tsx +773 -0
- package/frontend/src/pages/connections/index.tsx +328 -0
- package/frontend/src/pages/dashboard.tsx +50 -0
- package/frontend/src/pages/leads/index.tsx +24 -0
- package/frontend/src/pages/my-schedule/index.tsx +496 -0
- package/frontend/src/pages/patients/create-patient-dialog.tsx +358 -0
- package/frontend/src/pages/patients/detail.tsx +1195 -0
- package/frontend/src/pages/patients/edit-patient-dialog.tsx +387 -0
- package/frontend/src/pages/patients/examinations-tab.tsx +460 -0
- package/frontend/src/pages/patients/index.tsx +381 -0
- package/frontend/src/pages/patients/medical-history-dialog.tsx +207 -0
- package/frontend/src/pages/patients/photo-sets-tab.tsx +616 -0
- package/frontend/src/pages/patients/timeline-tab.tsx +164 -0
- package/frontend/src/pages/patients/treatment-plans-tab.tsx +598 -0
- package/frontend/src/pages/phone-numbers/detail.tsx +427 -0
- package/frontend/src/pages/phone-numbers/index.tsx +455 -0
- package/frontend/src/pages/platform/index.tsx +454 -0
- package/frontend/src/pages/settings/index.tsx +126 -0
- package/frontend/src/pages/treatments/index.tsx +487 -0
- package/frontend/src/pages/users/doctor-profile.tsx +672 -0
- package/frontend/src/pages/users/edit.tsx +329 -0
- package/frontend/src/pages/users/index.tsx +407 -0
- package/frontend/src/pages/validation/index.tsx +24 -0
- package/frontend/src/stores/auth.store.ts +108 -0
- package/frontend/src/stores/ui.store.ts +41 -0
- package/frontend/tsconfig.app.json +32 -0
- package/frontend/tsconfig.json +13 -0
- package/frontend/tsconfig.node.json +26 -0
- package/frontend/vite.config.ts +29 -0
- package/nestjs/.dockerignore +5 -0
- package/nestjs/.env.docker +64 -0
- package/nestjs/.prettierrc +4 -0
- package/nestjs/Dockerfile +36 -0
- package/nestjs/README.md +98 -0
- package/nestjs/eslint.config.mjs +35 -0
- package/nestjs/nest-cli.json +8 -0
- package/nestjs/package-lock.json +13390 -0
- package/nestjs/package.json +114 -0
- package/nestjs/prisma/migrations/20260409161536_add_message_metadata_fields/migration.sql +1746 -0
- package/nestjs/prisma/migrations/20260410140436_add_agent_ai_fields/migration.sql +36 -0
- package/nestjs/prisma/migrations/20260410175519_add_agent_clinic_assignments/migration.sql +21 -0
- package/nestjs/prisma/migrations/20260412094344_make_agent_tenant_optional/migration.sql +2 -0
- package/nestjs/prisma/migrations/20260412110008_add_admin_chat_sessions/migration.sql +47 -0
- package/nestjs/prisma/migrations/migration_lock.toml +3 -0
- package/nestjs/prisma/schema.prisma +1843 -0
- package/nestjs/prisma/seed.ts +375 -0
- package/nestjs/prisma.config.ts +14 -0
- package/nestjs/src/admin/admin.controller.ts +27 -0
- package/nestjs/src/admin/admin.module.ts +16 -0
- package/nestjs/src/admin/admin.service.ts +91 -0
- package/nestjs/src/admin/ai-chat-session.service.ts +454 -0
- package/nestjs/src/admin/ai-test.controller.ts +191 -0
- package/nestjs/src/admin/superadmin.controller.ts +106 -0
- package/nestjs/src/agents/agents.controller.ts +262 -0
- package/nestjs/src/agents/agents.module.ts +13 -0
- package/nestjs/src/agents/agents.service.ts +733 -0
- package/nestjs/src/agents/dto/create-agent.dto.ts +99 -0
- package/nestjs/src/agents/dto/index.ts +2 -0
- package/nestjs/src/agents/dto/update-agent.dto.ts +148 -0
- package/nestjs/src/app.module.ts +115 -0
- package/nestjs/src/appointment-validation/appointment-validation.controller.ts +194 -0
- package/nestjs/src/appointment-validation/appointment-validation.module.ts +16 -0
- package/nestjs/src/appointment-validation/appointment-validation.service.ts +450 -0
- package/nestjs/src/appointment-validation/dto/create-batch.dto.ts +105 -0
- package/nestjs/src/appointment-validation/dto/index.ts +1 -0
- package/nestjs/src/appointment-validation/processors/validation-dispatch.processor.ts +26 -0
- package/nestjs/src/appointment-validation/processors/validation-sync.processor.ts +23 -0
- package/nestjs/src/appointments/appointments.controller.ts +268 -0
- package/nestjs/src/appointments/appointments.module.ts +13 -0
- package/nestjs/src/appointments/appointments.service.ts +773 -0
- package/nestjs/src/appointments/dto/create-appointment.dto.ts +72 -0
- package/nestjs/src/appointments/dto/index.ts +4 -0
- package/nestjs/src/appointments/dto/query-appointments.dto.ts +60 -0
- package/nestjs/src/appointments/dto/update-appointment.dto.ts +43 -0
- package/nestjs/src/appointments/dto/update-status.dto.ts +18 -0
- package/nestjs/src/appointments/processors/reminder.processor.ts +243 -0
- package/nestjs/src/audit/audit.controller.ts +84 -0
- package/nestjs/src/audit/audit.decorator.ts +20 -0
- package/nestjs/src/audit/audit.interceptor.ts +67 -0
- package/nestjs/src/audit/audit.interfaces.ts +15 -0
- package/nestjs/src/audit/audit.module.ts +12 -0
- package/nestjs/src/audit/audit.service.ts +177 -0
- package/nestjs/src/auth/auth.controller.ts +116 -0
- package/nestjs/src/auth/auth.module.ts +25 -0
- package/nestjs/src/auth/auth.service.ts +612 -0
- package/nestjs/src/auth/dto/change-password.dto.ts +13 -0
- package/nestjs/src/auth/dto/forgot-password.dto.ts +8 -0
- package/nestjs/src/auth/dto/index.ts +6 -0
- package/nestjs/src/auth/dto/login.dto.ts +13 -0
- package/nestjs/src/auth/dto/refresh.dto.ts +8 -0
- package/nestjs/src/auth/dto/register.dto.ts +28 -0
- package/nestjs/src/auth/dto/reset-password.dto.ts +13 -0
- package/nestjs/src/auth/permissions.config.ts +85 -0
- package/nestjs/src/availability-blocks/availability-blocks.controller.ts +83 -0
- package/nestjs/src/availability-blocks/availability-blocks.module.ts +10 -0
- package/nestjs/src/availability-blocks/availability-blocks.service.ts +202 -0
- package/nestjs/src/billing/billing.controller.ts +104 -0
- package/nestjs/src/billing/billing.module.ts +12 -0
- package/nestjs/src/billing/billing.service.ts +398 -0
- package/nestjs/src/billing/dto/index.ts +2 -0
- package/nestjs/src/billing/dto/query-billing.dto.ts +29 -0
- package/nestjs/src/billing/dto/record-payment.dto.ts +60 -0
- package/nestjs/src/billing/processors/alerts.processor.ts +216 -0
- package/nestjs/src/billing/processors/snapshot.processor.ts +181 -0
- package/nestjs/src/calls/calls.controller.ts +92 -0
- package/nestjs/src/calls/calls.module.ts +10 -0
- package/nestjs/src/calls/calls.service.ts +359 -0
- package/nestjs/src/calls/dto/index.ts +1 -0
- package/nestjs/src/calls/dto/query-calls.dto.ts +46 -0
- package/nestjs/src/clinics/clinics.controller.ts +226 -0
- package/nestjs/src/clinics/clinics.module.ts +11 -0
- package/nestjs/src/clinics/clinics.service.ts +203 -0
- package/nestjs/src/clinics/dto/create-clinic.dto.ts +40 -0
- package/nestjs/src/clinics/dto/create-meta-connection.dto.ts +44 -0
- package/nestjs/src/clinics/dto/index.ts +4 -0
- package/nestjs/src/clinics/dto/update-clinic.dto.ts +133 -0
- package/nestjs/src/clinics/dto/update-meta-connection.dto.ts +22 -0
- package/nestjs/src/clinics/meta-connections.service.ts +210 -0
- package/nestjs/src/common/decorators/accessible-clinics.decorator.ts +9 -0
- package/nestjs/src/common/decorators/current-user.decorator.ts +10 -0
- package/nestjs/src/common/decorators/features.decorator.ts +7 -0
- package/nestjs/src/common/decorators/index.ts +4 -0
- package/nestjs/src/common/decorators/permissions.decorator.ts +13 -0
- package/nestjs/src/common/gateways/events.gateway.ts +157 -0
- package/nestjs/src/common/guards/clinic-access.guard.ts +40 -0
- package/nestjs/src/common/guards/features.guard.ts +38 -0
- package/nestjs/src/common/guards/index.ts +5 -0
- package/nestjs/src/common/guards/jwt-auth.guard.ts +54 -0
- package/nestjs/src/common/guards/permissions.guard.ts +50 -0
- package/nestjs/src/common/guards/superadmin.guard.ts +35 -0
- package/nestjs/src/common/interceptors/request-context.interceptor.ts +32 -0
- package/nestjs/src/common/interceptors/superadmin-tenant.interceptor.ts +42 -0
- package/nestjs/src/common/interfaces/jwt-payload.interface.ts +11 -0
- package/nestjs/src/config/config.module.ts +13 -0
- package/nestjs/src/database/database.module.ts +9 -0
- package/nestjs/src/database/prisma.service.ts +20 -0
- package/nestjs/src/database/tenant-context.ts +27 -0
- package/nestjs/src/google-calendar/google-calendar.controller.ts +259 -0
- package/nestjs/src/google-calendar/google-calendar.module.ts +10 -0
- package/nestjs/src/google-calendar/google-calendar.service.ts +811 -0
- package/nestjs/src/integrations/ai/ai.interface.ts +74 -0
- package/nestjs/src/integrations/ai/ai.module.ts +11 -0
- package/nestjs/src/integrations/ai/ai.service.ts +148 -0
- package/nestjs/src/integrations/ai/providers/anthropic.provider.ts +146 -0
- package/nestjs/src/integrations/ai/providers/openai.provider.ts +158 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.module.ts +8 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.service.ts +226 -0
- package/nestjs/src/integrations/encryption/encryption.module.ts +9 -0
- package/nestjs/src/integrations/encryption/encryption.service.ts +31 -0
- package/nestjs/src/integrations/image/image.module.ts +9 -0
- package/nestjs/src/integrations/image/image.service.ts +61 -0
- package/nestjs/src/integrations/meta-business/meta-business.module.ts +10 -0
- package/nestjs/src/integrations/meta-business/meta-instagram.service.ts +94 -0
- package/nestjs/src/integrations/meta-business/meta-webhook.service.ts +52 -0
- package/nestjs/src/integrations/meta-business/meta-whatsapp.service.ts +254 -0
- package/nestjs/src/integrations/minio/minio.module.ts +9 -0
- package/nestjs/src/integrations/minio/minio.service.ts +88 -0
- package/nestjs/src/integrations/netgsm/netgsm.module.ts +8 -0
- package/nestjs/src/integrations/netgsm/netgsm.service.ts +17 -0
- package/nestjs/src/integrations/tektippay/tektippay.module.ts +8 -0
- package/nestjs/src/integrations/tektippay/tektippay.service.ts +23 -0
- package/nestjs/src/leads/dto/index.ts +2 -0
- package/nestjs/src/leads/dto/query-leads.dto.ts +50 -0
- package/nestjs/src/leads/dto/update-lead.dto.ts +26 -0
- package/nestjs/src/leads/leads.controller.ts +184 -0
- package/nestjs/src/leads/leads.module.ts +10 -0
- package/nestjs/src/leads/leads.service.ts +375 -0
- package/nestjs/src/logging/logging.controller.ts +82 -0
- package/nestjs/src/logging/logging.module.ts +11 -0
- package/nestjs/src/logging/logging.service.ts +180 -0
- package/nestjs/src/main.ts +86 -0
- package/nestjs/src/outbound-campaigns/dto/create-campaign.dto.ts +47 -0
- package/nestjs/src/outbound-campaigns/dto/index.ts +3 -0
- package/nestjs/src/outbound-campaigns/dto/update-campaign.dto.ts +31 -0
- package/nestjs/src/outbound-campaigns/dto/upload-entries.dto.ts +35 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.controller.ts +307 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.module.ts +13 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.service.ts +471 -0
- package/nestjs/src/outbound-campaigns/processors/campaign-dispatch.processor.ts +366 -0
- package/nestjs/src/patients/documents.service.ts +231 -0
- package/nestjs/src/patients/dto/create-examination.dto.ts +34 -0
- package/nestjs/src/patients/dto/create-note.dto.ts +14 -0
- package/nestjs/src/patients/dto/create-patient.dto.ts +86 -0
- package/nestjs/src/patients/dto/create-photo-set.dto.ts +32 -0
- package/nestjs/src/patients/dto/index.ts +10 -0
- package/nestjs/src/patients/dto/update-examination.dto.ts +29 -0
- package/nestjs/src/patients/dto/update-medical-history.dto.ts +47 -0
- package/nestjs/src/patients/dto/update-patient.dto.ts +87 -0
- package/nestjs/src/patients/dto/update-photo-set.dto.ts +28 -0
- package/nestjs/src/patients/dto/upload-document.dto.ts +31 -0
- package/nestjs/src/patients/dto/upload-photo.dto.ts +27 -0
- package/nestjs/src/patients/examinations.service.ts +271 -0
- package/nestjs/src/patients/medical-history.service.ts +149 -0
- package/nestjs/src/patients/notes.service.ts +172 -0
- package/nestjs/src/patients/patients.controller.ts +485 -0
- package/nestjs/src/patients/patients.module.ts +22 -0
- package/nestjs/src/patients/patients.service.ts +412 -0
- package/nestjs/src/patients/photo-sets.service.ts +389 -0
- package/nestjs/src/phone-numbers/dto/create-phone-number.dto.ts +57 -0
- package/nestjs/src/phone-numbers/dto/index.ts +3 -0
- package/nestjs/src/phone-numbers/dto/update-phone-number.dto.ts +38 -0
- package/nestjs/src/phone-numbers/dto/update-schedule.dto.ts +39 -0
- package/nestjs/src/phone-numbers/phone-numbers.controller.ts +125 -0
- package/nestjs/src/phone-numbers/phone-numbers.module.ts +10 -0
- package/nestjs/src/phone-numbers/phone-numbers.service.ts +209 -0
- package/nestjs/src/plans/dto/create-plan.dto.ts +70 -0
- package/nestjs/src/plans/dto/index.ts +2 -0
- package/nestjs/src/plans/dto/update-plan.dto.ts +80 -0
- package/nestjs/src/plans/plans.controller.ts +50 -0
- package/nestjs/src/plans/plans.module.ts +10 -0
- package/nestjs/src/plans/plans.service.ts +115 -0
- package/nestjs/src/platform/dto/create-tenant.dto.ts +36 -0
- package/nestjs/src/platform/dto/index.ts +2 -0
- package/nestjs/src/platform/dto/update-tenant-platform.dto.ts +44 -0
- package/nestjs/src/platform/platform.controller.ts +79 -0
- package/nestjs/src/platform/platform.module.ts +10 -0
- package/nestjs/src/platform/platform.service.ts +301 -0
- package/nestjs/src/queue/queue.module.ts +56 -0
- package/nestjs/src/redis/redis.module.ts +20 -0
- package/nestjs/src/tenants/dto/index.ts +1 -0
- package/nestjs/src/tenants/dto/update-tenant.dto.ts +15 -0
- package/nestjs/src/tenants/tenants.controller.ts +45 -0
- package/nestjs/src/tenants/tenants.module.ts +10 -0
- package/nestjs/src/tenants/tenants.service.ts +41 -0
- package/nestjs/src/tools/adapters/elevenlabs-http.adapter.ts +51 -0
- package/nestjs/src/tools/adapters/elevenlabs-ws.adapter.ts +59 -0
- package/nestjs/src/tools/handlers/calendar.tools.ts +441 -0
- package/nestjs/src/tools/handlers/notification.tools.ts +34 -0
- package/nestjs/src/tools/handlers/operator.tools.ts +303 -0
- package/nestjs/src/tools/handlers/patient.tools.ts +242 -0
- package/nestjs/src/tools/handlers/payment.tools.ts +43 -0
- package/nestjs/src/tools/handlers/validation.tools.ts +152 -0
- package/nestjs/src/tools/tool-registry.service.ts +221 -0
- package/nestjs/src/tools/tool.decorator.ts +16 -0
- package/nestjs/src/tools/tool.interfaces.ts +26 -0
- package/nestjs/src/tools/tools.module.ts +50 -0
- package/nestjs/src/treatments/dto/create-plan-item.dto.ts +27 -0
- package/nestjs/src/treatments/dto/create-treatment-plan.dto.ts +69 -0
- package/nestjs/src/treatments/dto/create-treatment.dto.ts +59 -0
- package/nestjs/src/treatments/dto/index.ts +6 -0
- package/nestjs/src/treatments/dto/update-plan-item.dto.ts +23 -0
- package/nestjs/src/treatments/dto/update-treatment-plan.dto.ts +22 -0
- package/nestjs/src/treatments/dto/update-treatment.dto.ts +70 -0
- package/nestjs/src/treatments/treatment-plans.service.ts +362 -0
- package/nestjs/src/treatments/treatments.controller.ts +265 -0
- package/nestjs/src/treatments/treatments.module.ts +14 -0
- package/nestjs/src/treatments/treatments.service.ts +165 -0
- package/nestjs/src/users/doctor-profiles.service.ts +202 -0
- package/nestjs/src/users/dto/index.ts +4 -0
- package/nestjs/src/users/dto/invite-user.dto.ts +52 -0
- package/nestjs/src/users/dto/update-clinic-assignments.dto.ts +9 -0
- package/nestjs/src/users/dto/update-doctor-profile.dto.ts +49 -0
- package/nestjs/src/users/dto/update-user.dto.ts +41 -0
- package/nestjs/src/users/users.controller.ts +142 -0
- package/nestjs/src/users/users.module.ts +11 -0
- package/nestjs/src/users/users.service.ts +250 -0
- package/nestjs/src/webhooks/elevenlabs-tool.controller.ts +66 -0
- package/nestjs/src/webhooks/elevenlabs-webhook.controller.ts +60 -0
- package/nestjs/src/webhooks/meta-webhook.controller.ts +178 -0
- package/nestjs/src/webhooks/processors/elevenlabs-webhook.processor.ts +28 -0
- package/nestjs/src/webhooks/webhooks.module.ts +17 -0
- package/nestjs/src/whatsapp/chat-context.service.ts +281 -0
- package/nestjs/src/whatsapp/dto/add-blacklist.dto.ts +13 -0
- package/nestjs/src/whatsapp/dto/index.ts +2 -0
- package/nestjs/src/whatsapp/dto/send-message.dto.ts +14 -0
- package/nestjs/src/whatsapp/listeners/meta-message.listener.ts +579 -0
- package/nestjs/src/whatsapp/meta-auth.controller.ts +268 -0
- package/nestjs/src/whatsapp/meta-instagram-auth.controller.ts +244 -0
- package/nestjs/src/whatsapp/operator.service.ts +692 -0
- package/nestjs/src/whatsapp/processors/cost-sweep.processor.ts +130 -0
- package/nestjs/src/whatsapp/processors/grace.processor.ts +191 -0
- package/nestjs/src/whatsapp/processors/message-buffer.processor.ts +138 -0
- package/nestjs/src/whatsapp/processors/message-cleanup.processor.ts +148 -0
- package/nestjs/src/whatsapp/processors/meta-token-refresh.processor.ts +114 -0
- package/nestjs/src/whatsapp/processors/operator-expiry.processor.ts +105 -0
- package/nestjs/src/whatsapp/processors/profile-update.processor.ts +234 -0
- package/nestjs/src/whatsapp/processors/session-cleanup.processor.ts +178 -0
- package/nestjs/src/whatsapp/processors/session-labels.processor.ts +248 -0
- package/nestjs/src/whatsapp/whatsapp-agent.service.ts +2506 -0
- package/nestjs/src/whatsapp/whatsapp-recovery.service.ts +117 -0
- package/nestjs/src/whatsapp/whatsapp.controller.ts +398 -0
- package/nestjs/src/whatsapp/whatsapp.module.ts +51 -0
- package/nestjs/src/whatsapp/whatsapp.service.ts +592 -0
- package/nestjs/test/app.e2e-spec.ts +25 -0
- package/nestjs/test/jest-e2e.json +9 -0
- package/nestjs/tsconfig.build.json +4 -0
- package/nestjs/tsconfig.json +25 -0
- package/nginx.example.conf +18 -0
- package/package.json +47 -0
- package/scripts/addRecipient.ts +48 -0
- package/scripts/listRecipients.ts +31 -0
- package/scripts/migrate-agent-ref.ts +86 -0
- package/scripts/migrate-sessions.ts +183 -0
- package/scripts/promote.ts +27 -0
- package/scripts/retrigger.ts +84 -0
- package/scripts/seed.ts +435 -0
- package/scripts/testSend.ts +63 -0
- package/src/app.ts +85 -0
- package/src/config/agentPrompts.json +19 -0
- package/src/config/database.ts +21 -0
- package/src/config/env.ts +94 -0
- package/src/config/index.ts +86 -0
- package/src/controllers/webhook.controller.ts +150 -0
- package/src/errors/index.ts +9 -0
- package/src/hooks/webhookValidator.ts +55 -0
- package/src/index.ts +68 -0
- package/src/migrations/001_session-architecture.ts +138 -0
- package/src/migrations/002_agent-ref.ts +65 -0
- package/src/migrations/003_shift-schedule.ts +55 -0
- package/src/migrations/004_invert-shift-to-clinic-hours.ts +30 -0
- package/src/migrations/005_composite-baileys-chat-ids.ts +60 -0
- package/src/migrations/migration.model.ts +27 -0
- package/src/migrations/migration.routes.ts +40 -0
- package/src/migrations/migration.runner.ts +112 -0
- package/src/models/ConversationClaim.ts +17 -0
- package/src/models/ConversationEvaluation.ts +91 -0
- package/src/models/Summary.ts +77 -0
- package/src/models/Transcription.ts +68 -0
- package/src/models/WhatsAppRecipient.ts +37 -0
- package/src/modules/admin/admin.routes.ts +2385 -0
- package/src/modules/admin/elevenlabs-test-chat.routes.ts +193 -0
- package/src/modules/admin/whatsapp-test-chat.routes.ts +244 -0
- package/src/modules/agents/agent.model.ts +93 -0
- package/src/modules/agents/agent.routes.ts +65 -0
- package/src/modules/appointment-validation/appointment-validation.model.ts +163 -0
- package/src/modules/appointment-validation/appointment-validation.routes.ts +275 -0
- package/src/modules/appointment-validation/appointment-validation.service.ts +1028 -0
- package/src/modules/auth/auth.model.ts +42 -0
- package/src/modules/auth/auth.routes.ts +199 -0
- package/src/modules/auth/auth.service.ts +210 -0
- package/src/modules/auth/refresh-token.model.ts +26 -0
- package/src/modules/billing/billing-alert.model.ts +28 -0
- package/src/modules/billing/billing-period-snapshot.model.ts +68 -0
- package/src/modules/billing/billing.model.ts +42 -0
- package/src/modules/billing/billing.routes.ts +67 -0
- package/src/modules/billing/billing.service.ts +562 -0
- package/src/modules/billing/payment.model.ts +42 -0
- package/src/modules/calls/call.model.ts +102 -0
- package/src/modules/calls/call.routes.ts +118 -0
- package/src/modules/campaigns/campaign.model.ts +111 -0
- package/src/modules/campaigns/campaign.routes.ts +402 -0
- package/src/modules/campaigns/campaign.service.ts +99 -0
- package/src/modules/google-calendar/google-calendar.routes.ts +31 -0
- package/src/modules/inbound-call/inbound-call-config.model.ts +49 -0
- package/src/modules/inbound-call/inbound-call.routes.ts +289 -0
- package/src/modules/leads/lead.model.ts +40 -0
- package/src/modules/leads/lead.routes.ts +246 -0
- package/src/modules/logs/log.model.ts +27 -0
- package/src/modules/logs/log.routes.ts +102 -0
- package/src/modules/plans/plan.model.ts +45 -0
- package/src/modules/surveys/survey.model.ts +70 -0
- package/src/modules/surveys/survey.routes.ts +187 -0
- package/src/modules/tenants/tenant.model.ts +181 -0
- package/src/modules/tenants/tenant.routes.ts +78 -0
- package/src/modules/users/user.routes.ts +126 -0
- package/src/modules/webhooks/elevenlabs-tool.routes.ts +94 -0
- package/src/modules/webhooks/elevenlabs-tool.service.ts +491 -0
- package/src/modules/webhooks/elevenlabs.routes.ts +34 -0
- package/src/modules/webhooks/elevenlabs.service.ts +565 -0
- package/src/modules/webhooks/unipile.routes.ts +917 -0
- package/src/modules/whatsapp/appointment.model.ts +47 -0
- package/src/modules/whatsapp/operator-request.model.ts +58 -0
- package/src/modules/whatsapp/stt-usage.model.ts +30 -0
- package/src/modules/whatsapp/whatsapp-chat.model.ts +39 -0
- package/src/modules/whatsapp/whatsapp-contact-profile.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-message.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-session.model.ts +60 -0
- package/src/modules/whatsapp/whatsapp.routes.ts +1435 -0
- package/src/plugins/cors.ts +7 -0
- package/src/plugins/jwt.ts +18 -0
- package/src/plugins/rawBody.ts +12 -0
- package/src/plugins/rbac.ts +24 -0
- package/src/routes/admin.routes.ts +208 -0
- package/src/routes/health.routes.ts +12 -0
- package/src/routes/webhook.routes.ts +12 -0
- package/src/services/ai/base.ai.ts +132 -0
- package/src/services/ai/gemini.service.ts +41 -0
- package/src/services/ai/index.ts +24 -0
- package/src/services/ai/openai.service.ts +48 -0
- package/src/services/elevenlabs.service.ts +532 -0
- package/src/services/google-calendar.service.ts +656 -0
- package/src/services/inbound-call-schedule.service.ts +174 -0
- package/src/services/netgsm.service.ts +128 -0
- package/src/services/unipile.service.ts +200 -0
- package/src/services/whatsapp-agent.service.ts +2479 -0
- package/src/services/whatsapp.service.ts +245 -0
- package/src/templates/index.ts +71 -0
- package/src/templates/receptionist.ts +44 -0
- package/src/templates/survey.ts +44 -0
- package/src/types/index.ts +218 -0
- package/src/utils/logger.ts +83 -0
- package/tsconfig.json +19 -0
- package/web/.dockerignore +4 -0
- package/web/Dockerfile +18 -0
- package/web/README.md +73 -0
- package/web/components.json +23 -0
- package/web/eslint.config.js +23 -0
- package/web/index.html +14 -0
- package/web/nginx.conf +18 -0
- package/web/package-lock.json +10292 -0
- package/web/package.json +48 -0
- package/web/public/favicon.ico +0 -0
- package/web/public/vite.svg +1 -0
- package/web/src/App.tsx +191 -0
- package/web/src/assets/react.svg +1 -0
- package/web/src/components/Layout.tsx +261 -0
- package/web/src/components/LeadConversation.tsx +251 -0
- package/web/src/components/ProtectedRoute.tsx +20 -0
- package/web/src/components/conversation-review/CardAudioPlayer.tsx +200 -0
- package/web/src/components/conversation-review/CardEvaluation.tsx +351 -0
- package/web/src/components/conversation-review/CardMetadata.tsx +44 -0
- package/web/src/components/conversation-review/ConversationCard.tsx +95 -0
- package/web/src/components/conversation-review/ReviewContainer.tsx +120 -0
- package/web/src/components/conversation-review/ReviewFilters.tsx +88 -0
- package/web/src/components/empty-state.tsx +15 -0
- package/web/src/components/page-header.tsx +19 -0
- package/web/src/components/page-loader.tsx +32 -0
- package/web/src/components/pagination.tsx +38 -0
- package/web/src/components/stat-card.tsx +27 -0
- package/web/src/components/status-badge.tsx +125 -0
- package/web/src/components/ui/alert.tsx +66 -0
- package/web/src/components/ui/badge.tsx +48 -0
- package/web/src/components/ui/button.tsx +64 -0
- package/web/src/components/ui/card.tsx +92 -0
- package/web/src/components/ui/checkbox.tsx +32 -0
- package/web/src/components/ui/dialog.tsx +158 -0
- package/web/src/components/ui/dropdown-menu.tsx +255 -0
- package/web/src/components/ui/input.tsx +21 -0
- package/web/src/components/ui/label.tsx +22 -0
- package/web/src/components/ui/progress.tsx +29 -0
- package/web/src/components/ui/select.tsx +188 -0
- package/web/src/components/ui/separator.tsx +28 -0
- package/web/src/components/ui/sheet.tsx +123 -0
- package/web/src/components/ui/skeleton.tsx +13 -0
- package/web/src/components/ui/sonner.tsx +35 -0
- package/web/src/components/ui/table.tsx +116 -0
- package/web/src/components/ui/tabs.tsx +89 -0
- package/web/src/components/ui/textarea.tsx +18 -0
- package/web/src/components/ui/tooltip.tsx +57 -0
- package/web/src/components/whatsapp/ChatDetail.tsx +417 -0
- package/web/src/components/whatsapp/ChatHeader.tsx +78 -0
- package/web/src/components/whatsapp/ChatList.tsx +107 -0
- package/web/src/components/whatsapp/ChatListItem.tsx +60 -0
- package/web/src/components/whatsapp/MessageBubble.tsx +46 -0
- package/web/src/components/whatsapp/MessageInput.tsx +63 -0
- package/web/src/components/whatsapp/MessageStream.tsx +135 -0
- package/web/src/components/whatsapp/SessionDivider.tsx +65 -0
- package/web/src/components/whatsapp/SessionHistory.tsx +119 -0
- package/web/src/components/whatsapp/settings/AiSettingsTab.tsx +268 -0
- package/web/src/components/whatsapp/settings/CalendarTab.tsx +339 -0
- package/web/src/components/whatsapp/settings/ConnectionTab.tsx +236 -0
- package/web/src/components/whatsapp/settings/NotificationsTab.tsx +109 -0
- package/web/src/components/whatsapp/settings/OperatorTab.tsx +303 -0
- package/web/src/contexts/AuthContext.tsx +103 -0
- package/web/src/index.css +130 -0
- package/web/src/lib/api.ts +92 -0
- package/web/src/lib/utils.ts +6 -0
- package/web/src/main.tsx +10 -0
- package/web/src/pages/AppointmentDetail.tsx +206 -0
- package/web/src/pages/AppointmentValidation.tsx +157 -0
- package/web/src/pages/AppointmentValidationDetail.tsx +617 -0
- package/web/src/pages/AppointmentValidationNew.tsx +1005 -0
- package/web/src/pages/Appointments.tsx +283 -0
- package/web/src/pages/Billing.tsx +126 -0
- package/web/src/pages/CallDetail.tsx +293 -0
- package/web/src/pages/CallSettings.tsx +313 -0
- package/web/src/pages/Calls.tsx +188 -0
- package/web/src/pages/CampaignDetail.tsx +216 -0
- package/web/src/pages/CampaignNew.tsx +277 -0
- package/web/src/pages/CampaignResults.tsx +185 -0
- package/web/src/pages/Campaigns.tsx +171 -0
- package/web/src/pages/Dashboard.tsx +336 -0
- package/web/src/pages/InboundSchedule.tsx +246 -0
- package/web/src/pages/LeadDetail.tsx +183 -0
- package/web/src/pages/Leads.tsx +258 -0
- package/web/src/pages/Login.tsx +99 -0
- package/web/src/pages/Register.tsx +129 -0
- package/web/src/pages/Settings.tsx +133 -0
- package/web/src/pages/SurveyDetail.tsx +232 -0
- package/web/src/pages/SurveyPreview.tsx +179 -0
- package/web/src/pages/Surveys.tsx +207 -0
- package/web/src/pages/Users.tsx +199 -0
- package/web/src/pages/WhatsApp.tsx +147 -0
- package/web/src/pages/WhatsAppSettings.tsx +215 -0
- package/web/src/pages/admin/AdminBaileysMessageLog.tsx +331 -0
- package/web/src/pages/admin/AdminBaileysRawMessages.tsx +318 -0
- package/web/src/pages/admin/AdminConversationReview.tsx +116 -0
- package/web/src/pages/admin/AdminCredits.tsx +467 -0
- package/web/src/pages/admin/AdminElevenLabsAgentDetail.tsx +332 -0
- package/web/src/pages/admin/AdminElevenLabsAgents.tsx +164 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCallDetail.tsx +214 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsConversationDetail.tsx +230 -0
- package/web/src/pages/admin/AdminElevenLabsConversations.tsx +228 -0
- package/web/src/pages/admin/AdminElevenLabsInboundCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsPhoneNumbers.tsx +506 -0
- package/web/src/pages/admin/AdminElevenLabsTestChat.tsx +258 -0
- package/web/src/pages/admin/AdminElevenLabsWebhooks.tsx +289 -0
- package/web/src/pages/admin/AdminEvaluationDashboard.tsx +520 -0
- package/web/src/pages/admin/AdminLeads.tsx +339 -0
- package/web/src/pages/admin/AdminLogs.tsx +283 -0
- package/web/src/pages/admin/AdminMigrations.tsx +247 -0
- package/web/src/pages/admin/AdminPlans.tsx +313 -0
- package/web/src/pages/admin/AdminSystem.tsx +391 -0
- package/web/src/pages/admin/AdminTenantBillableItems.tsx +464 -0
- package/web/src/pages/admin/AdminTenantDetail.tsx +1317 -0
- package/web/src/pages/admin/AdminTenants.tsx +274 -0
- package/web/src/pages/admin/AdminWhatsApp.tsx +618 -0
- package/web/src/pages/admin/AdminWhatsAppTestChat.tsx +328 -0
- package/web/src/types/index.ts +242 -0
- package/web/tsconfig.app.json +32 -0
- package/web/tsconfig.json +13 -0
- package/web/tsconfig.node.json +26 -0
- package/web/vite.config.ts +23 -0
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
# 06 - Baileys WhatsApp Microservice
|
|
2
|
+
|
|
3
|
+
> **NOT IN SCOPE FOR LAUNCH.** Baileys microservice is deferred. Meta Business Cloud API is the sole WhatsApp provider at launch. This document is retained as a reference for potential future integration.
|
|
4
|
+
|
|
5
|
+
> Last updated: 2026-04-02
|
|
6
|
+
|
|
7
|
+
> The Baileys microservice provides a self-hosted WhatsApp bridge using the
|
|
8
|
+
> @whiskeysockets/baileys library. It runs as a separate Node.js process from the
|
|
9
|
+
> main NestJS application, communicating via Redis pub/sub (target) or HTTP REST (current).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Architecture
|
|
14
|
+
|
|
15
|
+
### Current Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
NestJS :3005
|
|
19
|
+
|
|
|
20
|
+
| HTTP REST calls (UnipileService)
|
|
21
|
+
| POST /api/v1/chats/:chatId/messages
|
|
22
|
+
| POST /api/v1/chats/:chatId/forward-media
|
|
23
|
+
| etc.
|
|
24
|
+
v
|
|
25
|
+
Baileys Gateway (Express) :3001
|
|
26
|
+
|
|
|
27
|
+
| child_process.fork() IPC
|
|
28
|
+
|
|
|
29
|
+
+---> Worker 1 (account-abc) --- Baileys socket ---> WhatsApp
|
|
30
|
+
+---> Worker 2 (account-def) --- Baileys socket ---> WhatsApp
|
|
31
|
+
+---> Worker N (account-xyz) --- Baileys socket ---> WhatsApp
|
|
32
|
+
|
|
|
33
|
+
v
|
|
34
|
+
MongoDB (shared) -- baileys_auth, baileys_accounts, etc.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Target Architecture
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
NestJS :3005
|
|
41
|
+
|
|
|
42
|
+
| Redis pub/sub
|
|
43
|
+
| baileys:cmd:{accountId} (NestJS -> Baileys)
|
|
44
|
+
| baileys:evt:{accountId} (Baileys -> NestJS)
|
|
45
|
+
| baileys:req:{reqId} (request-reply)
|
|
46
|
+
|
|
|
47
|
+
v
|
|
48
|
+
Baileys Gateway (Express/Node.js)
|
|
49
|
+
|
|
|
50
|
+
| child_process.fork() IPC (unchanged)
|
|
51
|
+
|
|
|
52
|
+
+---> Worker 1 (account-abc) --- Baileys socket ---> WhatsApp
|
|
53
|
+
+---> Worker 2 (account-def) --- Baileys socket ---> WhatsApp
|
|
54
|
+
+---> Worker N
|
|
55
|
+
|
|
|
56
|
+
v
|
|
57
|
+
MongoDB (Baileys-only) -- baileys_auth (encrypted), baileys_accounts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Key Architectural Decisions
|
|
61
|
+
|
|
62
|
+
- **Separate process:** Baileys crashes (Signal Protocol issues, WhatsApp bans) must not bring down the main application.
|
|
63
|
+
- **Worker-per-account:** Each WhatsApp account runs in an isolated `child_process.fork()`. This provides memory isolation, independent crash recovery, and supports 10+ concurrent accounts.
|
|
64
|
+
- **Communication change:** HTTP REST (current) is replaced by Redis pub/sub (target) for lower latency and decoupled lifecycle. The gateway subscribes to command channels and publishes events.
|
|
65
|
+
- **Baileys keeps MongoDB:** Auth state and account metadata remain in MongoDB (separate from the main PostgreSQL database). Baileys auth state documents are too frequent and too granular for PostgreSQL.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 2. Redis Pub/Sub Protocol (Target)
|
|
70
|
+
|
|
71
|
+
### Channel Structure
|
|
72
|
+
|
|
73
|
+
| Channel Pattern | Direction | Purpose |
|
|
74
|
+
|-----------------|-----------|---------|
|
|
75
|
+
| `baileys:cmd:{accountId}` | NestJS -> Baileys | Commands: send message, connect, disconnect, etc. |
|
|
76
|
+
| `baileys:evt:{accountId}` | Baileys -> NestJS | Events: incoming message, QR code, connection status |
|
|
77
|
+
| `baileys:req:{reqId}` | Baileys -> NestJS | Request-reply responses (for commands that need a return value) |
|
|
78
|
+
|
|
79
|
+
### Command Messages (NestJS -> Baileys)
|
|
80
|
+
|
|
81
|
+
Published to `baileys:cmd:{accountId}`:
|
|
82
|
+
|
|
83
|
+
| Type | Payload | Description | Returns |
|
|
84
|
+
|------|---------|-------------|---------|
|
|
85
|
+
| `connect` | `{ accountId }` | Create new WhatsApp connection, fork worker | QR code or connection status |
|
|
86
|
+
| `reconnect` | `{ accountId }` | Reconnect existing account | QR code or connection status |
|
|
87
|
+
| `disconnect` | `{ accountId }` | Disconnect and delete account | -- |
|
|
88
|
+
| `status` | `{ accountId }` | Get current connection status | Status object |
|
|
89
|
+
| `send` | `{ chatId, text, reqId }` | Send text message | `{ message_id }` |
|
|
90
|
+
| `start_chat` | `{ phone, text, reqId }` | Start new chat with a phone number | `{ chat_id, message_id }` |
|
|
91
|
+
| `send_image` | `{ chatId, imageBase64, caption, reqId }` | Send base64 image | `{ message_id }` |
|
|
92
|
+
| `forward_media` | `{ messageId, toPhone, caption, reqId }` | Forward cached media to another phone | `{ message_id }` |
|
|
93
|
+
| `download_audio` | `{ messageId, reqId }` | Download audio from cached voice message | `{ audio_base64 }` |
|
|
94
|
+
|
|
95
|
+
### Event Messages (Baileys -> NestJS)
|
|
96
|
+
|
|
97
|
+
Published to `baileys:evt:{accountId}`:
|
|
98
|
+
|
|
99
|
+
| Type | Payload | Description |
|
|
100
|
+
|------|---------|-------------|
|
|
101
|
+
| `qr` | `{ qr }` | QR code string for scanning (raw, not data URL) |
|
|
102
|
+
| `connected` | `{ phone }` | WhatsApp connection established successfully |
|
|
103
|
+
| `disconnected` | `{ reason, statusCode? }` | Unexpected disconnect (network, auth issue) |
|
|
104
|
+
| `logged_out` | -- | Session ended by user or WhatsApp (requires re-scan) |
|
|
105
|
+
| `message` | `{ payload }` | Incoming WhatsApp message in normalized webhook format |
|
|
106
|
+
| `reply` | `{ reqId, data?, error? }` | Response to a command that included a `reqId` |
|
|
107
|
+
|
|
108
|
+
### Request-Reply Pattern
|
|
109
|
+
|
|
110
|
+
For commands that need a response (send, forward_media, download_audio):
|
|
111
|
+
|
|
112
|
+
1. NestJS generates a `reqId` (UUID) and includes it in the command
|
|
113
|
+
2. NestJS subscribes to `baileys:req:{reqId}` (or uses a shared reply channel with message filtering)
|
|
114
|
+
3. Baileys publishes the result to `baileys:req:{reqId}`
|
|
115
|
+
4. NestJS resolves the pending promise with the result
|
|
116
|
+
5. Timeout: 30 seconds, then reject with error
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. Worker IPC Protocol (Unchanged)
|
|
121
|
+
|
|
122
|
+
The internal communication between the gateway process and worker processes uses Node.js IPC (`process.send` / `process.on('message')`). This protocol is unchanged in the migration.
|
|
123
|
+
|
|
124
|
+
### Gateway -> Worker Messages
|
|
125
|
+
|
|
126
|
+
| Type | Payload | Description |
|
|
127
|
+
|------|---------|-------------|
|
|
128
|
+
| `init` | `{ accountId, authDir, mongodbUri, mediaForwardTo }` | Initialize worker with account config |
|
|
129
|
+
| `send` | `{ chatId, text, reqId }` | Send text message (chatId = raw JID) |
|
|
130
|
+
| `start_chat` | `{ phone, text, reqId }` | Start chat with phone number |
|
|
131
|
+
| `send_image` | `{ chatId, imageBase64, caption, reqId }` | Send image |
|
|
132
|
+
| `forward_media` | `{ messageId, toPhone, caption, reqId }` | Forward cached media |
|
|
133
|
+
| `download_audio` | `{ messageId, reqId }` | Download voice message audio |
|
|
134
|
+
| `disconnect` | -- | Graceful disconnect and logout |
|
|
135
|
+
| `shutdown` | -- | Graceful shutdown (save state, close socket) |
|
|
136
|
+
|
|
137
|
+
### Worker -> Gateway Messages
|
|
138
|
+
|
|
139
|
+
| Type | Payload | Description |
|
|
140
|
+
|------|---------|-------------|
|
|
141
|
+
| `qr` | `{ qr }` | QR code for WhatsApp Web scanning |
|
|
142
|
+
| `connected` | `{ phone }` | Successfully connected, phone number confirmed |
|
|
143
|
+
| `disconnected` | `{ reason, statusCode? }` | Connection lost |
|
|
144
|
+
| `logged_out` | -- | Session terminated (account must re-authenticate) |
|
|
145
|
+
| `status` | `{ status }` | Current status update |
|
|
146
|
+
| `message` | `{ payload }` | Normalized incoming message (Unipile-compatible format) |
|
|
147
|
+
| `reply` | `{ reqId, data?, error? }` | Response to a request |
|
|
148
|
+
| `ready` | -- | Worker initialized and ready to receive commands |
|
|
149
|
+
|
|
150
|
+
### Message Payload Format
|
|
151
|
+
|
|
152
|
+
The `message` type carries a payload normalized to match the Unipile webhook format. This ensures the NestJS webhook handler can process messages from both Baileys and Unipile/Meta identically.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
{
|
|
156
|
+
account_id: string, // Baileys account UUID
|
|
157
|
+
account_type: 'WHATSAPP',
|
|
158
|
+
event: 'message_received',
|
|
159
|
+
chat_id: string, // Composite: '{accountId}:{jid}'
|
|
160
|
+
message_id: string, // Baileys message key ID
|
|
161
|
+
message: string, // Extracted text or media label
|
|
162
|
+
content_type: string, // e.g., 'conversation', 'imageMessage', 'audioMessage'
|
|
163
|
+
timestamp: string, // ISO 8601
|
|
164
|
+
is_sender: boolean, // true if sent by the clinic account
|
|
165
|
+
sender: {
|
|
166
|
+
attendee_id: string,
|
|
167
|
+
attendee_name: string,
|
|
168
|
+
attendee_provider_id: string,
|
|
169
|
+
attendee_specifics: { phone_number: string },
|
|
170
|
+
},
|
|
171
|
+
attendees: [...], // Contact info array
|
|
172
|
+
account_info: { type: 'WHATSAPP', phone_number: string },
|
|
173
|
+
ad_context?: { ... } | null, // Ad attribution from contextInfo
|
|
174
|
+
quoted_text?: string | null, // Quoted message text (for reply detection)
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 4. Auth State Security
|
|
181
|
+
|
|
182
|
+
### Current Problem: Plain Text Credentials
|
|
183
|
+
|
|
184
|
+
Baileys stores WhatsApp Signal Protocol credentials in the `baileys_auth` MongoDB collection as **unencrypted JSON**. Each account has 20-50 documents:
|
|
185
|
+
|
|
186
|
+
| Document Type | Contains | Risk If Exposed |
|
|
187
|
+
|---------------|----------|-----------------|
|
|
188
|
+
| `creds.json` | Curve25519 identity keypair, signed pre-key (private), advance secret key, noise key, registration ID | **Full account takeover** -- attacker can impersonate the WhatsApp session |
|
|
189
|
+
| `pre-key-{ID}.json` | Curve25519 pre-key pairs (forward secrecy) | Decrypt past messages |
|
|
190
|
+
| `sender-key-{ID}.json` | Group encryption keys | Read group messages |
|
|
191
|
+
| `app-state-sync-key-{ID}.json` | History sync encryption keys | Decrypt message history |
|
|
192
|
+
|
|
193
|
+
Documents are serialized with `BufferJSON.replacer` -- that is **serialization, not encryption**. Anyone with MongoDB read access can extract full key material.
|
|
194
|
+
|
|
195
|
+
### Target: AES-256-GCM Encryption Per Account
|
|
196
|
+
|
|
197
|
+
#### Encryption Flow
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
Write path:
|
|
201
|
+
auth data (JSON) --> JSON.stringify(data, BufferJSON.replacer)
|
|
202
|
+
--> AES-256-GCM encrypt(derivedKey, iv, plaintext)
|
|
203
|
+
--> base64(iv + authTag + ciphertext)
|
|
204
|
+
--> store in MongoDB { data: "base64...", encrypted: true }
|
|
205
|
+
|
|
206
|
+
Read path:
|
|
207
|
+
MongoDB { data: "base64..." } --> base64 decode
|
|
208
|
+
--> extract iv (12 bytes) + authTag (16 bytes) + ciphertext
|
|
209
|
+
--> AES-256-GCM decrypt(derivedKey, iv, ciphertext, authTag)
|
|
210
|
+
--> JSON.parse(plaintext, BufferJSON.reviver)
|
|
211
|
+
--> auth data (JSON)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Key Derivation (HKDF)
|
|
215
|
+
|
|
216
|
+
Each account gets a unique encryption key derived from a master key:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Master key: BAILEYS_AUTH_ENCRYPTION_KEY (32-byte hex from env)
|
|
220
|
+
Per-account: HKDF(masterKey, accountId) --> unique AES-256 key
|
|
221
|
+
|
|
222
|
+
Benefit: Compromise of one account's key material in memory
|
|
223
|
+
does not expose other accounts' auth state.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
function deriveKey(masterKeyHex: string, accountId: string): Buffer {
|
|
228
|
+
const masterKey = Buffer.from(masterKeyHex, 'hex');
|
|
229
|
+
// HKDF: extract-then-expand
|
|
230
|
+
return hkdf(masterKey, 32, { salt: accountId, info: 'baileys-auth' });
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function encryptAuthData(accountId: string, data: any): string {
|
|
234
|
+
const key = deriveKey(ENCRYPTION_KEY, accountId);
|
|
235
|
+
const iv = randomBytes(12); // AES-256-GCM nonce
|
|
236
|
+
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
237
|
+
const plaintext = JSON.stringify(data, BufferJSON.replacer);
|
|
238
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
239
|
+
const authTag = cipher.getAuthTag();
|
|
240
|
+
return Buffer.concat([iv, authTag, encrypted]).toString('base64');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function decryptAuthData(accountId: string, encryptedBase64: string): any {
|
|
244
|
+
const key = deriveKey(ENCRYPTION_KEY, accountId);
|
|
245
|
+
const buf = Buffer.from(encryptedBase64, 'base64');
|
|
246
|
+
const iv = buf.subarray(0, 12);
|
|
247
|
+
const authTag = buf.subarray(12, 28);
|
|
248
|
+
const ciphertext = buf.subarray(28);
|
|
249
|
+
const decipher = createDecipheriv('aes-256-gcm', key, iv);
|
|
250
|
+
decipher.setAuthTag(authTag);
|
|
251
|
+
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8');
|
|
252
|
+
return JSON.parse(plaintext, BufferJSON.reviver);
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
#### MongoDB Document After Encryption
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"_id": "account-uuid:creds.json",
|
|
261
|
+
"accountId": "account-uuid",
|
|
262
|
+
"filename": "creds.json",
|
|
263
|
+
"data": "base64-encrypted-blob...",
|
|
264
|
+
"encrypted": true,
|
|
265
|
+
"updatedAt": "2026-03-29T..."
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The `encrypted: true` flag enables a migration path: the system can detect unencrypted documents and refuse to read them after migration is complete.
|
|
270
|
+
|
|
271
|
+
#### Key Management
|
|
272
|
+
|
|
273
|
+
| Concern | Solution |
|
|
274
|
+
|---------|----------|
|
|
275
|
+
| Master key storage | `BAILEYS_AUTH_ENCRYPTION_KEY` in env var -- never in code or DB |
|
|
276
|
+
| Per-account isolation | HKDF derives unique key per `accountId` -- compromise of one does not expose others |
|
|
277
|
+
| Key rotation | New master key -> re-encrypt all documents in a migration script. Old key kept temporarily for rollback |
|
|
278
|
+
| Docker deployment | Pass via `environment` or Docker secrets -- not baked into image |
|
|
279
|
+
| Backup safety | Database dumps are useless without the master key |
|
|
280
|
+
|
|
281
|
+
#### Migration Plan
|
|
282
|
+
|
|
283
|
+
| Step | Action | Location |
|
|
284
|
+
|------|--------|----------|
|
|
285
|
+
| 1 | Add `BAILEYS_AUTH_ENCRYPTION_KEY` env var | Baileys `.env` |
|
|
286
|
+
| 2 | Create `encrypt/decrypt` helpers with HKDF | `baileys/src/utils/crypto.js` |
|
|
287
|
+
| 3 | Wrap `useMongoDBAuthState()` -- encrypt on write, decrypt on read | `baileys/src/utils/use-mongodb-auth-state.js` |
|
|
288
|
+
| 4 | One-time migration script: read all plain docs -> encrypt -> rewrite | Standalone script |
|
|
289
|
+
| 5 | Add `encrypted: true` flag -- reject plain reads after migration | Safety check |
|
|
290
|
+
| 6 | Encrypt file fallback (same AES-256-GCM) | `baileys/src/utils/use-file-auth-state.js` |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 5. QR Code Flow
|
|
295
|
+
|
|
296
|
+
### Connection Sequence
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
Admin UI NestJS API Baileys Gateway Worker WhatsApp
|
|
300
|
+
| | | | |
|
|
301
|
+
|-- Connect --> | | | |
|
|
302
|
+
| (POST | | | |
|
|
303
|
+
| /connect) | | | |
|
|
304
|
+
| |--- cmd: connect --->| | |
|
|
305
|
+
| | | | |
|
|
306
|
+
| | |-- fork worker --->| |
|
|
307
|
+
| | | | |
|
|
308
|
+
| | |-- IPC: init ----->| |
|
|
309
|
+
| | | | |
|
|
310
|
+
| | | |-- Baileys |
|
|
311
|
+
| | | | connect ---->|
|
|
312
|
+
| | | | |
|
|
313
|
+
| | | |<-- QR data ----|
|
|
314
|
+
| | | | |
|
|
315
|
+
| | |<-- IPC: qr -------| |
|
|
316
|
+
| | | | |
|
|
317
|
+
| |<-- evt: qr ---------| | |
|
|
318
|
+
| | (raw QR string) | | |
|
|
319
|
+
| | | | |
|
|
320
|
+
|<-- QR code -----| | | |
|
|
321
|
+
| (checkpoint. | | | |
|
|
322
|
+
| qrcode) | | | |
|
|
323
|
+
| | | | |
|
|
324
|
+
| User scans QR | | | |
|
|
325
|
+
| on their phone | | | |
|
|
326
|
+
| | | | |
|
|
327
|
+
| | | |<-- connected --|
|
|
328
|
+
| | | | |
|
|
329
|
+
| | |<-- IPC: connected-| |
|
|
330
|
+
| | | { phone } | |
|
|
331
|
+
| | | | |
|
|
332
|
+
| |<-- evt: connected --| | |
|
|
333
|
+
| | | | |
|
|
334
|
+
|<-- status ok ---| | | |
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### QR Code Format
|
|
338
|
+
|
|
339
|
+
The QR code is returned as a **raw string** in `checkpoint.qrcode`. The frontend renders it using `QRCodeSVG` from the `qrcode.react` library. It is NOT a data URL or image -- it is the raw data that the QR library encodes.
|
|
340
|
+
|
|
341
|
+
### Timeout
|
|
342
|
+
|
|
343
|
+
- **QR wait timeout:** 30 seconds (`config.qrTimeoutMs`)
|
|
344
|
+
- If the user does not scan in time, the API returns without a QR and the admin must retry
|
|
345
|
+
- **Baileys connection timeout:** 60 seconds (`config.connectTimeoutMs`)
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 6. Connection Management
|
|
350
|
+
|
|
351
|
+
### Auto-Restart
|
|
352
|
+
|
|
353
|
+
When a worker process exits unexpectedly:
|
|
354
|
+
|
|
355
|
+
| Condition | Action |
|
|
356
|
+
|-----------|--------|
|
|
357
|
+
| `status === 'logged_out'` | Do NOT restart -- user logged out or was banned |
|
|
358
|
+
| `status === 'conflict'` | Do NOT restart -- another session is active on this account |
|
|
359
|
+
| Account deleted | Do NOT restart -- clean up worker entry |
|
|
360
|
+
| `restartCount > 5` | Give up -- mark account as `'failed'` |
|
|
361
|
+
| Otherwise | Restart with exponential backoff |
|
|
362
|
+
|
|
363
|
+
### Restart Backoff
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
delay = workerRestartDelayMs * restartCount
|
|
367
|
+
= 3000ms * attempt
|
|
368
|
+
|
|
369
|
+
Attempt 1: 3s
|
|
370
|
+
Attempt 2: 6s
|
|
371
|
+
Attempt 3: 9s
|
|
372
|
+
Attempt 4: 12s
|
|
373
|
+
Attempt 5: 15s
|
|
374
|
+
Attempt 6: Give up (max 5 restarts)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
The `restartCount` resets to 0 on a successful connection (`connected` message received).
|
|
378
|
+
|
|
379
|
+
### Timeout Values
|
|
380
|
+
|
|
381
|
+
| Timeout | Value | Purpose |
|
|
382
|
+
|---------|-------|---------|
|
|
383
|
+
| QR wait | 30s | How long `createAccount` waits for QR before responding |
|
|
384
|
+
| Baileys connect | 60s | Baileys internal connection timeout |
|
|
385
|
+
| Worker restart delay | 3s * attempt | Backoff between restart attempts |
|
|
386
|
+
| Max restarts | 5 | Consecutive failures before giving up |
|
|
387
|
+
| Worker request timeout | 30s | How long gateway waits for worker to respond to a command |
|
|
388
|
+
| Worker shutdown grace | 3s | How long to wait for graceful shutdown before `kill()` |
|
|
389
|
+
|
|
390
|
+
### Account Restoration on Startup
|
|
391
|
+
|
|
392
|
+
On gateway startup, `restoreAll()`:
|
|
393
|
+
|
|
394
|
+
1. Kill any orphaned worker processes from a previous run (`pkill -f worker.js`)
|
|
395
|
+
2. Load all accounts from MongoDB
|
|
396
|
+
3. Filter to `connected` or `disconnected` status (skip `logged_out`, `failed`)
|
|
397
|
+
4. Fork a worker for each restorable account
|
|
398
|
+
5. Workers automatically reconnect using stored auth state
|
|
399
|
+
|
|
400
|
+
### Graceful Shutdown
|
|
401
|
+
|
|
402
|
+
`shutdownAll()` sends `{ type: 'shutdown' }` IPC to all workers, waits up to 3 seconds per worker for exit, then force-kills any remaining processes.
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## 7. Media Cache
|
|
407
|
+
|
|
408
|
+
### Purpose
|
|
409
|
+
|
|
410
|
+
Baileys' `downloadMediaMessage()` requires the **original message object** (containing encryption keys, media URL, etc.). The worker caches incoming media messages in memory so they can be re-downloaded later for forwarding to the doctor.
|
|
411
|
+
|
|
412
|
+
### Implementation
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
// In worker.js
|
|
416
|
+
const messageCache = new Map();
|
|
417
|
+
// Key: message ID (string)
|
|
418
|
+
// Value: { msg: BaileysMessage, contentType: string, timestamp: number }
|
|
419
|
+
|
|
420
|
+
const MESSAGE_CACHE_TTL_MS = 60 * 60 * 1000; // 60 minutes
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Lifecycle
|
|
424
|
+
|
|
425
|
+
1. **Cache on receive:** When `messages.upsert` fires with a media message, the full Baileys message object is stored in `messageCache`
|
|
426
|
+
2. **Forward on demand:** When `forward_media` IPC is received, look up the message, call `downloadMediaMessage()`, send the buffer to the target phone
|
|
427
|
+
3. **TTL cleanup:** Every 5 minutes, entries older than 60 minutes are evicted
|
|
428
|
+
4. **Cache miss:** If the message is not in cache (expired or worker restarted), the forward fails with an error
|
|
429
|
+
|
|
430
|
+
### Target Migration
|
|
431
|
+
|
|
432
|
+
In the NestJS rewrite, media is stored in MinIO on receipt (not just cached in memory). This eliminates the TTL limitation and survives worker restarts. The `forward_media` command reads from MinIO instead of the worker's in-memory cache.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## 8. MongoDB Collections (Baileys-Specific)
|
|
437
|
+
|
|
438
|
+
These collections are used exclusively by the Baileys microservice. They remain in MongoDB even after the main application migrates to PostgreSQL.
|
|
439
|
+
|
|
440
|
+
| Collection | Purpose | TTL | Key Fields |
|
|
441
|
+
|------------|---------|-----|------------|
|
|
442
|
+
| `baileys_auth` | Signal Protocol credentials and keys | None | `accountId`, `filename`, `data`, `encrypted` |
|
|
443
|
+
| `baileys_accounts` | Account metadata (status, phone, timestamps) | None | `accountId`, `status`, `phone`, `createdAt` |
|
|
444
|
+
| `baileys_webhooks` | Registered webhook URLs and secrets | None | `url`, `secret`, `events` |
|
|
445
|
+
| `baileys_message_log` | Message event log (dispatched, filtered, errors) | 7 days | `accountId`, `action`, `messageId`, `timestamp` |
|
|
446
|
+
| `baileys_raw_messages` | Raw Baileys message objects (debug) | 7 days | `accountId`, `remoteJid`, `messageId`, `raw` |
|
|
447
|
+
|
|
448
|
+
### baileys_auth
|
|
449
|
+
|
|
450
|
+
Stores one document per auth state file per account:
|
|
451
|
+
- `_id`: `{accountId}:{filename}` (e.g., `abc-123:creds.json`)
|
|
452
|
+
- `accountId`: account UUID
|
|
453
|
+
- `filename`: auth state file name (e.g., `creds.json`, `pre-key-1.json`)
|
|
454
|
+
- `data`: serialized JSON (currently plain, target: encrypted base64)
|
|
455
|
+
- `encrypted`: boolean flag (target: true after migration)
|
|
456
|
+
|
|
457
|
+
The `useMongoDBAuthState()` utility provides a Baileys-compatible auth state interface backed by these MongoDB documents. It implements `saveCreds()`, `get()`, `set()`, `remove()`, and `keys()`.
|
|
458
|
+
|
|
459
|
+
### baileys_accounts
|
|
460
|
+
|
|
461
|
+
One document per WhatsApp account:
|
|
462
|
+
- `accountId`: UUID
|
|
463
|
+
- `status`: `creating` | `connected` | `disconnected` | `logged_out` | `conflict` | `failed`
|
|
464
|
+
- `phone`: connected phone number (null until connected)
|
|
465
|
+
- `createdAt`: creation timestamp
|
|
466
|
+
|
|
467
|
+
### baileys_webhooks
|
|
468
|
+
|
|
469
|
+
Webhook registrations for dispatching incoming messages to the main application:
|
|
470
|
+
- `url`: webhook endpoint (e.g., `http://nestjs:3005/webhooks/unipile`)
|
|
471
|
+
- `secret`: shared secret sent as `x-unipile-secret` header
|
|
472
|
+
- `events`: array of event types to receive
|
|
473
|
+
|
|
474
|
+
### Message Log and Raw Messages
|
|
475
|
+
|
|
476
|
+
Debug/operational logs with 7-day TTL (MongoDB TTL index):
|
|
477
|
+
- `baileys_message_log`: structured log of message events (dispatched, filtered, send_failed, worker_exit, etc.)
|
|
478
|
+
- `baileys_raw_messages`: full Baileys message objects for debugging protocol issues
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## 9. Composite Chat ID
|
|
483
|
+
|
|
484
|
+
Baileys uses JIDs (Jabber IDs) as chat identifiers (e.g., `905551234567@s.whatsapp.net`). Since the system supports multiple WhatsApp accounts, a composite chat ID is used:
|
|
485
|
+
|
|
486
|
+
```
|
|
487
|
+
Format: {accountId}:{jid}
|
|
488
|
+
Example: abc-123-def:905551234567@s.whatsapp.net
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Why Composite
|
|
492
|
+
|
|
493
|
+
- Multiple accounts may chat with the same phone number
|
|
494
|
+
- The `accountId` prefix routes commands to the correct worker
|
|
495
|
+
- The NestJS side treats the composite ID as an opaque string (same as Unipile's chat IDs)
|
|
496
|
+
|
|
497
|
+
### Parsing
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
function buildChatId(accountId, jid) {
|
|
501
|
+
return `${accountId}:${jid}`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function parseChatId(chatId) {
|
|
505
|
+
const sep = chatId.indexOf(':');
|
|
506
|
+
return {
|
|
507
|
+
accountId: chatId.slice(0, sep),
|
|
508
|
+
jid: chatId.slice(sep + 1),
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## 10. Message Filtering
|
|
516
|
+
|
|
517
|
+
The worker filters out non-conversational messages before dispatching to the gateway. These are filtered:
|
|
518
|
+
|
|
519
|
+
| Filter | Check | Reason |
|
|
520
|
+
|--------|-------|--------|
|
|
521
|
+
| Broadcast messages | `isJidBroadcast(jid)` | Not real conversations |
|
|
522
|
+
| Group messages | `isJidGroup(jid)` | Only 1:1 chats supported |
|
|
523
|
+
| LID users | `isLidUser(jid)` | Internal WhatsApp identifiers |
|
|
524
|
+
| Protocol messages | `messageStubType` present | System events (group changes, etc.) |
|
|
525
|
+
| Status broadcasts | `jid === 'status@broadcast'` | WhatsApp Status stories |
|
|
526
|
+
| Own messages (partial) | `key.fromMe === true` | Echoes are passed through for dedup but flagged as `is_sender: true` |
|
|
527
|
+
|
|
528
|
+
### Content Type Detection
|
|
529
|
+
|
|
530
|
+
The worker uses `getContentType(message)` from Baileys to identify the message type:
|
|
531
|
+
- `conversation` -- plain text
|
|
532
|
+
- `extendedTextMessage` -- text with URL preview or reply
|
|
533
|
+
- `imageMessage` -- photo
|
|
534
|
+
- `videoMessage` -- video
|
|
535
|
+
- `audioMessage` -- voice message
|
|
536
|
+
- `documentMessage` -- file attachment
|
|
537
|
+
- `stickerMessage` -- sticker
|
|
538
|
+
- `contactMessage` -- shared contact
|
|
539
|
+
- `locationMessage` -- GPS location
|
|
540
|
+
|
|
541
|
+
### Text Extraction
|
|
542
|
+
|
|
543
|
+
For text messages: direct text field. For media messages: a Turkish-language label is generated (e.g., `"[Kullanici fotograf gonderdi]"`, `"[Kullanici ses mesaji gonderdi]"`). These labels pass through to the AI agent so it knows media was shared even though text-only mode is used.
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## 11. Webhook Dispatching
|
|
548
|
+
|
|
549
|
+
When a worker sends a `message` event, the gateway dispatches it to all registered webhooks:
|
|
550
|
+
|
|
551
|
+
1. Look up all webhooks from `baileys_webhooks` collection
|
|
552
|
+
2. For each webhook: POST the normalized payload with `x-unipile-secret` header
|
|
553
|
+
3. Retry on failure: 3 attempts with exponential backoff (`1s * 2^attempt`)
|
|
554
|
+
4. Auto-registration: if `WEBHOOK_AUTO_URL` env var is set, a webhook is automatically created on startup
|
|
555
|
+
|
|
556
|
+
The webhook format matches the Unipile format, so the NestJS webhook handler does not need to distinguish between Baileys and Unipile origins.
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## 12. Configuration
|
|
561
|
+
|
|
562
|
+
### Environment Variables
|
|
563
|
+
|
|
564
|
+
| Variable | Default | Description |
|
|
565
|
+
|----------|---------|-------------|
|
|
566
|
+
| `PORT` | `3001` | HTTP server port |
|
|
567
|
+
| `BAILEYS_API_KEY` | -- | API key for REST endpoint authentication |
|
|
568
|
+
| `DATA_DIR` | `./data` | Directory for file-based auth state fallback |
|
|
569
|
+
| `LOG_LEVEL` | `info` | Pino log level |
|
|
570
|
+
| `MONGODB_URI` | -- | MongoDB connection string |
|
|
571
|
+
| `MONGO_USER` | -- | MongoDB username (injected into URI if no credentials present) |
|
|
572
|
+
| `MONGO_PASS` | -- | MongoDB password |
|
|
573
|
+
| `MEDIA_FORWARD_TO` | -- | Dev: auto-forward media messages to this phone |
|
|
574
|
+
| `WEBHOOK_AUTO_URL` | -- | Auto-register this webhook URL on startup |
|
|
575
|
+
| `WEBHOOK_AUTO_SECRET` | -- | Secret for auto-registered webhook |
|
|
576
|
+
| `BAILEYS_AUTH_ENCRYPTION_KEY` | -- | **(Target)** 32-byte hex for auth state encryption |
|
|
577
|
+
|
|
578
|
+
### Timeout Configuration
|
|
579
|
+
|
|
580
|
+
| Config Key | Value | Description |
|
|
581
|
+
|------------|-------|-------------|
|
|
582
|
+
| `qrTimeoutMs` | 30,000 | Max wait for QR code before responding |
|
|
583
|
+
| `connectTimeoutMs` | 60,000 | Baileys connection timeout |
|
|
584
|
+
| `workerRestartDelayMs` | 3,000 | Base delay between worker restart attempts |
|
|
585
|
+
| `workerMaxRestarts` | 5 | Max consecutive restart attempts before giving up |
|
|
586
|
+
| `webhookRetries` | 3 | Max webhook delivery retry attempts |
|
|
587
|
+
| `webhookRetryBaseMs` | 1,000 | Base delay for webhook retry backoff |
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## 13. File Structure
|
|
592
|
+
|
|
593
|
+
```
|
|
594
|
+
baileys/
|
|
595
|
+
server.js # Express app entry point
|
|
596
|
+
worker.js # Baileys worker process (forked per account)
|
|
597
|
+
package.json
|
|
598
|
+
.env
|
|
599
|
+
data/ # File-based auth state fallback (per-account dirs)
|
|
600
|
+
src/
|
|
601
|
+
config.js # Configuration with MongoDB URI builder
|
|
602
|
+
middleware/
|
|
603
|
+
api-key.js # API key validation middleware
|
|
604
|
+
routes/
|
|
605
|
+
accounts.js # Account CRUD: create, reconnect, status, disconnect
|
|
606
|
+
chats.js # Chat operations: send, forward-media, send-image, download-audio, start-chat
|
|
607
|
+
webhooks.js # Webhook registration CRUD
|
|
608
|
+
services/
|
|
609
|
+
account-store.js # MongoDB account persistence + file system helpers
|
|
610
|
+
webhook-dispatcher.js # HTTP webhook delivery with retry
|
|
611
|
+
worker-manager.js # Worker lifecycle: fork, IPC, auto-restart, request-reply
|
|
612
|
+
utils/
|
|
613
|
+
jid.js # JID-to-phone conversion, text extraction, media labels
|
|
614
|
+
logger.js # Pino logger configuration
|
|
615
|
+
use-mongodb-auth-state.js # Baileys auth state adapter for MongoDB
|
|
616
|
+
```
|