From c75dfcd4993fa3bf5d7e76d792b26468e1091973 Mon Sep 17 00:00:00 2001 From: jaison-x Date: Mon, 15 Jan 2024 20:20:02 -0300 Subject: [PATCH] feat(chatwoot): read messages from whatsapp in chatwoot It works only with messages read from whatsapp to chatwoot. --- src/whatsapp/models/message.model.ts | 2 + src/whatsapp/services/chatwoot.service.ts | 67 ++++++++++++++++++++--- src/whatsapp/services/whatsapp.service.ts | 11 +++- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/src/whatsapp/models/message.model.ts b/src/whatsapp/models/message.model.ts index b0f39b76..9c7ac9dc 100644 --- a/src/whatsapp/models/message.model.ts +++ b/src/whatsapp/models/message.model.ts @@ -14,6 +14,7 @@ class ChatwootMessage { messageId?: number; inboxId?: number; conversationId?: number; + contactInbox?: { sourceId: string }; } export class MessageRaw { @@ -51,6 +52,7 @@ const messageSchema = new Schema({ messageId: { type: Number }, inboxId: { type: Number }, conversationId: { type: Number }, + contactInbox: { type: Object }, }, }); diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index ad1e9ef5..e418b904 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -1,4 +1,5 @@ -import ChatwootClient, { conversation, inbox } from '@figuro/chatwoot-sdk'; +import ChatwootClient, { ChatwootAPIConfig, contact, conversation, inbox } from '@figuro/chatwoot-sdk'; +import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request'; import axios from 'axios'; import FormData from 'form-data'; import { createReadStream, unlinkSync, writeFileSync } from 'fs'; @@ -71,12 +72,7 @@ export class ChatwootService { this.logger.verbose('create client to instance: ' + instance.instanceName); const client = new ChatwootClient({ - config: { - basePath: provider.url, - with_credentials: true, - credentials: 'include', - token: provider.token, - }, + config: this.getClientCwConfig(), }); this.logger.verbose('client created'); @@ -84,6 +80,15 @@ export class ChatwootService { return client; } + public getClientCwConfig(): ChatwootAPIConfig { + return { + basePath: this.provider.url, + with_credentials: true, + credentials: 'include', + token: this.provider.token, + }; + } + public getCache() { return this.cache; } @@ -1200,6 +1205,9 @@ export class ChatwootService { messageId: body.id, inboxId: body.inbox?.id, conversationId: body.conversation?.id, + contactInbox: { + sourceId: body.conversation?.contact_inbox?.source_id, + }, }, instance, ); @@ -1231,6 +1239,9 @@ export class ChatwootService { messageId: body.id, inboxId: body.inbox?.id, conversationId: body.conversation?.id, + contactInbox: { + sourceId: body.conversation?.contact_inbox?.source_id, + }, }, instance, ); @@ -1911,6 +1922,44 @@ export class ChatwootService { } } + if (event === 'messages.read') { + this.logger.verbose('read message from instance: ' + instance.instanceName); + + if (!body?.key?.id || !body?.key?.remoteJid) { + this.logger.warn('message id not found'); + return; + } + + const message = await this.getMessageByKeyId(instance, body.key.id); + const { conversationId, contactInbox } = message?.chatwoot || {}; + if (conversationId) { + let sourceId = contactInbox?.sourceId; + const inbox = (await this.getInbox(instance)) as inbox & { + inbox_identifier?: string; + }; + + if (!sourceId && inbox) { + const contact = (await this.findContact( + instance, + this.getNumberFromRemoteJid(body.key.remoteJid), + )) as contact; + const contactInbox = contact?.contact_inboxes?.find((contactInbox) => contactInbox?.inbox?.id === inbox.id); + sourceId = contactInbox?.source_id; + } + + if (sourceId && inbox?.inbox_identifier) { + const url = + `/public/api/v1/inboxes/${inbox.inbox_identifier}/contacts/${sourceId}` + + `/conversations/${conversationId}/update_last_seen`; + chatwootRequest(this.getClientCwConfig(), { + method: 'POST', + url: url, + }); + } + } + return; + } + if (event === 'status.instance') { this.logger.verbose('event status.instance'); const data = body; @@ -1981,4 +2030,8 @@ export class ChatwootService { this.logger.error(error); } } + + public getNumberFromRemoteJid(remoteJid: string) { + return remoteJid.replace(/:\d+/, '').split('@')[0]; + } } diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index efe4e2a3..3aa669e1 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -1932,6 +1932,13 @@ export class WAStartupService { this.logger.verbose('group ignored'); return; } + + if (status[update.status] === 'READ' && key.fromMe) { + if (this.localChatwoot.enabled) { + this.chatwootService.eventWhatsapp('messages.read', { instanceName: this.instance.name }, { key: key }); + } + } + // if (key.remoteJid !== 'status@broadcast' && !key?.remoteJid?.match(/(:\d+)/)) { if (key.remoteJid !== 'status@broadcast') { this.logger.verbose('Message update is valid'); @@ -2877,8 +2884,8 @@ export class WAStartupService { this.logger.verbose('Processing audio'); let tempAudioPath: string; let outputAudio: string; - - number = number.replace(/\D/g, ""); + + number = number.replace(/\D/g, ''); const hash = `${number}-${new Date().getTime()}`; this.logger.verbose('Hash to audio name: ' + hash);