rez_core 2.3.1 → 2.3.4

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.
Files changed (151) hide show
  1. package/dist/app.module.js +2 -0
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/module/enterprise/repository/school.repository.js +0 -1
  4. package/dist/module/enterprise/repository/school.repository.js.map +1 -1
  5. package/dist/module/filter/repository/saved-filter.repository.js +0 -1
  6. package/dist/module/filter/repository/saved-filter.repository.js.map +1 -1
  7. package/dist/module/integration/controller/integration.controller.d.ts +8 -1
  8. package/dist/module/integration/controller/integration.controller.js +22 -0
  9. package/dist/module/integration/controller/integration.controller.js.map +1 -1
  10. package/dist/module/integration/dto/create-config.dto.d.ts +7 -0
  11. package/dist/module/integration/dto/create-config.dto.js +29 -1
  12. package/dist/module/integration/dto/create-config.dto.js.map +1 -1
  13. package/dist/module/integration/factories/sms.factory.d.ts +9 -1
  14. package/dist/module/integration/factories/sms.factory.js +36 -4
  15. package/dist/module/integration/factories/sms.factory.js.map +1 -1
  16. package/dist/module/integration/factories/whatsapp.factory.d.ts +5 -1
  17. package/dist/module/integration/factories/whatsapp.factory.js +14 -2
  18. package/dist/module/integration/factories/whatsapp.factory.js.map +1 -1
  19. package/dist/module/integration/integration.module.js +10 -0
  20. package/dist/module/integration/integration.module.js.map +1 -1
  21. package/dist/module/integration/service/integration.service.d.ts +7 -0
  22. package/dist/module/integration/service/integration.service.js +51 -0
  23. package/dist/module/integration/service/integration.service.js.map +1 -1
  24. package/dist/module/integration/strategies/sms/gupshup-sms.strategy.d.ts +9 -0
  25. package/dist/module/integration/strategies/sms/gupshup-sms.strategy.js +104 -0
  26. package/dist/module/integration/strategies/sms/gupshup-sms.strategy.js.map +1 -0
  27. package/dist/module/integration/strategies/sms/msg91-sms.strategy.d.ts +9 -0
  28. package/dist/module/integration/strategies/sms/msg91-sms.strategy.js +113 -0
  29. package/dist/module/integration/strategies/sms/msg91-sms.strategy.js.map +1 -0
  30. package/dist/module/integration/strategies/sms/tubelight-sms.strategy.d.ts +9 -0
  31. package/dist/module/integration/strategies/sms/tubelight-sms.strategy.js +109 -0
  32. package/dist/module/integration/strategies/sms/tubelight-sms.strategy.js.map +1 -0
  33. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.d.ts +7 -2
  34. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.js +52 -5
  35. package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.js.map +1 -1
  36. package/dist/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.d.ts +19 -0
  37. package/dist/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.js +257 -0
  38. package/dist/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.js.map +1 -0
  39. package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.d.ts +22 -0
  40. package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.js +295 -0
  41. package/dist/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.js.map +1 -0
  42. package/dist/module/layout_preference/service/layout_preference.service.js +0 -2
  43. package/dist/module/layout_preference/service/layout_preference.service.js.map +1 -1
  44. package/dist/module/listmaster/service/list-master.service.js +0 -1
  45. package/dist/module/listmaster/service/list-master.service.js.map +1 -1
  46. package/dist/module/mapper/controller/field-mapper.controller.d.ts +6 -0
  47. package/dist/module/mapper/controller/field-mapper.controller.js +45 -0
  48. package/dist/module/mapper/controller/field-mapper.controller.js.map +1 -0
  49. package/dist/module/mapper/dto/field-mapper.dto.d.ts +11 -0
  50. package/dist/module/mapper/dto/field-mapper.dto.js +8 -0
  51. package/dist/module/mapper/dto/field-mapper.dto.js.map +1 -0
  52. package/dist/module/mapper/entity/field-lovs.entity.d.ts +7 -0
  53. package/dist/module/mapper/entity/field-lovs.entity.js +38 -0
  54. package/dist/module/mapper/entity/field-lovs.entity.js.map +1 -0
  55. package/dist/module/mapper/entity/field-mapper.entity.d.ts +12 -0
  56. package/dist/module/mapper/entity/field-mapper.entity.js +58 -0
  57. package/dist/module/mapper/entity/field-mapper.entity.js.map +1 -0
  58. package/dist/module/mapper/mapper.module.d.ts +2 -0
  59. package/dist/module/mapper/mapper.module.js +38 -0
  60. package/dist/module/mapper/mapper.module.js.map +1 -0
  61. package/dist/module/mapper/repository/field-lovs.repository.d.ts +8 -0
  62. package/dist/module/mapper/repository/field-lovs.repository.js +41 -0
  63. package/dist/module/mapper/repository/field-lovs.repository.js.map +1 -0
  64. package/dist/module/mapper/repository/field-mapper.repository.d.ts +9 -0
  65. package/dist/module/mapper/repository/field-mapper.repository.js +42 -0
  66. package/dist/module/mapper/repository/field-mapper.repository.js.map +1 -0
  67. package/dist/module/mapper/service/field-mapper.service.d.ts +16 -0
  68. package/dist/module/mapper/service/field-mapper.service.js +92 -0
  69. package/dist/module/mapper/service/field-mapper.service.js.map +1 -0
  70. package/dist/module/master/service/master.service.js +0 -2
  71. package/dist/module/master/service/master.service.js.map +1 -1
  72. package/dist/module/meta/repository/entity-table.repository.js +0 -1
  73. package/dist/module/meta/repository/entity-table.repository.js.map +1 -1
  74. package/dist/module/meta/service/entity-dynamic.service.js +0 -1
  75. package/dist/module/meta/service/entity-dynamic.service.js.map +1 -1
  76. package/dist/module/meta/service/entity-service-impl.service.js +0 -2
  77. package/dist/module/meta/service/entity-service-impl.service.js.map +1 -1
  78. package/dist/module/meta/service/entity-table.service.js +0 -2
  79. package/dist/module/meta/service/entity-table.service.js.map +1 -1
  80. package/dist/module/meta/service/field-group.service.js +0 -1
  81. package/dist/module/meta/service/field-group.service.js.map +1 -1
  82. package/dist/module/module/service/module-access.service.js +0 -6
  83. package/dist/module/module/service/module-access.service.js.map +1 -1
  84. package/dist/module/notification/service/email.service.js +0 -1
  85. package/dist/module/notification/service/email.service.js.map +1 -1
  86. package/dist/module/user/service/login.service.js +0 -1
  87. package/dist/module/user/service/login.service.js.map +1 -1
  88. package/dist/module/workflow/entity/action.entity.d.ts +2 -0
  89. package/dist/module/workflow/entity/action.entity.js +8 -0
  90. package/dist/module/workflow/entity/action.entity.js.map +1 -1
  91. package/dist/module/workflow/repository/stage.repository.js +0 -1
  92. package/dist/module/workflow/repository/stage.repository.js.map +1 -1
  93. package/dist/module/workflow/service/action.service.js +0 -1
  94. package/dist/module/workflow/service/action.service.js.map +1 -1
  95. package/dist/module/workflow/service/comm-template.service.js +0 -1
  96. package/dist/module/workflow/service/comm-template.service.js.map +1 -1
  97. package/dist/module/workflow/service/populate-workflow.service.js +0 -5
  98. package/dist/module/workflow/service/populate-workflow.service.js.map +1 -1
  99. package/dist/module/workflow/service/task.service.js +0 -1
  100. package/dist/module/workflow/service/task.service.js.map +1 -1
  101. package/dist/module/workflow/service/workflow-meta.service.js +0 -2
  102. package/dist/module/workflow/service/workflow-meta.service.js.map +1 -1
  103. package/dist/module/workflow-automation/service/workflow-automation-engine.service.js +0 -1
  104. package/dist/module/workflow-automation/service/workflow-automation-engine.service.js.map +1 -1
  105. package/dist/tsconfig.build.tsbuildinfo +1 -1
  106. package/docs/modules/integration.md +55 -1
  107. package/package.json +1 -1
  108. package/src/app.module.ts +2 -0
  109. package/src/module/enterprise/repository/school.repository.ts +0 -1
  110. package/src/module/filter/repository/saved-filter.repository.ts +0 -1
  111. package/src/module/integration/controller/integration.controller.ts +24 -0
  112. package/src/module/integration/dto/create-config.dto.ts +22 -0
  113. package/src/module/integration/factories/sms.factory.ts +39 -6
  114. package/src/module/integration/factories/whatsapp.factory.ts +10 -0
  115. package/src/module/integration/integration.module.ts +14 -0
  116. package/src/module/integration/service/integration.service.ts +107 -0
  117. package/src/module/integration/strategies/sms/gupshup-sms.strategy.ts +146 -0
  118. package/src/module/integration/strategies/sms/msg91-sms.strategy.ts +164 -0
  119. package/src/module/integration/strategies/sms/tubelight-sms.strategy.ts +163 -0
  120. package/src/module/integration/strategies/telephone/ozonetel-voice.strategy.ts +80 -7
  121. package/src/module/integration/strategies/whatsapp/gupshup-whatsapp.strategy.ts +360 -0
  122. package/src/module/integration/strategies/whatsapp/tubelight-whatsapp.strategy.ts +419 -0
  123. package/src/module/layout_preference/service/layout_preference.service.ts +0 -2
  124. package/src/module/listmaster/service/list-master.service.ts +1 -10
  125. package/src/module/mapper/controller/field-mapper.controller.ts +19 -0
  126. package/src/module/mapper/dto/field-mapper.dto.ts +14 -0
  127. package/src/module/mapper/entity/field-lovs.entity.ts +21 -0
  128. package/src/module/mapper/entity/field-mapper.entity.ts +36 -0
  129. package/src/module/mapper/mapper.module.ts +26 -0
  130. package/src/module/mapper/repository/field-lovs.repository.ts +22 -0
  131. package/src/module/mapper/repository/field-mapper.repository.ts +27 -0
  132. package/src/module/mapper/service/field-mapper.service.ts +91 -0
  133. package/src/module/master/service/master.service.ts +0 -2
  134. package/src/module/meta/repository/entity-table.repository.ts +0 -1
  135. package/src/module/meta/service/entity-dynamic.service.ts +1 -5
  136. package/src/module/meta/service/entity-service-impl.service.ts +0 -4
  137. package/src/module/meta/service/entity-table.service.ts +0 -2
  138. package/src/module/meta/service/field-group.service.ts +0 -1
  139. package/src/module/module/service/module-access.service.ts +0 -13
  140. package/src/module/notification/service/email.service.ts +0 -1
  141. package/src/module/user/service/login.service.ts +0 -1
  142. package/src/module/workflow/entity/action.entity.ts +6 -0
  143. package/src/module/workflow/repository/stage.repository.ts +1 -2
  144. package/src/module/workflow/service/action.service.ts +0 -1
  145. package/src/module/workflow/service/comm-template.service.ts +0 -1
  146. package/src/module/workflow/service/populate-workflow.service.ts +2 -12
  147. package/src/module/workflow/service/task.service.ts +0 -1
  148. package/src/module/workflow/service/workflow-meta.service.ts +1 -4
  149. package/src/module/workflow-automation/service/workflow-automation-engine.service.ts +0 -1
  150. package/src/resources/dev.properties.yaml +1 -1
  151. package/.vscode/extensions.json +0 -5
