Skip to content

Commit d51af8d

Browse files
authored
Merge pull request #31 from samagra-comms/main
- Outbound - Feedback - Template resp Deploying to dev
2 parents fcda5de + 47360c0 commit d51af8d

File tree

3 files changed

+84
-35
lines changed

3 files changed

+84
-35
lines changed
Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
1-
import { Body, Controller, Post } from '@nestjs/common';
2-
import { XMessage } from '@samagra-x/xmessage';
1+
import { Body, Controller, Logger, Post } from '@nestjs/common';
2+
import { ConfigService } from '@nestjs/config';
3+
import { MessageState, XMessage } from '@samagra-x/xmessage';
34
import { OutboundService } from 'src/message/services/outbound/outbound.service';
45

56
@Controller('/outbound/gupshup/whatsapp')
67
export class OutboundMessageController {
7-
constructor(private readonly outboundService: OutboundService) {}
8+
constructor(private readonly outboundService: OutboundService, private readonly configService: ConfigService,) {}
9+
private readonly logger = new Logger(OutboundMessageController.name);
810

911
@Post()
1012
async handleIncomingXMessage(@Body() orchestratorRequest: XMessage): Promise<any> {
11-
12-
if (orchestratorRequest.from.bot) {
13-
if ( 'botMobileNumber' in orchestratorRequest.from.meta) {
14-
const botMobileNumber = orchestratorRequest.from.meta.botMobileNumber as string
15-
const credentials = await this.outboundService.getAdapterCredentials(botMobileNumber)
16-
await this.outboundService.handleOrchestratorResponse(orchestratorRequest, credentials)
17-
}
18-
}
19-
20-
13+
this.logger.log('Orchestrator Request', orchestratorRequest);
14+
const botMobileNumber = this.configService.get<string>('BOT_MOBILE_NUMBER')
15+
const credentials = await this.outboundService.getAdapterCredentials(botMobileNumber);
16+
orchestratorRequest.messageState = MessageState.REPLIED;
17+
await this.outboundService.handleOrchestratorResponse(orchestratorRequest, credentials);
2118
}
22-
2319
}

src/message/message.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import { CredentialService } from './services/credentials/credentials.service';
77
import { OutboundMessageController } from './controllers/outbound/outbound.controller';
88
import { UserModule } from 'src/user/user.module';
99
import { SupabaseService } from './services/supabase.service';
10+
import { FeedbackService } from './services/feedback/feedback.service';
1011

1112
@Module({
1213
imports: [ConfigModule.forRoot(), UserModule],
1314
controllers: [GupshupWhatsappInboundController, OutboundMessageController],
14-
providers: [GupshupWhatsappInboundService, OutboundService, CredentialService, SupabaseService]
15+
providers: [GupshupWhatsappInboundService, OutboundService, CredentialService, SupabaseService, FeedbackService]
1516
})
1617
export class MessageModule {}

src/message/services/inbound/gupshup.whatsapp.service.ts

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ import { OutboundService } from '../outbound/outbound.service';
88
import { XMessage, MessageType, MessageState } from '@samagra-x/xmessage';
99
import { CredentialService } from '../credentials/credentials.service';
1010
import { UserService } from 'src/user/user.service';
11+
import { FeedbackService } from '../feedback/feedback.service';
1112

