diff --git a/src/controllers/whatsapp-webhook.controller.ts b/src/controllers/whatsapp-webhook.controller.ts new file mode 100644 index 00000000..015a2be9 --- /dev/null +++ b/src/controllers/whatsapp-webhook.controller.ts @@ -0,0 +1,81 @@ +import { Body, Controller, HttpCode, HttpStatus, Logger, Post, Req } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { Request } from 'express'; +import { Auth } from 'src/decorators/auth.decorator'; +import { Public } from 'src/decorators/public.decorator'; +import { AuthType } from 'src/enums/auth-type.enum'; + +@Auth(AuthType.None) +@Controller('webhook/whatsapp') +@ApiTags('Solid Core') +export class WhatsappWebhookController { + private readonly logger = new Logger(WhatsappWebhookController.name); + + @Public() + @Post() + @HttpCode(HttpStatus.OK) + async receiveWebhook(@Req() req: Request, @Body() body: unknown) { + const userAgent = req.headers['user-agent'] ?? null; + this.logger.log(`Received WhatsApp webhook${userAgent ? ` from ${userAgent}` : ''}`); + this.logger.debug(`WhatsApp webhook payload: ${JSON.stringify(body)}`); + + const statusInfo = this.extractStatusInfo(body); + if (statusInfo) { + this.logger.log( + `WhatsApp delivery update: status=${statusInfo.status ?? 'unknown'}, messageId=${statusInfo.messageId ?? 'n/a'}, destination=${statusInfo.destination ?? 'n/a'}, reason=${statusInfo.reason ?? 'n/a'}`, + ); + } + + // Always acknowledge webhook receipt to avoid provider retries. + return { + success: true, + message: 'Webhook received', + }; + } + + private extractStatusInfo(body: unknown): { + status?: string; + messageId?: string; + destination?: string; + reason?: string; + } | null { + if (!body || typeof body !== 'object') { + return null; + } + + const payload = body as Record; + + const status = + this.asString(payload.status) || + this.asString(payload.messageStatus) || + this.asString((payload.payload as Record)?.status); + + const messageId = + this.asString(payload.messageId) || + this.asString(payload.id) || + this.asString((payload.payload as Record)?.id) || + this.asString((payload.payload as Record)?.messageId); + + const destination = + this.asString(payload.destination) || + this.asString(payload.phone) || + this.asString((payload.payload as Record)?.destination) || + this.asString((payload.payload as Record)?.phone); + + const reason = + this.asString(payload.reason) || + this.asString(payload.error) || + this.asString((payload.payload as Record)?.reason) || + this.asString((payload.payload as Record)?.error); + + if (!status && !messageId && !destination && !reason) { + return null; + } + + return { status, messageId, destination, reason }; + } + + private asString(value: unknown): string | undefined { + return typeof value === 'string' && value.trim() ? value.trim() : undefined; + } +} diff --git a/src/listeners/user-registration.listener.ts b/src/listeners/user-registration.listener.ts index 9915aa83..5bd800ad 100755 --- a/src/listeners/user-registration.listener.ts +++ b/src/listeners/user-registration.listener.ts @@ -1,7 +1,11 @@ import { User } from "../entities/user.entity"; import { OnEvent } from "@nestjs/event-emitter"; import { Injectable, Logger } from "@nestjs/common"; +import { OnEvent } from "@nestjs/event-emitter"; +import { AxiosError } from "axios"; +import { WhatsAppFactory } from "src/factories/whatsapp.factory"; import { EventDetails, EventType } from "../interfaces"; +import { User } from "../entities/user.entity"; import { WhatsAppFactory } from "src/factories/whatsapp.factory"; @Injectable() @@ -14,6 +18,45 @@ export class UserRegistrationListener { async handleUserRegistration(event: EventDetails) { this.logger.log(`User registered with details: ${JSON.stringify(event.payload)}`); + const to = + process.env.WHATSAPP_EVENT_NOTIFY_TO || + process.env.COMMON_WHATSAPP_EVENT_NOTIFY_TO; + + if (!to) { + this.logger.debug( + "Skipping WhatsApp registration notification. Set WHATSAPP_EVENT_NOTIFY_TO or COMMON_WHATSAPP_EVENT_NOTIFY_TO.", + ); + return; + } + + const userName = event?.payload?.username || event?.payload?.email || "User"; + + try { + const whatsappService = this.whatsAppFactory.getWhatsappService(); + await whatsappService.sendWhatsAppMessage(to, null, { + payload: { + channel: "whatsapp", + source: + process.env.COMMON_GUPSHUP_WHATSAPP_SOURCE || + process.env.GUPSHUP_SOURCE_NUMBER, + destination: to, + "src.name": process.env.COMMON_GUPSHUP_APP_NAME || "solidx", + message: { + type: "text", + text: `New user registered: ${userName}`, + }, + }, + }); + + this.logger.log(`Sent registration WhatsApp notification to ${to}`); + } catch (error) { + const axiosError = error as AxiosError; + const status = axiosError.response?.status; + const responseData = axiosError.response?.data; + const genericError = error as Error; + + this.logger.error( + `Failed to send registration WhatsApp notification to ${to}. status=${status ?? 'unknown'}, response=${typeof responseData === 'object' ? JSON.stringify(responseData) : responseData}, message=${genericError?.message ?? 'unknown'}, stack=${genericError?.stack ?? 'n/a'}`, const notifyTo = process.env.WHATSAPP_EVENT_NOTIFY_TO; if (!notifyTo) { this.logger.debug("WHATSAPP_EVENT_NOTIFY_TO not set. Skipping registration WhatsApp notification."); diff --git a/src/services/authentication.service.ts b/src/services/authentication.service.ts index 4d46daa2..2920663d 100755 --- a/src/services/authentication.service.ts +++ b/src/services/authentication.service.ts @@ -378,6 +378,9 @@ export class AuthenticationService { // Send welcome notifications (email/SMS) if enabled. await this.notifyUserOnSignup(user); + + // Emit registration event for all successful standard signups as well. + this.triggerRegistrationEvent(user); } generatePassword(length: number = 8): string { diff --git a/src/services/settings/default-settings-provider.service.ts b/src/services/settings/default-settings-provider.service.ts index bdb7d4f3..eb6fe220 100644 --- a/src/services/settings/default-settings-provider.service.ts +++ b/src/services/settings/default-settings-provider.service.ts @@ -1218,6 +1218,16 @@ const getSolidCoreSettings = (isProd: boolean) => sortOrder: 30, controlType: "shortText", }, + + //gupshup-settings-provider.service.ts + { + moduleName: "solid-core", + key: "gupShupAppName", + value: process.env.COMMON_GUPSHUP_APP_NAME, + level: SettingLevel.SystemAdminReadonly, + label: "Gupshup App Name", + group: "gupshup-settings", + sortOrder: 10, { moduleName: "solid-core", key: "metaWhatsappApiUrl", @@ -1230,6 +1240,12 @@ const getSolidCoreSettings = (isProd: boolean) => }, { moduleName: "solid-core", + key: "gupshupApiUrl", + value: process.env.COMMON_GUPSHUP_API_URL, + level: SettingLevel.SystemAdminReadonly, + label: "Gupshup API URL", + group: "gupshup-settings", + sortOrder: 10, key: "metaWhatsappApiVersion", value: process.env.COMMON_META_WHATSAPP_API_VERSION || "v23.0", level: SettingLevel.SystemAdminReadonly, @@ -1240,6 +1256,12 @@ const getSolidCoreSettings = (isProd: boolean) => }, { moduleName: "solid-core", + key: "gupshupWhatsappProvider", + value: process.env.COMMON_WHATSAPP_PROVIDER, + level: SettingLevel.SystemAdminReadonly, + label: "Gupshup WhatsApp Provider", + group: "gupshup-settings", + sortOrder: 10, key: "metaWhatsappPhoneNumberId", value: process.env.COMMON_META_WHATSAPP_PHONE_NUMBER_ID, level: SettingLevel.SystemAdminReadonly, @@ -1250,6 +1272,12 @@ const getSolidCoreSettings = (isProd: boolean) => }, { moduleName: "solid-core", + key: "gupshupWhatsappApiKey", + value: process.env.COMMON_GUPSHUP_WHATSAPP_API_KEY, + level: SettingLevel.SystemEnv, + label: "Gupshup API Key", + group: "gupshup-settings", + sortOrder: 10, key: "metaWhatsappBusinessAccountId", value: process.env.COMMON_META_WHATSAPP_BUSINESS_ACCOUNT_ID, level: SettingLevel.SystemAdminReadonly, @@ -1260,6 +1288,23 @@ const getSolidCoreSettings = (isProd: boolean) => }, { moduleName: "solid-core", + key: "gupshupWhatsappSource", + value: process.env.COMMON_GUPSHUP_WHATSAPP_SOURCE, + level: SettingLevel.SystemEnv, + label: "Gupshup WhatsApp Source", + group: "gupshup-settings", + sortOrder: 10, + controlType: "shortText", + }, + { + moduleName: "solid-core", + key: "gupshupNotifyTo", + value: process.env.WHATSAPP_EVENT_NOTIFY_TO, + level: SettingLevel.SystemEnv, + label: "Gupshup Notify To", + group: "gupshup-settings", + sortOrder: 10, + controlType: "shortText", key: "metaWhatsappAccessToken", value: process.env.COMMON_META_WHATSAPP_ACCESS_TOKEN, level: SettingLevel.SystemEnv, diff --git a/src/services/whatsapp/GupshupWhatsappService.ts b/src/services/whatsapp/GupshupWhatsappService.ts new file mode 100644 index 00000000..b3e7a5ac --- /dev/null +++ b/src/services/whatsapp/GupshupWhatsappService.ts @@ -0,0 +1,119 @@ +import { HttpService } from '@nestjs/axios'; +import { Injectable, Logger } from '@nestjs/common'; +import { AxiosError } from 'axios'; +import { QueueMessage } from 'src/interfaces/mq'; +import { IWhatsAppTransport } from '../../interfaces'; +import { WhatsAppProvider } from 'src/decorators/whatsapp-provider.decorator'; + +@Injectable() +@WhatsAppProvider() +export class GupshupWhatsappService implements IWhatsAppTransport { + readonly logger = new Logger(GupshupWhatsappService.name); + + constructor(private readonly httpService: HttpService) {} + + async sendWhatsAppMessage( + to: string, + templateId: string, + parameters: any, + parentEntity?: any, + parentEntityId?: any, + ): Promise { + const message = { + payload: { + to, + templateId, + ...parameters, + }, + parentEntity, + parentEntityId, + }; + + await this.sendWhatsAppMessageSynchronously(message); + return message; + } + + async sendWhatsAppMessageSynchronously(message: QueueMessage): Promise { + const requestBody = this.createWhatsappRequest(message); + + const apiKey = + process.env.COMMON_GUPSHUP_WHATSAPP_API_KEY || process.env.GUPSHUP_API_KEY; + const url = + process.env.COMMON_GUPSHUP_WHATSAPP_API_URL || process.env.GUPSHUP_API_URL; + + if (!apiKey || !url) { + throw new Error('Missing Gupshup configuration: API key or URL'); + } + + const isWaEndpoint = url.includes('/wa/api/v1/msg'); + + try { + if (isWaEndpoint) { + const form = this.toWaFormEncoded(requestBody); + await this.httpService.axiosRef.post(url, form.toString(), { + headers: { + apikey: apiKey, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }); + } else { + await this.httpService.axiosRef.post(url, requestBody, { + headers: { + apikey: apiKey, + 'Content-Type': 'application/json', + }, + }); + } + + this.logger.debug( + `Sent Gupshup WhatsApp message to ${message.payload.to} using ${isWaEndpoint ? 'wa' : 'json'} endpoint`, + ); + } catch (error) { + const axiosError = error as AxiosError; + const status = axiosError.response?.status; + const responseData = axiosError.response?.data; + + this.logger.error( + `Gupshup send failed: status=${status ?? 'unknown'}, url=${url}, response=${typeof responseData === 'object' ? JSON.stringify(responseData) : responseData}`, + ); + + throw error; + } + } + + private createWhatsappRequest(message: QueueMessage): any { + const { to, templateId, ...parameters } = message.payload; + const source = + process.env.COMMON_GUPSHUP_WHATSAPP_SOURCE || process.env.GUPSHUP_SOURCE_NUMBER; + + if (parameters?.payload) { + return parameters.payload; + } + + return { + channel: 'whatsapp', + source, + destination: to, + message: { + type: 'template', + template: { + id: templateId, + params: parameters, + }, + }, + }; + } + + private toWaFormEncoded(payload: Record): URLSearchParams { + const params = new URLSearchParams(); + const appName = process.env.COMMON_GUPSHUP_APP_NAME || 'solidx'; + + params.append('channel', payload.channel || 'whatsapp'); + params.append('source', payload.source || ''); + params.append('destination', payload.destination || ''); + params.append('src.name', payload['src.name'] || appName); + params.append('message', JSON.stringify(payload.message || {})); + + return params; + } +} diff --git a/src/solid-core.module.ts b/src/solid-core.module.ts index a2a640d5..3042a217 100755 --- a/src/solid-core.module.ts +++ b/src/solid-core.module.ts @@ -184,67 +184,66 @@ import { DashboardQuestionController } from "./controllers/dashboard-question.co import { DashboardVariableController } from "./controllers/dashboard-variable.controller"; import { DashboardLayoutController } from "./controllers/dashboard-layout.controller"; -import { DashboardController } from './controllers/dashboard.controller'; -import { ExportTemplateController } from './controllers/export-template.controller'; -import { ExportTransactionController } from './controllers/export-transaction.controller'; -import { ImportTransactionErrorLogController } from './controllers/import-transaction-error-log.controller'; -import { ImportTransactionController } from './controllers/import-transaction.controller'; -import { ListOfValuesController } from './controllers/list-of-values.controller'; -import { LocaleController } from './controllers/locale.controller'; -import { RoleMetadataController } from './controllers/role-metadata.controller'; -import { SavedFiltersController } from './controllers/saved-filters.controller'; -import { ScheduledJobController } from './controllers/scheduled-job.controller'; -import { AgentSessionController } from './controllers/agent-session.controller'; -import { AgentEventController } from './controllers/agent-event.controller'; -import { McpAuditLogController } from './controllers/mcp-audit-log.controller'; -import { SecurityRuleController } from './controllers/security-rule.controller'; -import { SettingController } from './controllers/setting.controller'; -import { InfoController } from './controllers/info.controller'; -import { InfoService } from './services/info.service'; -import { UserActivityHistoryController } from './controllers/user-activity-history.controller'; -import { UserViewMetadataController } from './controllers/user-view-metadata.controller'; -import { UserController } from './controllers/user.controller'; -import { AiInteraction } from './entities/ai-interaction.entity'; -import { ChatterMessageDetails } from './entities/chatter-message-details.entity'; -import { ChatterMessage } from './entities/chatter-message.entity'; -import { DashboardQuestionSqlDatasetConfig } from './entities/dashboard-question-sql-dataset-config.entity'; -import { DashboardQuestion } from './entities/dashboard-question.entity'; -import { DashboardVariable } from './entities/dashboard-variable.entity'; -import { DashboardLayout } from './entities/dashboard-layout.entity'; +import { DashboardController } from "./controllers/dashboard.controller"; +import { ExportTemplateController } from "./controllers/export-template.controller"; +import { ExportTransactionController } from "./controllers/export-transaction.controller"; +import { ImportTransactionErrorLogController } from "./controllers/import-transaction-error-log.controller"; +import { ImportTransactionController } from "./controllers/import-transaction.controller"; +import { ListOfValuesController } from "./controllers/list-of-values.controller"; +import { LocaleController } from "./controllers/locale.controller"; +import { RoleMetadataController } from "./controllers/role-metadata.controller"; +import { SavedFiltersController } from "./controllers/saved-filters.controller"; +import { ScheduledJobController } from "./controllers/scheduled-job.controller"; +import { AgentSessionController } from "./controllers/agent-session.controller"; +import { AgentEventController } from "./controllers/agent-event.controller"; +import { SecurityRuleController } from "./controllers/security-rule.controller"; +import { SettingController } from "./controllers/setting.controller"; +import { InfoController } from "./controllers/info.controller"; +import { WhatsappWebhookController } from "./controllers/whatsapp-webhook.controller"; +import { InfoService } from "./services/info.service"; +import { UserActivityHistoryController } from "./controllers/user-activity-history.controller"; +import { UserViewMetadataController } from "./controllers/user-view-metadata.controller"; +import { UserController } from "./controllers/user.controller"; +import { AiInteraction } from "./entities/ai-interaction.entity"; +import { ChatterMessageDetails } from "./entities/chatter-message-details.entity"; +import { ChatterMessage } from "./entities/chatter-message.entity"; +import { DashboardQuestionSqlDatasetConfig } from "./entities/dashboard-question-sql-dataset-config.entity"; +import { DashboardQuestion } from "./entities/dashboard-question.entity"; +import { DashboardVariable } from "./entities/dashboard-variable.entity"; +import { DashboardLayout } from "./entities/dashboard-layout.entity"; -import { Dashboard } from './entities/dashboard.entity'; -import { ExportTemplate } from './entities/export-template.entity'; -import { ExportTransaction } from './entities/export-transaction.entity'; -import { ImportTransactionErrorLog } from './entities/import-transaction-error-log.entity'; -import { ImportTransaction } from './entities/import-transaction.entity'; -import { Locale } from './entities/locale.entity'; -import { RoleMetadata } from './entities/role-metadata.entity'; -import { SavedFilters } from './entities/saved-filters.entity'; -import { ScheduledJob } from './entities/scheduled-job.entity'; -import { AgentSession } from './entities/agent-session.entity'; -import { AgentEvent } from './entities/agent-event.entity'; -import { McpAuditLog } from './entities/mcp-audit-log.entity'; -import { SecurityRule } from './entities/security-rule.entity'; -import { Setting } from './entities/setting.entity'; -import { UserActivityHistory } from './entities/user-activity-history.entity'; -import { UserViewMetadata } from './entities/user-view-metadata.entity'; -import { UserApiKey } from './entities/user-api-key.entity'; -import { User } from './entities/user.entity'; -import { HttpExceptionFilter } from './filters/http-exception.filter'; -import { ModelMetadataHelperService } from './helpers/model-metadata-helper.service'; -import { ModuleMetadataHelperService } from './helpers/module-metadata-helper.service'; -import { ApiEmailQueuePublisherDatabase } from './jobs/database/api-email-publisher-database.service'; -import { ApiEmailQueueSubscriberDatabase } from './jobs/database/api-email-subscriber-database.service'; -import { ComputedFieldEvaluationPublisherDatabase } from './jobs/database/computed-field-evaluation-publisher-database.service'; -import { ComputedFieldEvaluationSubscriberDatabase } from './jobs/database/computed-field-evaluation-subscriber-database.service'; -import { GenerateCodePublisherDatabase } from './jobs/database/generate-code-publisher-database.service'; -import { GenerateCodeSubscriberDatabase } from './jobs/database/generate-code-subscriber-database.service'; -import { OTPQueuePublisherDatabase } from './jobs/database/otp-publisher-database.service'; -import { OTPQueueSubscriberDatabase } from './jobs/database/otp-subscriber-database.service'; -import { Msg91SmsQueuePublisherDatabase } from './jobs/database/msg91-sms-publisher-database.service'; -import { Msg91SmsQueueSubscriberDatabase } from './jobs/database/msg91-sms-subscriber-database.service'; -import { SmtpEmailQueuePublisherDatabase } from './jobs/database/smtp-email-publisher-database.service'; -import { SmtpEmailQueueSubscriberDatabase } from './jobs/database/smtp-email-subscriber-database.service'; +import { Dashboard } from "./entities/dashboard.entity"; +import { ExportTemplate } from "./entities/export-template.entity"; +import { ExportTransaction } from "./entities/export-transaction.entity"; +import { ImportTransactionErrorLog } from "./entities/import-transaction-error-log.entity"; +import { ImportTransaction } from "./entities/import-transaction.entity"; +import { Locale } from "./entities/locale.entity"; +import { RoleMetadata } from "./entities/role-metadata.entity"; +import { SavedFilters } from "./entities/saved-filters.entity"; +import { ScheduledJob } from "./entities/scheduled-job.entity"; +import { AgentSession } from "./entities/agent-session.entity"; +import { AgentEvent } from "./entities/agent-event.entity"; +import { SecurityRule } from "./entities/security-rule.entity"; +import { Setting } from "./entities/setting.entity"; +import { UserActivityHistory } from "./entities/user-activity-history.entity"; +import { UserViewMetadata } from "./entities/user-view-metadata.entity"; +import { UserApiKey } from "./entities/user-api-key.entity"; +import { User } from "./entities/user.entity"; +import { HttpExceptionFilter } from "./filters/http-exception.filter"; +import { ModelMetadataHelperService } from "./helpers/model-metadata-helper.service"; +import { ModuleMetadataHelperService } from "./helpers/module-metadata-helper.service"; +import { ApiEmailQueuePublisherDatabase } from "./jobs/database/api-email-publisher-database.service"; +import { ApiEmailQueueSubscriberDatabase } from "./jobs/database/api-email-subscriber-database.service"; +import { ComputedFieldEvaluationPublisherDatabase } from "./jobs/database/computed-field-evaluation-publisher-database.service"; +import { ComputedFieldEvaluationSubscriberDatabase } from "./jobs/database/computed-field-evaluation-subscriber-database.service"; +import { GenerateCodePublisherDatabase } from "./jobs/database/generate-code-publisher-database.service"; +import { GenerateCodeSubscriberDatabase } from "./jobs/database/generate-code-subscriber-database.service"; +import { OTPQueuePublisherDatabase } from "./jobs/database/otp-publisher-database.service"; +import { OTPQueueSubscriberDatabase } from "./jobs/database/otp-subscriber-database.service"; +import { Msg91SmsQueuePublisherDatabase } from "./jobs/database/msg91-sms-publisher-database.service"; +import { Msg91SmsQueueSubscriberDatabase } from "./jobs/database/msg91-sms-subscriber-database.service"; +import { SmtpEmailQueuePublisherDatabase } from "./jobs/database/smtp-email-publisher-database.service"; +import { SmtpEmailQueueSubscriberDatabase } from "./jobs/database/smtp-email-subscriber-database.service"; import { TwilioSmsQueuePublisherDatabase } from "./jobs/database/twilio-sms-publisher-database.service"; import { TwilioSmsQueueSubscriberDatabase } from "./jobs/database/twilio-sms-subscriber-database.service"; @@ -282,124 +281,123 @@ import { DashboardVariableRepository } from "./repository/dashboard-variable.rep import { DashboardRepository } from "./repository/dashboard.repository"; import { DashboardLayoutRepository } from "./repository/dashboard-layout.repository"; -import { EmailTemplateRepository } from './repository/email-template.repository'; -import { ExportTemplateRepository } from './repository/export-template.repository'; -import { ExportTransactionRepository } from './repository/export-transaction.repository'; -import { FieldMetadataRepository } from './repository/field-metadata.repository'; -import { ImportTransactionErrorLogRepository } from './repository/import-transaction-error-log.repository'; -import { ImportTransactionRepository } from './repository/import-transaction.repository'; -import { ListOfValuesRepository } from './repository/list-of-values.repository'; -import { LocaleRepository } from './repository/locale.repository'; -import { MediaRepository } from './repository/media.repository'; -import { MenuItemMetadataRepository } from './repository/menu-item-metadata.repository'; -import { ModelMetadataRepository } from './repository/model-metadata.repository'; -import { ModuleMetadataRepository } from './repository/module-metadata.repository'; -import { MqMessageQueueRepository } from './repository/mq-message-queue.repository'; -import { MqMessageRepository } from './repository/mq-message.repository'; -import { PermissionMetadataRepository } from './repository/permission-metadata.repository'; -import { RoleMetadataRepository } from './repository/role-metadata.repository'; -import { SavedFiltersRepository } from './repository/saved-filters.repository'; -import { ScheduledJobRepository } from './repository/scheduled-job.repository'; -import { AgentSessionRepository } from './repository/agent-session.repository'; -import { AgentEventRepository } from './repository/agent-event.repository'; -import { McpAuditLogRepository } from './repository/mcp-audit-log.repository'; -import { SecurityRuleRepository } from './repository/security-rule.repository'; -import { SettingRepository } from './repository/setting.repository'; -import { SmsTemplateRepository } from './repository/sms-template.repository'; -import { UserActivityHistoryRepository } from './repository/user-activity-history.repository'; -import { UserViewMetadataRepository } from './repository/user-view-metadata.repository'; -import { UserApiKeyRepository } from './repository/user-api-key.repository'; -import { UserRepository } from './repository/user.repository'; -import { ViewMetadataRepository } from './repository/view-metadata.repository'; -import { PermissionMetadataSeederService } from './seeders/permission-metadata-seeder.service'; -import { SystemFieldsSeederService } from './seeders/system-fields-seeder.service'; -import { AiInteractionService } from './services/ai-interaction.service'; -import { ChatterMessageDetailsService } from './services/chatter-message-details.service'; -import { ChatterMessageService } from './services/chatter-message.service'; -import { ConcatComputedFieldProvider } from './services/computed-fields/concat-computed-field-provider.service'; -import { AlphaNumExternalIdComputationProvider } from './services/computed-fields/entity/alpha-num-external-id-computed-field-provider'; -import { ConcatEntityComputedFieldProvider } from './services/computed-fields/entity/concat-entity-computed-field-provider.service'; -import { NoopsEntityComputedFieldProviderService } from './services/computed-fields/entity/noops-entity-computed-field-provider.service'; -import { CRUDService } from './services/crud.service'; -import { CsvService } from './services/csv.service'; -import { DashboardQuestionSqlDatasetConfigService } from './services/dashboard-question-sql-dataset-config.service'; -import { DashboardQuestionService } from './services/dashboard-question.service'; -import { DashboardVariableSQLDynamicProvider } from './services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service'; -import { DasbhoardVariableTestDynamicProvider } from './services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service'; -import { DashboardVariableService } from './services/dashboard-variable.service'; -import { DashboardService } from './services/dashboard.service'; -import { DashboardLayoutService } from './services/dashboard-layout.service'; +import { EmailTemplateRepository } from "./repository/email-template.repository"; +import { ExportTemplateRepository } from "./repository/export-template.repository"; +import { ExportTransactionRepository } from "./repository/export-transaction.repository"; +import { FieldMetadataRepository } from "./repository/field-metadata.repository"; +import { ImportTransactionErrorLogRepository } from "./repository/import-transaction-error-log.repository"; +import { ImportTransactionRepository } from "./repository/import-transaction.repository"; +import { ListOfValuesRepository } from "./repository/list-of-values.repository"; +import { LocaleRepository } from "./repository/locale.repository"; +import { MediaRepository } from "./repository/media.repository"; +import { MenuItemMetadataRepository } from "./repository/menu-item-metadata.repository"; +import { ModelMetadataRepository } from "./repository/model-metadata.repository"; +import { ModuleMetadataRepository } from "./repository/module-metadata.repository"; +import { MqMessageQueueRepository } from "./repository/mq-message-queue.repository"; +import { MqMessageRepository } from "./repository/mq-message.repository"; +import { PermissionMetadataRepository } from "./repository/permission-metadata.repository"; +import { RoleMetadataRepository } from "./repository/role-metadata.repository"; +import { SavedFiltersRepository } from "./repository/saved-filters.repository"; +import { ScheduledJobRepository } from "./repository/scheduled-job.repository"; +import { AgentSessionRepository } from "./repository/agent-session.repository"; +import { AgentEventRepository } from "./repository/agent-event.repository"; +import { SecurityRuleRepository } from "./repository/security-rule.repository"; +import { SettingRepository } from "./repository/setting.repository"; +import { SmsTemplateRepository } from "./repository/sms-template.repository"; +import { UserActivityHistoryRepository } from "./repository/user-activity-history.repository"; +import { UserViewMetadataRepository } from "./repository/user-view-metadata.repository"; +import { UserApiKeyRepository } from "./repository/user-api-key.repository"; +import { UserRepository } from "./repository/user.repository"; +import { ViewMetadataRepository } from "./repository/view-metadata.repository"; +import { PermissionMetadataSeederService } from "./seeders/permission-metadata-seeder.service"; +import { SystemFieldsSeederService } from "./seeders/system-fields-seeder.service"; +import { AiInteractionService } from "./services/ai-interaction.service"; +import { ChatterMessageDetailsService } from "./services/chatter-message-details.service"; +import { ChatterMessageService } from "./services/chatter-message.service"; +import { ConcatComputedFieldProvider } from "./services/computed-fields/concat-computed-field-provider.service"; +import { AlphaNumExternalIdComputationProvider } from "./services/computed-fields/entity/alpha-num-external-id-computed-field-provider"; +import { ConcatEntityComputedFieldProvider } from "./services/computed-fields/entity/concat-entity-computed-field-provider.service"; +import { NoopsEntityComputedFieldProviderService } from "./services/computed-fields/entity/noops-entity-computed-field-provider.service"; +import { CRUDService } from "./services/crud.service"; +import { CsvService } from "./services/csv.service"; +import { DashboardQuestionSqlDatasetConfigService } from "./services/dashboard-question-sql-dataset-config.service"; +import { DashboardQuestionService } from "./services/dashboard-question.service"; +import { DashboardVariableSQLDynamicProvider } from "./services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service"; +import { DasbhoardVariableTestDynamicProvider } from "./services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service"; +import { DashboardVariableService } from "./services/dashboard-variable.service"; +import { DashboardService } from "./services/dashboard.service"; +import { DashboardLayoutService } from "./services/dashboard-layout.service"; -import { ExcelService } from './services/excel.service'; -import { ExportTemplateService } from './services/export-template.service'; -import { ExportTransactionService } from './services/export-transaction.service'; -import { IngestMetadataService } from './services/genai/ingest-metadata.service'; -import { McpHandlerFactory } from './services/genai/mcp-handlers/mcp-handler-factory.service'; -import { R2RHelperService } from './services/genai/r2r-helper.service'; -import { ImportTransactionErrorLogService } from './services/import-transaction-error-log.service'; -import { ImportTransactionService } from './services/import-transaction.service'; -import { LocaleService } from './services/locale.service'; -import { FileS3StorageProvider } from './services/mediaStorageProviders/file-s3-storage-provider'; -import { FileStorageProvider } from './services/mediaStorageProviders/file-storage-provider'; -import { PollerService } from './services/poller.service'; -import { ChartJsSqlDataProvider } from './services/question-data-providers/chartjs-sql-data-provider.service'; -import { PrimeReactDatatableSqlDataProvider } from './services/question-data-providers/prime-react-datatable-sql-data-provider.service'; -import { PrimeReactMeterGroupSqlDataProvider } from './services/question-data-providers/prime-react-meter-group-sql-data-provider.service'; -import { PublisherFactory } from './services/queues/publisher-factory.service'; -import { RequestContextService } from './services/request-context.service'; -import { RoleMetadataService } from './services/role-metadata.service'; -import { SavedFiltersService } from './services/saved-filters.service'; -import { ScheduledJobService } from './services/scheduled-job.service'; -import { AgentSessionService } from './services/agent-session.service'; -import { AgentEventService } from './services/agent-event.service'; -import { McpAuditLogService } from './services/mcp-audit-log.service'; -import { SchedulerServiceImpl } from './services/scheduled-jobs/scheduler.service'; -import { SecurityRuleService } from './services/security-rule.service'; -import { ListOfDashboardQuestionProvidersSelectionProvider } from './services/selection-providers/list-of-dashboard-question-providers-selection-provider.service'; -import { ListOfDashboardVariableProvidersSelectionProvider } from './services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service'; -import { ListOfScheduledJobsSelectionProvider } from './services/selection-providers/list-of-scheduled-jobs-selection-provider.service'; -import { LocaleListSelectionProvider } from './services/selection-providers/locale-list-selection-provider.service'; -import { SettingService } from './services/setting.service'; -import { TwilioSMSService } from './services/sms/TwilioSMSService'; -import { SolidTsMorphService } from './services/solid-ts-morph.service'; -import { SqlExpressionResolverService } from './services/sql-expression-resolver.service'; -import { TextractService } from './services/textract.service'; -import { UserActivityHistoryService } from './services/user-activity-history.service'; -import { UserViewMetadataService } from './services/user-view-metadata.service'; -import { UserService } from './services/user.service'; -import { Three60WhatsappService } from './services/whatsapp/Three60WhatsappService'; -import { AuditSubscriber } from './subscribers/audit.subscriber'; -import { ComputedEntityFieldSubscriber } from './subscribers/computed-entity-field.subscriber'; -import { CreatedByUpdatedBySubscriber } from './subscribers/created-by-updated-by.subscriber'; -import { DashboardQuestionSqlDatasetConfigSubscriber } from './subscribers/dashboard-question-sql-dataset-config.subscriber'; -import { DashboardQuestionSubscriber } from './subscribers/dashboard-question.subscriber'; -import { DashboardVariableSubscriber } from './subscribers/dashboard-variable.subscriber'; -import { DashboardSubscriber } from './subscribers/dashboard.subscriber'; -import { ListOfValuesSubscriber } from './subscribers/list-of-values.subscriber'; -import { ScheduledJobSubscriber } from './subscribers/scheduled-job.subscriber'; -import { SecurityRuleSubscriber } from './subscribers/security-rule.subscriber'; -import { ViewMetadataSubsciber } from './subscribers/view-metadata.subscriber'; -import { MediaStorageProviderMetadataRepository } from './repository/media-storage-provider-metadata.repository'; -import { McpCommand } from './commands/mcp.command'; -import { FixturesService } from './services/fixtures.service'; -import { FixturesSetupCommand } from './commands/fixtures/fixtures-setup.command'; -import { FixturesTearDownCommand } from './commands/fixtures/fixtures-tear-down.command'; -import { DatabaseBootstrapService } from './services/database/database-bootstrap.service'; -import { SequenceNumComputedFieldProvider } from './services/computed-fields/entity/sequence-num-computed-field-provider'; -import { ModelSequence } from './entities/model-sequence.entity'; -import { ModelSequenceService } from './services/model-sequence.service'; -import { ModelSequenceController } from './controllers/model-sequence.controller'; -import { ModelSequenceRepository } from './repository/model-sequence.repository'; -import { CacheModule } from '@nestjs/cache-manager'; -import { CacheManagerOptions } from './config/cache.options'; -import { SolidCoreDefaultSettingsProvider } from './services/settings/default-settings-provider.service'; -import { SmsFactory } from './factories/sms.factory'; -import { WhatsAppFactory } from './factories/whatsapp.factory'; -import { ImageEncodingService } from './helpers/image-encoding.helper'; -import { SolidMicroserviceAdapter } from './helpers/solid-microservice-adapter.service'; -import { InfoCommand } from './commands/info.command'; -import { ListOfRolesSelectionProvider } from './services/selection-providers/list-of-roles-selectionproviders.service'; -import { Entity } from 'typeorm'; +import { ExcelService } from "./services/excel.service"; +import { ExportTemplateService } from "./services/export-template.service"; +import { ExportTransactionService } from "./services/export-transaction.service"; +import { IngestMetadataService } from "./services/genai/ingest-metadata.service"; +import { McpHandlerFactory } from "./services/genai/mcp-handlers/mcp-handler-factory.service"; +import { R2RHelperService } from "./services/genai/r2r-helper.service"; +import { ImportTransactionErrorLogService } from "./services/import-transaction-error-log.service"; +import { ImportTransactionService } from "./services/import-transaction.service"; +import { LocaleService } from "./services/locale.service"; +import { FileS3StorageProvider } from "./services/mediaStorageProviders/file-s3-storage-provider"; +import { FileStorageProvider } from "./services/mediaStorageProviders/file-storage-provider"; +import { PollerService } from "./services/poller.service"; +import { ChartJsSqlDataProvider } from "./services/question-data-providers/chartjs-sql-data-provider.service"; +import { PrimeReactDatatableSqlDataProvider } from "./services/question-data-providers/prime-react-datatable-sql-data-provider.service"; +import { PrimeReactMeterGroupSqlDataProvider } from "./services/question-data-providers/prime-react-meter-group-sql-data-provider.service"; +import { PublisherFactory } from "./services/queues/publisher-factory.service"; +import { RequestContextService } from "./services/request-context.service"; +import { RoleMetadataService } from "./services/role-metadata.service"; +import { SavedFiltersService } from "./services/saved-filters.service"; +import { ScheduledJobService } from "./services/scheduled-job.service"; +import { AgentSessionService } from "./services/agent-session.service"; +import { AgentEventService } from "./services/agent-event.service"; +import { SchedulerServiceImpl } from "./services/scheduled-jobs/scheduler.service"; +import { SecurityRuleService } from "./services/security-rule.service"; +import { ListOfDashboardQuestionProvidersSelectionProvider } from "./services/selection-providers/list-of-dashboard-question-providers-selection-provider.service"; +import { ListOfDashboardVariableProvidersSelectionProvider } from "./services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service"; +import { ListOfScheduledJobsSelectionProvider } from "./services/selection-providers/list-of-scheduled-jobs-selection-provider.service"; +import { LocaleListSelectionProvider } from "./services/selection-providers/locale-list-selection-provider.service"; +import { SettingService } from "./services/setting.service"; +import { TwilioSMSService } from "./services/sms/TwilioSMSService"; +import { SolidTsMorphService } from "./services/solid-ts-morph.service"; +import { SqlExpressionResolverService } from "./services/sql-expression-resolver.service"; +import { TextractService } from "./services/textract.service"; +import { UserActivityHistoryService } from "./services/user-activity-history.service"; +import { UserViewMetadataService } from "./services/user-view-metadata.service"; +import { UserService } from "./services/user.service"; +import { Three60WhatsappService } from "./services/whatsapp/Three60WhatsappService"; +import { AuditSubscriber } from "./subscribers/audit.subscriber"; +import { ComputedEntityFieldSubscriber } from "./subscribers/computed-entity-field.subscriber"; +import { CreatedByUpdatedBySubscriber } from "./subscribers/created-by-updated-by.subscriber"; +import { DashboardQuestionSqlDatasetConfigSubscriber } from "./subscribers/dashboard-question-sql-dataset-config.subscriber"; +import { DashboardQuestionSubscriber } from "./subscribers/dashboard-question.subscriber"; +import { DashboardVariableSubscriber } from "./subscribers/dashboard-variable.subscriber"; +import { DashboardSubscriber } from "./subscribers/dashboard.subscriber"; +import { ListOfValuesSubscriber } from "./subscribers/list-of-values.subscriber"; +import { ScheduledJobSubscriber } from "./subscribers/scheduled-job.subscriber"; +import { SecurityRuleSubscriber } from "./subscribers/security-rule.subscriber"; +import { ViewMetadataSubsciber } from "./subscribers/view-metadata.subscriber"; +import { MediaStorageProviderMetadataRepository } from "./repository/media-storage-provider-metadata.repository"; +import { McpCommand } from "./commands/mcp.command"; +import { FixturesService } from "./services/fixtures.service"; +import { FixturesSetupCommand } from "./commands/fixtures/fixtures-setup.command"; +import { FixturesTearDownCommand } from "./commands/fixtures/fixtures-tear-down.command"; +import { DatabaseBootstrapService } from "./services/database/database-bootstrap.service"; +import { SequenceNumComputedFieldProvider } from "./services/computed-fields/entity/sequence-num-computed-field-provider"; +import { ModelSequence } from "./entities/model-sequence.entity"; +import { ModelSequenceService } from "./services/model-sequence.service"; +import { ModelSequenceController } from "./controllers/model-sequence.controller"; +import { ModelSequenceRepository } from "./repository/model-sequence.repository"; +import { CacheModule } from "@nestjs/cache-manager"; +import { CacheManagerOptions } from "./config/cache.options"; +import { SolidCoreDefaultSettingsProvider } from "./services/settings/default-settings-provider.service"; +import { SmsFactory } from "./factories/sms.factory"; +import { WhatsAppFactory } from "./factories/whatsapp.factory"; +import { GupshupWhatsappService } from "./services/whatsapp/GupshupWhatsappService"; +import { ImageEncodingService } from "./helpers/image-encoding.helper"; +import { SolidMicroserviceAdapter } from "./helpers/solid-microservice-adapter.service"; +import { InfoCommand } from "./commands/info.command"; +import { ListOfRolesSelectionProvider } from "./services/selection-providers/list-of-roles-selectionproviders.service"; +import { Entity } from "typeorm"; @Global() @Module({ @@ -522,6 +520,7 @@ import { Entity } from 'typeorm'; ServiceController, SettingController, InfoController, + WhatsappWebhookController, SmsTemplateController, TestController, TestQueueController, @@ -647,6 +646,7 @@ import { Entity } from 'typeorm'; Msg91WhatsappQueueSubscriberDatabase, Three60WhatsappQueuePublisher, Three60WhatsappQueueSubscriber, + GupshupWhatsappService, Three60WhatsappQueuePublisherDatabase, Three60WhatsappQueueSubscriberDatabase, Three60WhatsappService,