diff --git a/src/modules/whatsapp/repositories/mensagens.repository.ts b/src/modules/whatsapp/repositories/mensagens.repository.ts new file mode 100644 index 0000000..0cd341f --- /dev/null +++ b/src/modules/whatsapp/repositories/mensagens.repository.ts @@ -0,0 +1,52 @@ +import { Injectable } from '@nestjs/common'; +import { DatabaseService } from '../../../infra/database/database.service'; + +@Injectable() +export class MensagensRepository { + constructor(private readonly database: DatabaseService) {} + + async save(msg: { + wamid: string; + chatId: string; + fromMe: boolean; + type: string; + body?: string; + senderName?: string; + status?: string; + timestamp: number; + }) { + await this.database.query( + `INSERT INTO mensagens (wamid, chat_id, from_me, type, body, sender_name, status, timestamp) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (wamid) DO NOTHING`, + [msg.wamid, msg.chatId, msg.fromMe, msg.type, msg.body ?? null, msg.senderName ?? null, msg.status ?? null, msg.timestamp], + ); + } + + async updateStatus(wamid: string, status: string) { + await this.database.query( + `UPDATE mensagens SET status = $1 WHERE wamid = $2`, + [status, wamid], + ); + } + + async findByChatId(chatId: string) { + return this.database.query( + `SELECT * FROM mensagens WHERE chat_id = $1 ORDER BY timestamp ASC`, + [chatId], + ); + } + + async findChats() { + return this.database.query(` + SELECT DISTINCT ON (chat_id) + chat_id, + body AS preview, + from_me AS last_message_from_me, + sender_name, + timestamp + FROM mensagens + ORDER BY chat_id, timestamp DESC + `); + } +} diff --git a/src/modules/whatsapp/whatsapp.module.ts b/src/modules/whatsapp/whatsapp.module.ts index bef8fa9..762f51e 100644 --- a/src/modules/whatsapp/whatsapp.module.ts +++ b/src/modules/whatsapp/whatsapp.module.ts @@ -7,10 +7,11 @@ import { AuthModule } from '../auth/auth.module'; import { ContactsModule } from '../contacts/contacts.module'; import { WhatsappTemplateRepository } from './repositories/whatsapp-template.repository'; import { WhatsappTemplateService } from './whatsapp-template.service'; +import { MensagensRepository } from './repositories/mensagens.repository'; @Module({ imports: [AttendanceModule, AuthModule, ContactsModule], - providers: [WhatsappService, WhatsappGateway, WhatsappTemplateService, WhatsappTemplateRepository], + providers: [WhatsappService, WhatsappGateway, WhatsappTemplateService, WhatsappTemplateRepository, MensagensRepository], controllers: [WhatsappController], exports: [WhatsappService], }) diff --git a/src/modules/whatsapp/whatsapp.service.ts b/src/modules/whatsapp/whatsapp.service.ts index 8a08d84..b16dfdc 100644 --- a/src/modules/whatsapp/whatsapp.service.ts +++ b/src/modules/whatsapp/whatsapp.service.ts @@ -3,6 +3,7 @@ import { WhatsappGateway } from './whatsapp.gateway'; import { AttendanceAssignmentService } from '../attendance/attendance-assignment.service'; import { ContactsService } from '../contacts/contacts.service'; import { WhatsappTemplateService } from './whatsapp-template.service'; +import { MensagensRepository } from './repositories/mensagens.repository'; @Injectable() export class WhatsappService { @@ -15,6 +16,7 @@ export class WhatsappService { private readonly assignmentService: AttendanceAssignmentService, private readonly contactsService: ContactsService, private readonly whatsappTemplateService: WhatsappTemplateService, + private readonly mensagensRepository: MensagensRepository, ) {} private async enqueueIncomingRoute(remoteJid: string, msg: any, messageBody: string, messageId: string) { @@ -54,11 +56,11 @@ export class WhatsappService { } async getChats() { - return []; + return this.mensagensRepository.findChats(); } - async getChatMessages(_chatId: string) { - return []; + async getChatMessages(chatId: string) { + return this.mensagensRepository.findByChatId(chatId); } async getMessageMedia(_chatId: string, _messageId: string) { @@ -119,8 +121,23 @@ export class WhatsappService { throw new Error(`Meta API erro ${response.status}: ${JSON.stringify(error)}`); } - const result = await response.json(); - this.logger.log(`[Meta] Mensagem enviada para ${to}: ${(result as any)?.messages?.[0]?.id}`); + const result = await response.json() as any; + const wamid = result?.messages?.[0]?.id; + this.logger.log(`[Meta] Mensagem enviada para ${to}: ${wamid}`); + + if (wamid) { + await this.mensagensRepository.save({ + wamid, + chatId: to, + fromMe: true, + type: 'text', + body: body, + senderName: senderName ?? 'Sistema', + status: 'sent', + timestamp: Math.floor(Date.now() / 1000), + }); + } + await this.assignmentService.clearTransferNote(to); return result; } @@ -179,6 +196,7 @@ export class WhatsappService { if (value?.statuses?.length) { for (const status of value.statuses) { this.logger.log(`[Meta] Status de mensagem: ${status.id} → ${status.status} (destinatário: ${status.recipient_id})`); + await this.mensagensRepository.updateStatus(status.id, status.status); } } } @@ -203,6 +221,16 @@ export class WhatsappService { this.logger.log(`[Meta] Mensagem recebida de ${from} (${contactName}): ${messageBody || '[mídia]'}`); + await this.mensagensRepository.save({ + wamid: messageId, + chatId: from, + fromMe: false, + type: message.type ?? 'text', + body: messageBody || null, + senderName: contactName, + timestamp, + }); + this.gateway.emitNewMessage({ from, body: messageBody,