1213
@Injectable()
1314
export class GupshupWhatsappInboundService {
1415
constructor(
15-
private configService: ConfigService,
16+
private readonly configService: ConfigService,
1617
private readonly userService: UserService,
1718
private readonly outboundService: OutboundService,
18-
private readonly credentialService: CredentialService
19+
private readonly credentialService: CredentialService,
20+
private readonly feedbackService: FeedbackService
1921
) {}
2022
private readonly logger = new Logger(GupshupWhatsappInboundService.name);
2123

@@ -69,48 +71,98 @@ export class GupshupWhatsappInboundService {
6971

7072
async handleIncomingGsWhatsappMessage(whatsappMessage: GSWhatsAppMessage) {
7173
const adapterCredentials = await this.getAdapterCredentials(whatsappMessage.waNumber);
72-
this.logger.log("Obtained Creds")
74+
7375
try {
74-
//Handle Feedback First
75-
if ('interactive' in whatsappMessage) {
76-
const interactiveInteraction = JSON.parse(whatsappMessage.interactive);
77-
if ((interactiveInteraction.type = 'button_reply')) {
78-
//handle feedback
79-
this.logger.log('Feedback is not being handled right now!');
80-
return;
76+
//Handle Feedback
77+
const thumbsUpEmojis = ['👍', '👍🏻', '👍🏼', '👍🏽', '👍🏾', '👍🏿'];
78+
const thumbsDownEmojis = ['👎', '👎🏻', '👎🏼', '👎🏽', '👎🏾', '👎🏿'];
79+
if (
80+
'replyId' in whatsappMessage &&
81+
'text' in whatsappMessage &&
82+
'messageId' in whatsappMessage &&
83+
(thumbsUpEmojis.includes(whatsappMessage.text) || thumbsDownEmojis.includes(whatsappMessage.text))
84+
) {
85+
if (thumbsUpEmojis.includes(whatsappMessage.text)) {
86+
this.feedbackService.givePositiveFeedback(whatsappMessage.messageId);
87+
this.logger.log('Message ID', whatsappMessage.messageId);
88+
} else if (thumbsDownEmojis.includes(whatsappMessage.text)) {
89+
this.feedbackService.giveNegativeFeedback(whatsappMessage.messageId);
90+
this.logger.log('Message ID', whatsappMessage.messageId);
8191
}
92+
return;
8293
}
8394

8495
const xMessagePayload: XMessage = await convertMessageToXMsg(whatsappMessage);
8596
if (xMessagePayload.messageType != MessageType.TEXT) {
86-
throw new Error("Media Type Not Supported");
97+
throw new Error('Media Type Not Supported');
8798
}
8899

89-
this.logger.log("Converted Message:", xMessagePayload)
100+
this.logger.log('Converted Message:', xMessagePayload);
90101
xMessagePayload.from.userID = uuid4();
91102
xMessagePayload.to.userID = uuid4();
92103
xMessagePayload.messageId.Id = uuid4();
93104

94105
xMessagePayload.to.bot = true;
95106
xMessagePayload.to.meta = xMessagePayload.to.meta || new Map<string, string>();
96107
xMessagePayload.to.meta.set('botMobileNumber', whatsappMessage.waNumber);
97-
console.log(xMessagePayload)
108+
109+
xMessagePayload.from.bot = false;
110+
xMessagePayload.from.meta = xMessagePayload.from.meta || new Map<string, string>();
111+
xMessagePayload.from.meta.set('mobileNumber', whatsappMessage.mobile.substring(2));
112+
113+
//Send Template response before the actuar response because the actual response takes time
114+
const templateResponse = this.convertApiResponseToXMessage(
115+
{
116+
adapterId: '7b0cf232-38a2-4f9b-8070-9b988ff94c2c',
117+
messageType: MessageType.TEXT,
118+
messageId: {},
119+
from: { userID: 'admin' },
120+
channelURI: 'WhatsApp',
121+
providerURI: 'gupshup',
122+
timestamp: Date.now(),
123+
messageState: MessageState.REPLIED,
124+
payload: {
125+
text: 'Thank you for your question! Our chatbot is working diligently to provide you with the best possible answer. Generating responses may take a moment, so please be patient.'
126+
}
127+
},
128+
whatsappMessage.mobile.substring(2)
129+
);
130+
131+
const tempResp = await this.outboundService.handleOrchestratorResponse(
132+
templateResponse,
133+
adapterCredentials
134+
);
98135

99136
const orchestratorServiceUrl = this.configService.get<string>('ORCHESTRATOR_API_ENDPOINT');
100-
const resp = await axios.post(`${orchestratorServiceUrl}/prompt`, xMessagePayload, {
137+
138+
139+
// Map<string,string>() cannot be sent in request body
140+
const payload = JSON.parse(JSON.stringify(xMessagePayload));
141+
142+
xMessagePayload.to.meta.forEach((val: string, key: string) => {
143+
payload.to.meta[key] = val;
144+
});
145+
146+
xMessagePayload.from.meta.forEach((val: string, key: string) => {
147+
payload.from.meta[key] = val;
148+
});
149+
const resp = await axios.post(`${orchestratorServiceUrl}/prompt`, payload, {
101150
headers: {
102151
'Content-Type': 'application/json'
103152
}
104153
});
105-
this.logger.log('OrchestratorResponse', resp.data)
154+
155+
this.logger.log('OrchestratorResponse', resp.data);
156+
//remove after this with active outbound
106157
const xResponse = this.convertApiResponseToXMessage(resp.data, whatsappMessage.mobile.substring(2));
107-
this.logger.log("OrchestratorResponse", xResponse)
158+
this.logger.log('OrchestratorResponse', xResponse);
108159
const sentResp = await this.outboundService.handleOrchestratorResponse(xResponse, adapterCredentials);
109-
this.logger.log("OutboundResponse",sentResp)
160+
this.logger.log('OutboundResponse', sentResp);
161+
110162
} catch (error) {
111-
let errorText = 'Something went wrong. Please try again later'
112-
if ( error == 'Error: Media Type Not Supported') {
113-
errorText = `Sorry, I can only respond to text-based questions at the moment. Please type your question using regular text characters, and I'll be happy to help!\n\nThank you for your understanding!`
163+
let errorText = 'Something went wrong. Please try again later';
164+
if (error == 'Error: Media Type Not Supported') {
165+
errorText = `Sorry, I can only respond to text-based questions at the moment. Please type your question using regular text characters, and I'll be happy to help!\n\nThank you for your understanding!`;
114166
}
115167
const errorResponse = this.convertApiResponseToXMessage(
116168
{

0 commit comments

Comments
 (0)