@@ -139,7 +139,7 @@ export class IntegrationService {
139
139
  ```json
140
140
  {
141
141
  "app_code": "MYAPP",
142
- "integration_type": "WA",
142
+ "integration_type": "WA",
143
143
  "integration_provider": "whatsapp",
144
144
  "integration_source_id": 3,
145
145
  "config_json": {
@@ -150,6 +150,60 @@ export class IntegrationService {
150
150
  }
151
151
  ```
152
152
 
153
+ ### Gupshup WhatsApp
154
+ ```json
155
+ {
156
+ "app_code": "MYAPP",
157
+ "integration_type": "WA",
158
+ "integration_provider": "gupshup",
159
+ "integration_source_id": 4,
160
+ "config_json": {
161
+ "apiKey": "your-gupshup-api-key",
162
+ "appName": "your-app-name",
163
+ "sourceNumber": "your-source-number",
164
+ "baseUrl": "https://api.gupshup.io/sm/api/v1"
165
+ }
166
+ }
167
+ ```
168
+
169
+ **Gupshup Message Types:**
170
+ - **Text Message**: Default type, just send message
171
+ - **Template**: Requires `messageType: "template"`, `templateId`, optional `templateParams`
172
+ - **Image**: Requires `messageType: "image"`, `mediaUrl`, optional `previewUrl`, `caption`
173
+ - **Document**: Requires `messageType: "document"`, `mediaUrl`, optional `filename`, `caption`
174
+ - **Audio**: Requires `messageType: "audio"`, `mediaUrl`
175
+ - **Video**: Requires `messageType: "video"`, `mediaUrl`, optional `caption`
176
+ - **Location**: Requires `messageType: "location"`, `latitude`, `longitude`, optional `locationName`, `locationAddress`
177
+ - **List**: Requires `messageType: "list"`, `listItems`, optional `listTitle`, `globalButtons`
178
+ - **Quick Reply**: Requires `messageType: "quick_reply"`, `quickReplyOptions`
179
+
180
+ ### Tubelight WhatsApp
181
+ ```json
182
+ {
183
+ "app_code": "MYAPP",
184
+ "integration_type": "WA",
185
+ "integration_provider": "tubelight",
186
+ "integration_source_id": 5,
187
+ "config_json": {
188
+ "userName": "your-tubelight-username",
189
+ "password": "your-tubelight-password",
190
+ "tenantId": "your-tenant-id",
191
+ "sourceNumber": "your-source-number",
192
+ "baseUrl": "https://portal.tubelightcommunications.com/whatsapp/api/v1"
193
+ }
194
+ }
195
+ ```
196
+
197
+ **Tubelight Message Types:**
198
+ - **Text Message**: Default type with `messageType: "TEXT"` or no messageType specified
199
+ - **Template**: Requires `messageType: "template"`, `templateId`, optional `templateParams`, `templateLanguage` (default: "en")
200
+ - **Image**: Requires `messageType: "image"`, `mediaUrl`, optional `caption`
201
+ - **Document**: Requires `messageType: "document"`, `mediaUrl`, optional `filename`, `caption`
202
+ - **Audio**: Requires `messageType: "audio"`, `mediaUrl`
203
+ - **Video**: Requires `messageType: "video"`, `mediaUrl`, optional `caption`
204
+ - **Location**: Requires `messageType: "location"`, `latitude`, `longitude`, optional `locationName`, `locationAddress`
205
+ - **Interactive**: Requires `messageType: "interactive"`, `interactiveType` ("button" or "list"), optional `buttons`, `sections`, `header`, `footer`
206
+
153
207
  ### Knowlarity Voice
154
208
  ```json
155
209
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.3.1",
3
+ "version": "2.3.4",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
package/src/app.module.ts CHANGED
@@ -19,6 +19,7 @@ import { DashboardModule } from './module/dashboard/dashboard.module';
19
19
  import { IntegrationModule } from './module/integration/integration.module';
20
20
  import { ScheduleModule } from '@nestjs/schedule';
21
21
  import { AuthModule } from './module/auth/auth.module';
22
+ import { MapperModule } from './module/mapper/mapper.module';
22
23
 
23
24
  @Module({
24
25
  imports: [
@@ -41,6 +42,7 @@ import { AuthModule } from './module/auth/auth.module';
41
42
  DashboardModule,
42
43
  IntegrationModule,
43
44
  AuthModule,
45
+ MapperModule,
44
46
  ScheduleModule.forRoot(),
45
47
  ],
46
48
  })
@@ -37,7 +37,6 @@ export class SchoolRepository {
37
37
  .andWhere('urm.level_type = :levelType', { levelType: 'ORG' })
38
38
  .getRawMany();
39
39
 
40
- console.log('hasOrgAccess', hasOrgAccess);
41
40
 
42
41
  let currentORGLevel_id = hasOrgAccess[0]?.urm_level_id;
43
42
  if (hasOrgAccess[0]?.urm_level_id == 1) {
@@ -35,7 +35,6 @@ export class SavedFilterRepositoryService {
35
35
  }
36
36
 
37
37
  async getDetailsByCode(code: string): Promise<SavedFilterDetail[]> {
38
- console.log("IN GET DETAILS BY CODE", code);
39
38
  return this.savedFilterDetailRepo.find({
40
39
  where: { mapped_filter_code: code },
41
40
  });
@@ -15,6 +15,7 @@ import {
15
15
  import { IntegrationService } from '../service/integration.service';
16
16
  import {
17
17
  BulkMessageDto,
18
+ CheckAgentStatusDto,
18
19
  CreateConfigDto,
19
20
  CreateUserIntegrationDto,
20
21
  GenericSendMessageDto,
@@ -69,6 +70,29 @@ export class IntegrationController {
69
70
  return this.integrationService.sendTemplateMessage(templateMessage);
70
71
  }
71
72
 
73
+ @Post('check-agent-status')
74
+ @HttpCode(HttpStatus.OK)
75
+ async checkAgentStatus(@Body() checkAgentStatusDto: CheckAgentStatusDto) {
76
+ try {
77
+ const result = await this.integrationService.checkAgentStatus(
78
+ checkAgentStatusDto.levelId,
79
+ checkAgentStatusDto.levelType,
80
+ checkAgentStatusDto.app_code,
81
+ checkAgentStatusDto.user_id,
82
+ checkAgentStatusDto.type || 'TELEPHONE',
83
+ );
84
+
85
+ return result;
86
+ } catch (error) {
87
+ throw new BadRequestException({
88
+ success: false,
89
+ error: 'CHECK_AGENT_STATUS_ERROR',
90
+ message: error.message || 'Failed to check agent status',
91
+ code: 'AGENT_STATUS_ERROR',
92
+ });
93
+ }
94
+ }
95
+
72
96
  @Post('config')
73
97
  @HttpCode(HttpStatus.OK)
74
98
  async createConfig(@Body() createConfigDto: CreateConfigDto) {
@@ -473,3 +473,25 @@ export class UpdateUserIntegrationDto {
473
473
  @IsBoolean()
474
474
  is_active?: boolean;
475
475
  }
476
+
477
+ export class CheckAgentStatusDto {
478
+ @IsNotEmpty()
479
+ @IsNumber()
480
+ levelId: number;
481
+
482
+ @IsNotEmpty()
483
+ @IsString()
484
+ levelType: string;
485
+
486
+ @IsNotEmpty()
487
+ @IsString()
488
+ app_code: string;
489
+
490
+ @IsNotEmpty()
491
+ @IsNumber()
492
+ user_id: number;
493
+
494
+ @IsOptional()
495
+ @IsIn(['TELEPHONE'])
496
+ type?: 'TELEPHONE';
497
+ }
@@ -1,19 +1,52 @@
1
1
  import { Injectable } from '@nestjs/common';
2
+ import { BaseFactory } from './base.factory';
2
3
  import { IntegrationStrategy } from '../strategies/integration.strategy';
4
+ import { GupshupSmsStrategy } from '../strategies/sms/gupshup-sms.strategy';
5
+ import { TubelightSmsStrategy } from '../strategies/sms/tubelight-sms.strategy';
6
+ import { Msg91SmsStrategy } from '../strategies/sms/msg91-sms.strategy';
3
7
 
4
8
  @Injectable()
5
- export class SmsFactory {
9
+ export class SmsFactory implements BaseFactory {
10
+ constructor(
11
+ private gupshupSmsStrategy: GupshupSmsStrategy,
12
+ private tubelightSmsStrategy: TubelightSmsStrategy,
13
+ private msg91SmsStrategy: Msg91SmsStrategy,
14
+ ) {}
15
+
6
16
  createProvider(service: string, provider: string): IntegrationStrategy {
7
- throw new Error(`SMS integration is not supported. Provider: ${provider}, Service: ${service}`);
17
+ const key = `${service.toLowerCase()}_${provider.toLowerCase()}`;
18
+
19
+ switch (key) {
20
+ case 'api_gupshup':
21
+ case 'sms_gupshup':
22
+ return this.gupshupSmsStrategy;
23
+ case 'api_tubelight':
24
+ case 'sms_tubelight':
25
+ return this.tubelightSmsStrategy;
26
+ case 'api_msg91':
27
+ case 'sms_msg91':
28
+ return this.msg91SmsStrategy;
29
+
30
+ default:
31
+ throw new Error(
32
+ `Unsupported SMS service/provider: ${service}/${provider}`,
33
+ );
34
+ }
8
35
  }
9
36
 
10
37
  getSupportedCombinations(): Array<{ service: string; provider: string }> {
11
- // Return empty array since no SMS strategies are supported
12
- return [];
38
+ return [
39
+ { service: 'API', provider: 'gupshup' },
40
+ { service: 'API', provider: 'tubelight' },
41
+ { service: 'API', provider: 'msg91' },
42
+ ];
13
43
  }
14
44
 
15
45
  validateCombination(service: string, provider: string): boolean {
16
- // No SMS combinations are valid since we removed all strategies
17
- return false;
46
+ return this.getSupportedCombinations().some(
47
+ (combo) =>
48
+ combo.service.toLowerCase() === service.toLowerCase() &&
49
+ combo.provider.toLowerCase() === provider.toLowerCase(),
50
+ );
18
51
  }
19
52
  }
@@ -3,12 +3,16 @@ import { BaseFactory } from './base.factory';
3
3
  import { IntegrationStrategy } from '../strategies/integration.strategy';
4
4
  import { WhatsAppStrategy } from '../strategies/whatsapp/whatsapp.strategy';
5
5
  import { WhatsAppCloudStrategy } from '../strategies/whatsapp/whatsapp-cloud.strategy';
6
+ import { GupshupWhatsAppStrategy } from '../strategies/whatsapp/gupshup-whatsapp.strategy';
7
+ import { TubelightWhatsAppStrategy } from '../strategies/whatsapp/tubelight-whatsapp.strategy';
6
8
 
7
9
  @Injectable()
8
10
  export class WhatsAppFactory implements BaseFactory {
9
11
  constructor(
10
12
  private whatsappStrategy: WhatsAppStrategy,
11
13
  private whatsappCloudStrategy: WhatsAppCloudStrategy,
14
+ private gupshupWhatsAppStrategy: GupshupWhatsAppStrategy,
15
+ private tubelightWhatsAppStrategy: TubelightWhatsAppStrategy,
12
16
  ) {}
13
17
 
14
18
  createProvider(service: string, provider: string): IntegrationStrategy {
@@ -20,6 +24,10 @@ export class WhatsAppFactory implements BaseFactory {
20
24
  case 'api_whatsapp-cloud':
21
25
  case 'api_meta':
22
26
  return this.whatsappCloudStrategy;
27
+ case 'api_gupshup':
28
+ return this.gupshupWhatsAppStrategy;
29
+ case 'api_tubelight':
30
+ return this.tubelightWhatsAppStrategy;
23
31
 
24
32
  default:
25
33
  throw new Error(
@@ -33,6 +41,8 @@ export class WhatsAppFactory implements BaseFactory {
33
41
  { service: 'API', provider: 'whatsapp' },
34
42
  { service: 'API', provider: 'whatsapp-cloud' },
35
43
  { service: 'API', provider: 'meta' },
44
+ { service: 'API', provider: 'gupshup' },
45
+ { service: 'API', provider: 'tubelight' },
36
46
  ];
37
47
  }
38
48
 
@@ -17,6 +17,13 @@ import { SendGridApiStrategy } from './strategies/email/sendgrid-api.strategy';
17
17
  import { WhatsAppCloudStrategy } from './strategies/whatsapp/whatsapp-cloud.strategy';
18
18
  import { OzonetelVoiceStrategy } from './strategies/telephone/ozonetel-voice.strategy';
19
19
  import { TubelightVoiceStrategy } from './strategies/telephone/tubelight-voice.strategy';
20
+ import { GupshupWhatsAppStrategy } from './strategies/whatsapp/gupshup-whatsapp.strategy';
21
+ import { TubelightWhatsAppStrategy } from './strategies/whatsapp/tubelight-whatsapp.strategy';
22
+
23
+ // SMS Strategies
24
+ import { GupshupSmsStrategy } from './strategies/sms/gupshup-sms.strategy';
25
+ import { TubelightSmsStrategy } from './strategies/sms/tubelight-sms.strategy';
26
+ import { Msg91SmsStrategy } from './strategies/sms/msg91-sms.strategy';
20
27
 
21
28
  // New unified strategies
22
29
  import { OutlookStrategy } from './strategies/email/outlook.strategy';
@@ -61,6 +68,13 @@ import { UserIntegration } from './entity/user-integration.entity';
61
68
  WhatsAppCloudStrategy,
62
69
  OzonetelVoiceStrategy,
63
70
  TubelightVoiceStrategy,
71
+ GupshupWhatsAppStrategy,
72
+ TubelightWhatsAppStrategy,
73
+
74
+ // SMS Strategies
75
+ GupshupSmsStrategy,
76
+ TubelightSmsStrategy,
77
+ Msg91SmsStrategy,
64
78
 
65
79
  // New unified strategies
66
80
  OutlookStrategy,
@@ -2164,4 +2164,111 @@ export class IntegrationService {
2164
2164
  return null;
2165
2165
  }
2166
2166
  }
2167
+
2168
+ /**
2169
+ * Check agent status for TELEPHONE integration
2170
+ * Currently supports: Ozonetel
2171
+ */
2172
+ async checkAgentStatus(
2173
+ levelId: number,
2174
+ levelType: string,
2175
+ appCode: string,
2176
+ userId: number,
2177
+ integrationType: 'TELEPHONE' = 'TELEPHONE',
2178
+ ): Promise<{
2179
+ success: boolean;
2180
+ isReady?: boolean;
2181
+ state?: string;
2182
+ agentInfo?: any;
2183
+ error?: string;
2184
+ }> {
2185
+ try {
2186
+ // Get the active configuration
2187
+ const config = await this.getSingleActiveConfig(
2188
+ levelId,
2189
+ levelType,
2190
+ appCode,
2191
+ integrationType,
2192
+ );
2193
+
2194
+ if (!config) {
2195
+ return {
2196
+ success: false,
2197
+ error: 'No active TELEPHONE configuration found',
2198
+ };
2199
+ }
2200
+
2201
+ // Get user integration mapping
2202
+ const userIntegration = await this.getUserIntegrationByUserAndConfig(
2203
+ userId,
2204
+ config.id,
2205
+ );
2206
+
2207
+ if (!userIntegration) {
2208
+ return {
2209
+ success: false,
2210
+ error: 'User integration mapping not found. Please configure agent details.',
2211
+ };
2212
+ }
2213
+
2214
+ // Create strategy instance
2215
+ const strategy = this.integrationFactory.create(
2216
+ config.integration_type,
2217
+ 'API', // service is deprecated, using default
2218
+ config.integration_provider,
2219
+ );
2220
+
2221
+ // Get the merged config with user data
2222
+ let mergedConfig = config.config_json;
2223
+
2224
+ if (strategy.createUserSpecificConfig) {
2225
+ mergedConfig = strategy.createUserSpecificConfig(
2226
+ config.config_json,
2227
+ userIntegration.external_user_id,
2228
+ );
2229
+ }
2230
+
2231
+ // Check if strategy is Ozonetel (currently only Ozonetel supports status check)
2232
+ if (config.integration_provider.toLowerCase() === 'ozonetel') {
2233
+ const ozonetelStrategy = strategy as any;
2234
+
2235
+ // Generate token
2236
+ const token = await ozonetelStrategy.generateToken(mergedConfig);
2237
+ if (!token) {
2238
+ return {
2239
+ success: false,
2240
+ error: 'Failed to authenticate with telephone provider',
2241
+ };
2242
+ }
2243
+
2244
+ // Check agent status
2245
+ const statusResult = await ozonetelStrategy.checkAgentStatus(
2246
+ mergedConfig,
2247
+ token,
2248
+ );
2249
+
2250
+ return {
2251
+ success: true,
2252
+ isReady: statusResult.isReady,
2253
+ state: statusResult.state,
2254
+ error: statusResult.error,
2255
+ };
2256
+ }
2257
+
2258
+ // For other providers, return not supported
2259
+ return {
2260
+ success: false,
2261
+ error: `Agent status check not supported for provider: ${config.integration_provider}`,
2262
+ };
2263
+ } catch (error) {
2264
+ this.logger.error(
2265
+ `Error checking agent status: ${error.message}`,
2266
+ error.stack,
2267
+ );
2268
+ return {
2269
+ success: false,
2270
+ error: error.message || 'Failed to check agent status',
2271
+ };
2272
+ }
2273
+ }
2167
2274
  }
@@ -0,0 +1,146 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import axios, { AxiosResponse } from 'axios';
3
+ import {
4
+ IntegrationStrategy,
5
+ IntegrationResult,
6
+ } from '../integration.strategy';
7
+
8
+ interface GupshupSmsConfig {
9
+ apiKey: string;
10
+ sourceNumber: string;
11
+ baseUrl?: string;
12
+ method?: string; // 'SendMessage' or 'SendSMS'
13
+ }
14
+
15
+ interface GupshupSmsApiResponse {
16
+ status: string;
17
+ messageId?: string;
18
+ response?: {
19
+ id: string;
20
+ phone: string;
21
+ details: string;
22
+ };
23
+ error?: {
24
+ code: number;
25
+ message: string;
26
+ };
27
+ }
28
+
29
+ @Injectable()
30
+ export class GupshupSmsStrategy implements IntegrationStrategy {
31
+ private readonly logger = new Logger(GupshupSmsStrategy.name);
32
+ private readonly defaultBaseUrl = 'https://enterprise.smsgupshup.com/GatewayAPI/rest';
33
+
34
+ async sendMessage(
35
+ to: string,
36
+ message: string,
37
+ config: any,
38
+ ): Promise<IntegrationResult> {
39
+ try {
40
+ if (!this.validateConfig(config)) {
41
+ throw new Error('Invalid Gupshup SMS configuration');
42
+ }
43
+
44
+ const gupshupConfig = config as GupshupSmsConfig;
45
+ const baseUrl = gupshupConfig.baseUrl || this.defaultBaseUrl;
46
+ const method = gupshupConfig.method || 'SendMessage';
47
+
48
+ const params = new URLSearchParams();
49
+ params.append('method', method);
50
+ params.append('send_to', this.formatPhoneNumber(to));
51
+ params.append('msg', message);
52
+ params.append('msg_type', 'TEXT');
53
+ params.append('userid', gupshupConfig.apiKey);
54
+ params.append('auth_scheme', 'plain');
55
+ params.append('v', '1.1');
56
+ params.append('format', 'text');
57
+
58
+ const url = `${baseUrl}?${params.toString()}`;
59
+
60
+ const response: AxiosResponse = await axios.get(url, {
61
+ timeout: 30000,
62
+ });
63
+
64
+ // Gupshup SMS API returns text response like: "success | message-id"
65
+ const responseText = response.data?.toString() || '';
66
+
67
+ if (responseText.toLowerCase().includes('success')) {
68
+ const parts = responseText.split('|');
69
+ const messageId = parts.length > 1 ? parts[1].trim() : new Date().getTime().toString();
70
+
71
+ this.logger.log(
72
+ `Gupshup SMS sent successfully to ${to}, messageId: ${messageId}`,
73
+ );
74
+
75
+ return {
76
+ success: true,
77
+ messageId: messageId,
78
+ provider: 'gupshup',
79
+ service: 'SMS',
80
+ timestamp: new Date(),
81
+ };
82
+ } else {
83
+ throw new Error(responseText || 'Failed to send SMS via Gupshup');
84
+ }
85
+ } catch (error) {
86
+ this.logger.error(
87
+ `Failed to send Gupshup SMS to ${to}`,
88
+ error.response?.data || error.message,
89
+ );
90
+
91
+ return {
92
+ success: false,
93
+ provider: 'gupshup',
94
+ service: 'SMS',
95
+ error: this.extractErrorMessage(error),
96
+ timestamp: new Date(),
97
+ };
98
+ }
99
+ }
100
+
101
+ private formatPhoneNumber(phoneNumber: string): string {
102
+ // Remove any non-digit characters except +
103
+ let formatted = phoneNumber.replace(/[^\d+]/g, '');
104
+
105
+ // Remove + if present as Gupshup expects just numbers
106
+ formatted = formatted.replace(/\+/g, '');
107
+
108
+ return formatted;
109
+ }
110
+
111
+ private extractErrorMessage(error: any): string {
112
+ if (error.response?.data) {
113
+ const data = error.response.data.toString();
114
+ if (data) {
115
+ return data;
116
+ }
117
+ }
118
+
119
+ if (error.response?.data?.error?.message) {
120
+ return error.response.data.error.message;
121
+ }
122
+
123
+ if (error.response?.data?.message) {
124
+ return error.response.data.message;
125
+ }
126
+
127
+ if (error.message) {
128
+ return error.message;
129
+ }
130
+
131
+ return 'Unknown Gupshup SMS API error';
132
+ }
133
+
134
+ validateConfig(config: any): boolean {
135
+ if (!config || typeof config !== 'object') {
136
+ return false;
137
+ }
138
+
139
+ // Required fields
140
+ if (!config.apiKey || !config.sourceNumber) {
141
+ return false;
142
+ }
143
+
144
+ return true;
145
+ }
146
+ }