import { Injectable, Logger } from '@nestjs/common'; import axios, { AxiosResponse } from 'axios'; import { IntegrationStrategy, IntegrationResult, } from '../integration.strategy'; interface GupshupSmsConfig { apiKey: string; sourceNumber: string; baseUrl?: string; method?: string; // 'SendMessage' or 'SendSMS' } interface GupshupSmsApiResponse { status: string; messageId?: string; response?: { id: string; phone: string; details: string; }; error?: { code: number; message: string; }; } @Injectable() export class GupshupSmsStrategy implements IntegrationStrategy { private readonly logger = new Logger(GupshupSmsStrategy.name); private readonly defaultBaseUrl = 'https://enterprise.smsgupshup.com/GatewayAPI/rest'; async sendMessage( to: string, message: string, config: any, ): Promise { try { if (!this.validateConfig(config)) { throw new Error('Invalid Gupshup SMS configuration'); } const gupshupConfig = config as GupshupSmsConfig; const baseUrl = gupshupConfig.baseUrl || this.defaultBaseUrl; const method = gupshupConfig.method || 'SendMessage'; const params = new URLSearchParams(); params.append('method', method); params.append('send_to', this.formatPhoneNumber(to)); params.append('msg', message); params.append('msg_type', 'TEXT'); params.append('userid', gupshupConfig.apiKey); params.append('auth_scheme', 'plain'); params.append('v', '1.1'); params.append('format', 'text'); const url = `${baseUrl}?${params.toString()}`; const response: AxiosResponse = await axios.get(url, { timeout: 30000, }); // Gupshup SMS API returns text response like: "success | message-id" const responseText = response.data?.toString() || ''; if (responseText.toLowerCase().includes('success')) { const parts = responseText.split('|'); const messageId = parts.length > 1 ? parts[1].trim() : new Date().getTime().toString(); this.logger.log( `Gupshup SMS sent successfully to ${to}, messageId: ${messageId}`, ); return { success: true, messageId: messageId, provider: 'gupshup', service: 'SMS', timestamp: new Date(), }; } else { throw new Error(responseText || 'Failed to send SMS via Gupshup'); } } catch (error) { this.logger.error( `Failed to send Gupshup SMS to ${to}`, error.response?.data || error.message, ); return { success: false, provider: 'gupshup', service: 'SMS', error: this.extractErrorMessage(error), timestamp: new Date(), }; } } private formatPhoneNumber(phoneNumber: string): string { // Remove any non-digit characters except + let formatted = phoneNumber.replace(/[^\d+]/g, ''); // Remove + if present as Gupshup expects just numbers formatted = formatted.replace(/\+/g, ''); return formatted; } private extractErrorMessage(error: any): string { if (error.response?.data) { const data = error.response.data.toString(); if (data) { return data; } } if (error.response?.data?.error?.message) { return error.response.data.error.message; } if (error.response?.data?.message) { return error.response.data.message; } if (error.message) { return error.message; } return 'Unknown Gupshup SMS API error'; } validateConfig(config: any): boolean { if (!config || typeof config !== 'object') { return false; } // Required fields if (!config.apiKey || !config.sourceNumber) { return false; } return true; } }