Skip to content

Commit

Permalink
Merge pull request #24 from samagra-comms/main
Browse files Browse the repository at this point in the history
Feedback+User Module
  • Loading branch information
KDwevedi authored Dec 12, 2023
2 parents e708b83 + 4c2b12f commit 1c54a7b
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MessageModule } from './message/message.module';
import { ConfigModule } from '@nestjs/config';
import { UserModule } from './user/user.module';

@Module({
imports: [
Expand Down
6 changes: 0 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
// import axios from 'axios';
// import {XMessage, MessageState, MessageType} from "xmessage";
// import {} from "userservice";
// import {configService} from "botservice";
// import {GSWhatsAppMessage, convertXMessageToMsg} from "gupshup-whatsapp-adapter";
// import { measureMemory } from 'vm';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
Expand Down
16 changes: 4 additions & 12 deletions src/message/dto/xmessage.dto.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { IsUUID, IsString, IsOptional, IsArray, IsEnum, IsNumber } from 'class-validator';
import { MessageState } from '@samagra-x/xmessage';

export enum MessageStatus {
DEFAULT = 'DEFAULT',
DELIVERED = 'DELIVERED',
RECEIVED = 'RECEIVED',
SENT = 'SENT',
PROCESSED = 'PROCESSED',
}

export class XMessageDbDto {
@IsOptional()
@IsUUID()
Expand All @@ -29,7 +21,7 @@ export class XMessageDbDto {
provider?: string;

@IsNumber()
timestamp: string;
timestamp: number;

@IsOptional()
@IsString()
Expand Down Expand Up @@ -88,7 +80,7 @@ export class XMessageDbDto {
@IsString()
remarks?: string;

// @IsOptional()
// @IsEnum(MessageStatus)
// status?: MessageStatus;
@IsOptional()
@IsEnum(MessageState)
status?: MessageState;
}
6 changes: 4 additions & 2 deletions src/message/message.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { ConfigModule } from '@nestjs/config';
import { OutboundService } from './services/outbound/outbound.service';
import { CredentialService } from './services/credentials/credentials.service';
import { OutboundMessageController } from './controllers/outbound/outbound.controller';
import { UserModule } from 'src/user/user.module';
import { SupabaseService } from './services/supabase.service';

@Module({
imports: [ConfigModule.forRoot()],
imports: [ConfigModule.forRoot(), UserModule],
controllers: [GupshupWhatsappInboundController, OutboundMessageController],
providers: [GupshupWhatsappInboundService, OutboundService, CredentialService]
providers: [GupshupWhatsappInboundService, OutboundService, CredentialService, SupabaseService]
})
export class MessageModule {}
1 change: 0 additions & 1 deletion src/message/services/credentials/credentials.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import axios from 'axios';


@Injectable()
export class CredentialService {
private readonly logger = new Logger(CredentialService.name);
Expand Down
24 changes: 24 additions & 0 deletions src/message/services/feedback/feedback.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';

@Injectable()
export class FeedbackService {
private readonly logger = new Logger(FeedbackService.name);

constructor(private readonly configService: ConfigService) {}

async givePositiveFeedback(messageId) {
const orchestratorUrl = this.configService.get<string>('ORCHESTRATOR_API_ENDPOINT');
const feedbackUrl = `${orchestratorUrl}/feedback/query/like/${messageId}`;

await axios.get(feedbackUrl);
}

async giveNegativeFeedback(messageId) {
const orchestratorUrl = this.configService.get<string>('ORCHESTRATOR_API_ENDPOINT');
const feedbackUrl = `${orchestratorUrl}/feedback/query/dislike/${messageId}`;

await axios.get(feedbackUrl)
}
}
10 changes: 9 additions & 1 deletion src/message/services/inbound/gupshup.whatsapp.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import { v4 as uuid4 } from 'uuid';
import { OutboundService } from '../outbound/outbound.service';
import { XMessage, MessageType, MessageState } from '@samagra-x/xmessage';
import { CredentialService } from '../credentials/credentials.service';
import { UserService } from 'src/user/user.service';

@Injectable()
export class GupshupWhatsappInboundService {
constructor(
private configService: ConfigService,
private readonly userService: UserService,
private readonly outboundService: OutboundService,
private readonly credentialService: CredentialService
) {}
Expand Down Expand Up @@ -78,6 +80,8 @@ export class GupshupWhatsappInboundService {
}
}

console.log("User", this.userService.getUserByUsername('9550360277'))

const xMessagePayload: XMessage = await convertMessageToXMsg(whatsappMessage);
if (xMessagePayload.messageType != MessageType.TEXT) {
throw new Error("Media Type Not Supported");
Expand All @@ -94,12 +98,16 @@ export class GupshupWhatsappInboundService {
console.log(xMessagePayload)

const orchestratorServiceUrl = this.configService.get<string>('ORCHESTRATOR_API_ENDPOINT');
const resp = await axios.post(orchestratorServiceUrl, xMessagePayload, {
const resp = await axios.post(`${orchestratorServiceUrl}/prompt`, xMessagePayload, {
headers: {
'Content-Type': 'application/json'
}
});
this.logger.log('OrchestratorResponse', resp)
const xResponse = this.convertApiResponseToXMessage(resp.data, whatsappMessage.mobile.substring(2));
this.logger.log("OrchestratorResponse", xResponse)
const sentResp = await this.outboundService.handleOrchestratorResponse(xResponse, adapterCredentials);
this.logger.log("OutboundResponse",sentResp)
} catch (error) {
let errorText = 'Something went wrong. Please try again later'
if ( error == 'Error: Media Type Not Supported') {
Expand Down
Empty file.
89 changes: 89 additions & 0 deletions src/message/services/supabase.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Injectable } from '@nestjs/common';
import { createClient, SupabaseClient } from '@supabase/supabase-js';
import { XMessage, MessageState } from '@samagra-x/xmessage';
import { XMessageDbDto } from '../dto/xmessage.dto';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class SupabaseService {
private supabase: SupabaseClient;

constructor(private readonly configService: ConfigService) {
this.supabase = createClient(
this.configService.get<string>('SUPABASE_URL'),
this.configService.get<string>('SUPABASE_KEY')
);
}

createXMessageDTO(msg: XMessage) {
const msgData: XMessageDbDto = {
userid: msg.to.userID as string,
fromid: msg.from.userID,
channel: msg.channelURI,
provider: msg.providerURI,
timestamp: msg.timestamp,
messagestate: msg.messageState,
app: msg.app,
xmessage: msg,
//auxdata:
messageid: msg.messageId.channelMessageId,
replyid: msg.messageId.replyId,
status: msg.messageState
};
return msgData;
}

// async readMessagesByBotId(botUuid: string): Promise<any[]> {
// const { data, error } = await this.supabase.from('xmessage').select('*').eq('botUuid', botUuid);

// if (error) throw error;
// return data;
// }

// async readMessagesByUserId(userId: string): Promise<any[]> {
// const { data, error } = await this.supabase.from('xmessage').select('*').eq('userId', userId);

// if (error) throw error;
// return data;
// }

// async readAggregateData(startDate: string, endDate: string): Promise<any[]> {
// const { data, error } = await this.supabase
// .from('xmessage')
// .select('*')
// .gte('timestamp', startDate)
// .lte('timestamp', endDate);

// if (error) throw error;
// return data;
// }

async writeMessage(message: XMessage): Promise<any> {
const msgData = this.createXMessageDTO(message);
const { data, error } = await this.supabase.from('xmessage').insert([message]);
if (error) throw error;
return data;
}

async writeMultipleMessages(messages: XMessage[]): Promise<any[]> {
const msgData = new Array<XMessageDbDto>();
messages.forEach((msg) => {
msgData.push(this.createXMessageDTO(msg));
});

const { data, error } = await this.supabase.from('xmessage').insert(msgData);

if (error) throw error;
return data;
}

async updateMessageStatus(messageId: string, newStatus: MessageState): Promise<any> {
const { data, error } = await this.supabase
.from('xmessage')
.update({ status: newStatus })
.eq('messageid', messageId);

if (error) throw error;
return data;
}
}
10 changes: 10 additions & 0 deletions src/user/user.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { HttpModule } from '@nestjs/axios';

@Module({
providers: [UserService],
imports: [HttpModule],
exports: [UserService]
})
export class UserModule {}
18 changes: 18 additions & 0 deletions src/user/user.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';

describe('UserService', () => {
let service: UserService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserService],
}).compile();

service = module.get<UserService>(UserService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
41 changes: 41 additions & 0 deletions src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { AxiosResponse } from 'axios';
import { Observable } from 'rxjs';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class UserService {
private configService: ConfigService;

constructor(private readonly httpService: HttpService) {}

private getHeaders() {
return {
headers: {
'Authorization': this.configService.get<string>('FA_AUTH_KEY'),
'Content-Type': 'application/json',
'X-FusionAuth-Application-Id': this.configService.get<string>('FA_APP_ID')
}
};
}

private getBaseUrl() {
return this.configService.get<string>('FA_URL');
}

getUserById(userId: string): Observable<AxiosResponse<any>> {
const url = `${this.getBaseUrl()}/api/user/${userId}`;
return this.httpService.get(url, this.getHeaders());
}

getUserByUsername(username: string): Observable<AxiosResponse<any>> {
const url = `${this.getBaseUrl}api/user/search?queryString=username%3A${username}&exactMatch=true`
return this.httpService.get(url, this.getHeaders());
}

createUser(userPayload: any): Observable<AxiosResponse<any>> {
const url = `${this.getBaseUrl()}/api/user`;
return this.httpService.post(url, userPayload, this.getHeaders());
}
}

0 comments on commit 1c54a7b

Please sign in to comment.