feat: prisma and remove mongodb

This commit is contained in:
Davidson Gomes
2024-06-06 14:47:58 -03:00
parent 35f97e08dd
commit 36ec67cef9
76 changed files with 1663 additions and 3894 deletions

View File

@@ -5,8 +5,7 @@ import { ConfigService, HttpServer } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { BadRequestException } from '../../../../exceptions';
import { InstanceDto } from '../../../dto/instance.dto';
import { MongodbRepository } from '../../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../../repository/prisma/repository.service';
import { PrismaRepository } from '../../../repository/repository.service';
import { waMonitor } from '../../../server.module';
import { CacheService } from '../../../services/cache.service';
import { ChatwootDto } from '../dto/chatwoot.dto';
@@ -18,7 +17,6 @@ export class ChatwootController {
constructor(
private readonly chatwootService: ChatwootService,
private readonly configService: ConfigService,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
) {}
@@ -30,39 +28,39 @@ export class ChatwootController {
throw new BadRequestException('url is not valid');
}
if (!data.account_id) {
throw new BadRequestException('account_id is required');
if (!data.accountId) {
throw new BadRequestException('accountId is required');
}
if (!data.token) {
throw new BadRequestException('token is required');
}
if (data.sign_msg !== true && data.sign_msg !== false) {
throw new BadRequestException('sign_msg is required');
if (data.signMsg !== true && data.signMsg !== false) {
throw new BadRequestException('signMsg is required');
}
if (data.sign_msg === false) data.sign_delimiter = null;
if (data.signMsg === false) data.signDelimiter = null;
}
if (!data.enabled) {
logger.verbose('chatwoot disabled');
data.account_id = '';
data.accountId = '';
data.token = '';
data.url = '';
data.sign_msg = false;
data.sign_delimiter = null;
data.reopen_conversation = false;
data.conversation_pending = false;
data.import_contacts = false;
data.import_messages = false;
data.merge_brazil_contacts = false;
data.days_limit_import_messages = 0;
data.auto_create = false;
data.name_inbox = '';
data.signMsg = false;
data.signDelimiter = null;
data.reopenConversation = false;
data.conversationPending = false;
data.importContacts = false;
data.importMessages = false;
data.mergeBrazilContacts = false;
data.daysLimitImportMessages = 0;
data.autoCreate = false;
data.nameInbox = '';
}
if (!data.name_inbox || data.name_inbox === '') {
data.name_inbox = instance.instanceName;
if (!data.nameInbox || data.nameInbox === '') {
data.nameInbox = instance.instanceName;
}
const result = await this.chatwootService.create(instance, data);
@@ -87,10 +85,10 @@ export class ChatwootController {
return {
enabled: false,
url: '',
account_id: '',
accountId: '',
token: '',
sign_msg: false,
name_inbox: '',
signMsg: false,
nameInbox: '',
webhook_url: '',
};
}
@@ -107,13 +105,7 @@ export class ChatwootController {
logger.verbose('requested receiveWebhook from ' + instance.instanceName + ' instance');
const chatwootCache = new CacheService(new CacheEngine(this.configService, ChatwootService.name).getEngine());
const chatwootService = new ChatwootService(
waMonitor,
this.configService,
this.mongodbRepository,
this.prismaRepository,
chatwootCache,
);
const chatwootService = new ChatwootService(waMonitor, this.configService, this.prismaRepository, chatwootCache);
return chatwootService.receiveWebhook(instance, data);
}

View File

@@ -1,17 +1,17 @@
export class ChatwootDto {
enabled?: boolean;
account_id?: string;
accountId?: string;
token?: string;
url?: string;
name_inbox?: string;
sign_msg?: boolean;
sign_delimiter?: string;
nameInbox?: string;
signMsg?: boolean;
signDelimiter?: string;
number?: string;
reopen_conversation?: boolean;
conversation_pending?: boolean;
merge_brazil_contacts?: boolean;
import_contacts?: boolean;
import_messages?: boolean;
days_limit_import_messages?: number;
auto_create?: boolean;
reopenConversation?: boolean;
conversationPending?: boolean;
mergeBrazilContacts?: boolean;
importContacts?: boolean;
importMessages?: boolean;
daysLimitImportMessages?: number;
autoCreate?: boolean;
}

View File

@@ -1,42 +0,0 @@
import { Schema } from 'mongoose';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class ChatwootRaw {
_id?: string;
enabled?: boolean;
account_id?: string;
token?: string;
url?: string;
name_inbox?: string;
sign_msg?: boolean;
sign_delimiter?: string;
number?: string;
reopen_conversation?: boolean;
conversation_pending?: boolean;
merge_brazil_contacts?: boolean;
import_contacts?: boolean;
import_messages?: boolean;
days_limit_import_messages?: number;
}
const chatwootSchema = new Schema<ChatwootRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
account_id: { type: String, required: true },
token: { type: String, required: true },
url: { type: String, required: true },
name_inbox: { type: String, required: true },
sign_msg: { type: Boolean, required: true },
sign_delimiter: { type: String, required: false },
number: { type: String, required: true },
reopen_conversation: { type: Boolean, required: true },
conversation_pending: { type: Boolean, required: true },
merge_brazil_contacts: { type: Boolean, required: true },
import_contacts: { type: Boolean, required: true },
import_messages: { type: Boolean, required: true },
days_limit_import_messages: { type: Number, required: true },
});
export const ChatwootModel = mongodbServer?.model(ChatwootRaw.name, chatwootSchema, 'chatwoot');
export type IChatwootModel = typeof ChatwootModel;

View File

@@ -1,62 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { IInsert, Repository } from '../../../abstract/abstract.repository';
import { ChatwootRaw, IChatwootModel } from '../../../models';
export class ChatwootRepository extends Repository {
constructor(private readonly chatwootModel: IChatwootModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('ChatwootRepository');
public async create(data: ChatwootRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating chatwoot');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving chatwoot to db');
const insert = await this.chatwootModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('chatwoot saved to db: ' + insert.modifiedCount + ' chatwoot');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving chatwoot to store');
this.writeStore<ChatwootRaw>({
path: join(this.storePath, 'chatwoot'),
fileName: instance,
data,
});
this.logger.verbose('chatwoot saved to store in path: ' + join(this.storePath, 'chatwoot') + '/' + instance);
this.logger.verbose('chatwoot created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<ChatwootRaw> {
try {
this.logger.verbose('finding chatwoot');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding chatwoot in db');
return await this.chatwootModel.findOne({ _id: instance });
}
this.logger.verbose('finding chatwoot in store');
return JSON.parse(
readFileSync(join(this.storePath, 'chatwoot', instance + '.json'), {
encoding: 'utf-8',
}),
) as ChatwootRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -8,11 +8,12 @@ import ChatwootClient, {
inbox,
} from '@figuro/chatwoot-sdk';
import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request';
import { proto } from '@whiskeysockets/baileys';
import { Chatwoot as ChatwootModel, Contact as ContactModel, Message as MessageModel } from '@prisma/client';
import axios from 'axios';
import FormData from 'form-data';
import { createReadStream, unlinkSync, writeFileSync } from 'fs';
import Jimp from 'jimp';
import Long from 'long';
import mimeTypes from 'mime-types';
import path from 'path';
@@ -22,14 +23,20 @@ import i18next from '../../../../utils/i18n';
import { ICache } from '../../../abstract/abstract.cache';
import { InstanceDto } from '../../../dto/instance.dto';
import { Options, Quoted, SendAudioDto, SendMediaDto, SendTextDto } from '../../../dto/sendMessage.dto';
import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../models';
import { MongodbRepository } from '../../../repository/mongodb/repository.manager';
import { PrismaRepository } from '../../../repository/prisma/repository.service';
import { PrismaRepository } from '../../../repository/repository.service';
import { WAMonitoringService } from '../../../services/monitor.service';
import { Events } from '../../../types/wa.types';
import { ChatwootDto } from '../dto/chatwoot.dto';
import { chatwootImport } from '../utils/chatwoot-import-helper';
interface ChatwootMessage {
messageId?: number;
inboxId?: number;
conversationId?: number;
contactInboxSourceId?: string;
isRead?: boolean;
}
export class ChatwootService {
private readonly logger = new Logger(ChatwootService.name);
@@ -38,7 +45,6 @@ export class ChatwootService {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly configService: ConfigService,
private readonly mongodbRepository: MongodbRepository,
private readonly prismaRepository: PrismaRepository,
private readonly cache: ICache,
) {}
@@ -46,7 +52,7 @@ export class ChatwootService {
private async getProvider(instance: InstanceDto) {
const cacheKey = `${instance.instanceName}:getProvider`;
if (await this.cache.has(cacheKey)) {
return (await this.cache.get(cacheKey)) as ChatwootRaw;
return (await this.cache.get(cacheKey)) as ChatwootModel;
}
this.logger.verbose('get provider to instance: ' + instance.instanceName);
@@ -110,12 +116,12 @@ export class ChatwootService {
this.logger.verbose('chatwoot created');
if (data.auto_create) {
if (data.autoCreate) {
const urlServer = this.configService.get<HttpServer>('SERVER').URL;
await this.initInstanceChatwoot(
instance,
data.name_inbox ?? instance.instanceName.split('-cwId-')[0],
data.nameInbox ?? instance.instanceName.split('-cwId-')[0],
`${urlServer}/chatwoot/webhook/${encodeURIComponent(instance.instanceName)}`,
true,
data.number,
@@ -1195,26 +1201,22 @@ export class ChatwootService {
this.logger.verbose('check if is a message deletion');
if (body.event === 'message_updated' && body.content_attributes?.deleted) {
const message = await this.mongodbRepository.message.find({
const message = await this.prismaRepository.message.findFirst({
where: {
owner: instance.instanceName,
chatwoot: {
messageId: body.id,
},
chatwootMessageId: body.id,
instanceId: instance.instanceId,
},
limit: 1,
});
if (message.length && message[0].key?.id) {
if (message) {
this.logger.verbose('deleting message in whatsapp. Message id: ' + message[0].key.id);
await waInstance?.client.sendMessage(message[0].key.remoteJid, { delete: message[0].key });
this.logger.verbose('deleting message in repository. Message id: ' + message[0].key.id);
this.mongodbRepository.message.delete({
this.prismaRepository.message.deleteMany({
where: {
owner: instance.instanceName,
chatwoot: {
messageId: body.id,
},
instanceId: instance.instanceId,
chatwootMessageId: body.id,
},
});
}
@@ -1368,9 +1370,7 @@ export class ChatwootService {
messageId: body.id,
inboxId: body.inbox?.id,
conversationId: body.conversation?.id,
contactInbox: {
sourceId: body.conversation?.contact_inbox?.source_id,
},
contactInboxSourceId: body.conversation?.contact_inbox?.source_id,
},
instance,
);
@@ -1391,25 +1391,27 @@ export class ChatwootService {
},
};
let messageSent: MessageRaw | proto.WebMessageInfo;
let messageSent: any;
try {
messageSent = await waInstance?.textMessage(data, true);
if (!messageSent) {
throw new Error('Message not sent');
}
if (Long.isLong(messageSent?.messageTimestamp)) {
messageSent.messageTimestamp = messageSent.messageTimestamp?.toNumber();
}
this.updateChatwootMessageId(
{
...messageSent,
owner: instance.instanceName,
instanceId: instance.instanceId,
},
{
messageId: body.id,
inboxId: body.inbox?.id,
conversationId: body.conversation?.id,
contactInbox: {
sourceId: body.conversation?.contact_inbox?.source_id,
},
contactInboxSourceId: body.conversation?.contact_inbox?.source_id,
},
instance,
);
@@ -1424,32 +1426,72 @@ export class ChatwootService {
const chatwootRead = this.configService.get<Chatwoot>('CHATWOOT').MESSAGE_READ;
if (chatwootRead) {
const lastMessage = await this.mongodbRepository.message.find({
const lastMessage = await this.prismaRepository.message.findFirst({
where: {
key: {
fromMe: false,
path: ['fromMe'],
equals: false,
},
owner: instance.instanceName,
instanceId: instance.instanceId,
},
limit: 1,
});
if (lastMessage.length > 0 && !lastMessage[0].chatwoot?.isRead) {
if (lastMessage && !lastMessage.chatwootIsRead) {
const key = lastMessage.key as {
id: string;
fromMe: boolean;
remoteJid: string;
participant?: string;
};
waInstance?.markMessageAsRead({
read_messages: lastMessage.map((msg) => ({
id: msg.key?.id,
fromMe: msg.key?.fromMe,
remoteJid: msg.key?.remoteJid,
})),
read_messages: [
{
id: key.id,
fromMe: key.fromMe,
remoteJid: key.remoteJid,
},
],
});
const updateMessage = lastMessage.map((msg) => ({
key: msg.key,
owner: msg.owner,
chatwoot: {
...msg.chatwoot,
isRead: true,
const updateMessage = {
chatwootMessageId: lastMessage.chatwootMessageId,
chatwootConversationId: lastMessage.chatwootConversationId,
chatwootInboxId: lastMessage.chatwootInboxId,
chatwootContactInboxSourceId: lastMessage.chatwootContactInboxSourceId,
chatwootIsRead: true,
};
await this.prismaRepository.message.updateMany({
where: {
instanceId: instance.instanceId,
AND: [
{
key: {
path: ['id'],
equals: key.id,
},
},
{
key: {
path: ['remoteJid'],
equals: key.remoteJid,
},
},
{
key: {
path: ['fromMe'],
equals: key.fromMe,
},
},
{
key: {
path: ['participant'],
equals: key.participant,
},
},
],
},
}));
this.mongodbRepository.message.update(updateMessage, instance.instanceName, true);
data: updateMessage,
});
}
}
}
@@ -1481,31 +1523,48 @@ export class ChatwootService {
}
}
private updateChatwootMessageId(
message: MessageRaw,
chatwootMessageIds: MessageRaw['chatwoot'],
instance: InstanceDto,
) {
if (!chatwootMessageIds.messageId || !message?.key?.id) {
private updateChatwootMessageId(message: MessageModel, chatwootMessageIds: ChatwootMessage, instance: InstanceDto) {
const key = message.key as {
id: string;
fromMe: boolean;
remoteJid: string;
participant?: string;
};
if (!chatwootMessageIds.messageId || !key?.id) {
return;
}
message.chatwoot = chatwootMessageIds;
this.mongodbRepository.message.update([message], instance.instanceName, true);
}
private async getMessageByKeyId(instance: InstanceDto, keyId: string): Promise<MessageRaw> {
const messages = await this.mongodbRepository.message.find({
this.prismaRepository.message.updateMany({
where: {
key: {
id: keyId,
path: ['id'],
equals: key.id,
},
owner: instance.instanceName,
instanceId: instance.instanceId,
},
data: {
chatwootMessageId: chatwootMessageIds.messageId,
chatwootConversationId: chatwootMessageIds.conversationId,
chatwootInboxId: chatwootMessageIds.inboxId,
chatwootContactInboxSourceId: chatwootMessageIds.contactInboxSourceId,
chatwootIsRead: chatwootMessageIds.isRead,
},
});
}
private async getMessageByKeyId(instance: InstanceDto, keyId: string): Promise<MessageModel> {
const messages = await this.prismaRepository.message.findFirst({
where: {
key: {
path: ['id'],
equals: keyId,
},
instanceId: instance.instanceId,
},
limit: 1,
});
return messages.length ? messages[0] : null;
return messages || null;
}
private async getReplyToIds(
@@ -1519,8 +1578,8 @@ export class ChatwootService {
inReplyToExternalId = msg.message?.extendedTextMessage?.contextInfo?.stanzaId;
if (inReplyToExternalId) {
const message = await this.getMessageByKeyId(instance, inReplyToExternalId);
if (message?.chatwoot?.messageId) {
inReplyTo = message.chatwoot.messageId;
if (message?.chatwootMessageId) {
inReplyTo = message.chatwootMessageId;
}
}
}
@@ -1533,16 +1592,21 @@ export class ChatwootService {
private async getQuotedMessage(msg: any, instance: InstanceDto): Promise<Quoted> {
if (msg?.content_attributes?.in_reply_to) {
const message = await this.mongodbRepository.message.find({
const message = await this.prismaRepository.message.findFirst({
where: {
chatwoot: {
messageId: msg?.content_attributes?.in_reply_to,
},
owner: instance.instanceName,
chatwootMessageId: msg?.content_attributes?.in_reply_to,
instanceId: instance.instanceId,
},
limit: 1,
});
if (message.length && message[0]?.key?.id) {
const key = message.key as {
id: string;
fromMe: boolean;
remoteJid: string;
participant?: string;
};
if (message && key?.id) {
return {
key: message[0].key,
message: message[0].message,
@@ -1588,7 +1652,12 @@ export class ChatwootService {
private getReactionMessage(msg: any) {
interface ReactionMessage {
key: MessageRaw['key'];
key: {
id: string;
fromMe: boolean;
remoteJid: string;
participant?: string;
};
text: string;
}
const reactionMessage: ReactionMessage | undefined = msg?.reactionMessage;
@@ -2131,22 +2200,23 @@ export class ChatwootService {
}
const message = await this.getMessageByKeyId(instance, body.key.id);
if (message?.chatwoot?.messageId && message?.chatwoot?.conversationId) {
if (message?.chatwootMessageId && message?.chatwootConversationId) {
this.logger.verbose('deleting message in repository. Message id: ' + body.key.id);
this.mongodbRepository.message.delete({
this.prismaRepository.message.deleteMany({
where: {
key: {
id: body.key.id,
path: ['id'],
equals: body.key.id,
},
owner: instance.instanceName,
instanceId: instance.instanceId,
},
});
this.logger.verbose('deleting message in chatwoot. Message id: ' + body.key.id);
return await client.messages.delete({
accountId: this.provider.account_id,
conversationId: message.chatwoot.conversationId,
messageId: message.chatwoot.messageId,
conversationId: message.chatwootConversationId,
messageId: message.chatwootMessageId,
});
}
}
@@ -2157,18 +2227,25 @@ export class ChatwootService {
body?.editedMessage?.conversation || body?.editedMessage?.extendedTextMessage?.text
}\n\n_\`${i18next.t('cw.message.edited')}.\`_`;
const message = await this.getMessageByKeyId(instance, body?.key?.id);
const messageType = message.key?.fromMe ? 'outgoing' : 'incoming';
const key = message.key as {
id: string;
fromMe: boolean;
remoteJid: string;
participant?: string;
};
if (message && message.chatwoot?.conversationId) {
const messageType = key?.fromMe ? 'outgoing' : 'incoming';
if (message && message.chatwootConversationId) {
const send = await this.createMessage(
instance,
message.chatwoot.conversationId,
message.chatwootConversationId,
editedText,
messageType,
false,
[],
{
message: { extendedTextMessage: { contextInfo: { stanzaId: message.key.id } } },
message: { extendedTextMessage: { contextInfo: { stanzaId: key.id } } },
},
'WAID:' + body.key.id,
);
@@ -2189,9 +2266,11 @@ export class ChatwootService {
}
const message = await this.getMessageByKeyId(instance, body.key.id);
const { conversationId, contactInbox } = message?.chatwoot || {};
const conversationId = message?.chatwootConversationId;
const contactInboxSourceId = message?.chatwootContactInboxSourceId;
if (conversationId) {
let sourceId = contactInbox?.sourceId;
let sourceId = contactInboxSourceId;
const inbox = (await this.getInbox(instance)) as inbox & {
inbox_identifier?: string;
};
@@ -2317,7 +2396,7 @@ export class ChatwootService {
/* We can't proccess messages exactly in batch because Chatwoot use message id to order
messages in frontend and we are receiving the messages mixed between the batches.
Because this, we need to put all batches together and order after */
public addHistoryMessages(instance: InstanceDto, messagesRaw: MessageRaw[]) {
public addHistoryMessages(instance: InstanceDto, messagesRaw: MessageModel[]) {
if (!this.isImportHistoryAvailable()) {
return;
}
@@ -2325,7 +2404,7 @@ export class ChatwootService {
chatwootImport.addHistoryMessages(instance, messagesRaw);
}
public addHistoryContacts(instance: InstanceDto, contactsRaw: ContactRaw[]) {
public addHistoryContacts(instance: InstanceDto, contactsRaw: ContactModel[]) {
if (!this.isImportHistoryAvailable()) {
return;
}
@@ -2382,16 +2461,18 @@ export class ChatwootService {
);
const contactsWithProfilePicture = (
await this.mongodbRepository.contact.find({
await this.prismaRepository.contact.findMany({
where: {
owner: instance.instanceName,
instanceId: instance.instanceId,
id: {
$in: recentContacts.map((contact) => contact.identifier),
in: recentContacts.map((contact) => Number(contact.identifier)),
},
profilePicUrl: {
not: null,
},
profilePictureUrl: { $ne: null },
},
} as any)
).reduce((acc: Map<string, ContactRaw>, contact: ContactRaw) => acc.set(contact.id, contact), new Map());
})
).reduce((acc: Map<number, ContactModel>, contact: ContactModel) => acc.set(contact.id, contact), new Map());
recentContacts.forEach(async (contact) => {
if (contactsWithProfilePicture.has(contact.identifier)) {

View File

@@ -1,10 +1,11 @@
import { inbox } from '@figuro/chatwoot-sdk';
import { Chatwoot as ChatwootModel, Contact, Message } from '@prisma/client';
import { proto } from '@whiskeysockets/baileys';
import { InstanceDto } from '../../../../api/dto/instance.dto';
import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../../api/models';
import { Chatwoot, configService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { ChatwootDto } from '../dto/chatwoot.dto';
import { postgresClient } from '../libs/postgres.client';
import { ChatwootService } from '../services/chatwoot.service';
@@ -29,8 +30,8 @@ type IWebMessageInfo = Omit<proto.IWebMessageInfo, 'key'> & Partial<Pick<proto.I
class ChatwootImport {
private logger = new Logger(ChatwootImport.name);
private repositoryMessagesCache = new Map<string, Set<string>>();
private historyMessages = new Map<string, MessageRaw[]>();
private historyContacts = new Map<string, ContactRaw[]>();
private historyMessages = new Map<string, Message[]>();
private historyContacts = new Map<string, Contact[]>();
public getRepositoryMessagesCache(instance: InstanceDto) {
return this.repositoryMessagesCache.has(instance.instanceName)
@@ -46,14 +47,14 @@ class ChatwootImport {
this.repositoryMessagesCache.delete(instance.instanceName);
}
public addHistoryMessages(instance: InstanceDto, messagesRaw: MessageRaw[]) {
public addHistoryMessages(instance: InstanceDto, messagesRaw: Message[]) {
const actualValue = this.historyMessages.has(instance.instanceName)
? this.historyMessages.get(instance.instanceName)
: [];
this.historyMessages.set(instance.instanceName, actualValue.concat(messagesRaw));
}
public addHistoryContacts(instance: InstanceDto, contactsRaw: ContactRaw[]) {
public addHistoryContacts(instance: InstanceDto, contactsRaw: Contact[]) {
const actualValue = this.historyContacts.has(instance.instanceName)
? this.historyContacts.get(instance.instanceName)
: [];
@@ -78,7 +79,7 @@ class ChatwootImport {
return this.historyMessages.get(instance.instanceName)?.length ?? 0;
}
public async importHistoryContacts(instance: InstanceDto, provider: ChatwootRaw) {
public async importHistoryContacts(instance: InstanceDto, provider: ChatwootDto) {
try {
if (this.getHistoryMessagesLenght(instance) > 0) {
return;
@@ -93,21 +94,21 @@ class ChatwootImport {
return 0;
}
let contactsChunk: ContactRaw[] = this.sliceIntoChunks(contacts, 3000);
let contactsChunk: Contact[] = this.sliceIntoChunks(contacts, 3000);
while (contactsChunk.length > 0) {
// inserting contacts in chatwoot db
let sqlInsert = `INSERT INTO contacts
(name, phone_number, account_id, identifier, created_at, updated_at) VALUES `;
const bindInsert = [provider.account_id];
const bindInsert = [provider.accountId];
for (const contact of contactsChunk) {
bindInsert.push(contact.pushName);
const bindName = `$${bindInsert.length}`;
bindInsert.push(`+${contact.id.split('@')[0]}`);
bindInsert.push(`+${contact.remoteJid.split('@')[0]}`);
const bindPhoneNumber = `$${bindInsert.length}`;
bindInsert.push(contact.id);
bindInsert.push(contact.remoteJid);
const bindIdentifier = `$${bindInsert.length}`;
sqlInsert += `(${bindName}, ${bindPhoneNumber}, $1, ${bindIdentifier}, NOW(), NOW()),`;
@@ -137,7 +138,7 @@ class ChatwootImport {
instance: InstanceDto,
chatwootService: ChatwootService,
inbox: inbox,
provider: ChatwootRaw,
provider: ChatwootModel,
) {
try {
const pgClient = postgresClient.getChatwootConnection();
@@ -156,8 +157,16 @@ class ChatwootImport {
// ordering messages by number and timestamp asc
messagesOrdered.sort((a, b) => {
const aKey = a.key as {
remoteJid: string;
};
const bKey = b.key as {
remoteJid: string;
};
return (
parseInt(a.key.remoteJid) - parseInt(b.key.remoteJid) ||
parseInt(aKey.remoteJid) - parseInt(bKey.remoteJid) ||
(a.messageTimestamp as number) - (b.messageTimestamp as number)
);
});
@@ -165,7 +174,7 @@ class ChatwootImport {
const allMessagesMappedByPhoneNumber = this.createMessagesMapByPhoneNumber(messagesOrdered);
// Map structure: +552199999999 => { first message timestamp from number, last message timestamp from number}
const phoneNumbersWithTimestamp = new Map<string, firstLastTimestamp>();
allMessagesMappedByPhoneNumber.forEach((messages: MessageRaw[], phoneNumber: string) => {
allMessagesMappedByPhoneNumber.forEach((messages: Message[], phoneNumber: string) => {
phoneNumbersWithTimestamp.set(phoneNumber, {
first: messages[0]?.messageTimestamp as number,
last: messages[messages.length - 1]?.messageTimestamp as number,
@@ -174,9 +183,9 @@ class ChatwootImport {
// processing messages in batch
const batchSize = 4000;
let messagesChunk: MessageRaw[] = this.sliceIntoChunks(messagesOrdered, batchSize);
let messagesChunk: Message[] = this.sliceIntoChunks(messagesOrdered, batchSize);
while (messagesChunk.length > 0) {
// Map structure: +552199999999 => MessageRaw[]
// Map structure: +552199999999 => Message[]
const messagesByPhoneNumber = this.createMessagesMapByPhoneNumber(messagesChunk);
if (messagesByPhoneNumber.size > 0) {
@@ -191,9 +200,9 @@ class ChatwootImport {
let sqlInsertMsg = `INSERT INTO messages
(content, account_id, inbox_id, conversation_id, message_type, private, content_type,
sender_type, sender_id, created_at, updated_at) VALUES `;
const bindInsertMsg = [provider.account_id, inbox.id];
const bindInsertMsg = [provider.accountId, inbox.id];
messagesByPhoneNumber.forEach((messages: MessageRaw[], phoneNumber: string) => {
messagesByPhoneNumber.forEach((messages: any[], phoneNumber: string) => {
const fksChatwoot = fksByNumber.get(phoneNumber);
messages.forEach((message) => {
@@ -257,14 +266,14 @@ class ChatwootImport {
}
public async selectOrCreateFksFromChatwoot(
provider: ChatwootRaw,
provider: ChatwootModel,
inbox: inbox,
phoneNumbersWithTimestamp: Map<string, firstLastTimestamp>,
messagesByPhoneNumber: Map<string, MessageRaw[]>,
messagesByPhoneNumber: Map<string, Message[]>,
): Promise<Map<string, FksChatwoot>> {
const pgClient = postgresClient.getChatwootConnection();
const bindValues = [provider.account_id, inbox.id];
const bindValues = [provider.accountId, inbox.id];
const phoneNumberBind = Array.from(messagesByPhoneNumber.keys())
.map((phoneNumber) => {
const phoneNumberTimestamp = phoneNumbersWithTimestamp.get(phoneNumber);
@@ -348,7 +357,7 @@ class ChatwootImport {
return new Map(fksFromChatwoot.rows.map((item: FksChatwoot) => [item.phone_number, item]));
}
public async getChatwootUser(provider: ChatwootRaw): Promise<ChatwootUser> {
public async getChatwootUser(provider: ChatwootModel): Promise<ChatwootUser> {
try {
const pgClient = postgresClient.getChatwootConnection();
@@ -362,10 +371,13 @@ class ChatwootImport {
}
}
public createMessagesMapByPhoneNumber(messages: MessageRaw[]): Map<string, MessageRaw[]> {
return messages.reduce((acc: Map<string, MessageRaw[]>, message: MessageRaw) => {
if (!this.isIgnorePhoneNumber(message?.key?.remoteJid)) {
const phoneNumber = message?.key?.remoteJid?.split('@')[0];
public createMessagesMapByPhoneNumber(messages: Message[]): Map<string, Message[]> {
return messages.reduce((acc: Map<string, Message[]>, message: Message) => {
const key = message?.key as {
remoteJid: string;
};
if (!this.isIgnorePhoneNumber(key?.remoteJid)) {
const phoneNumber = key?.remoteJid?.split('@')[0];
if (phoneNumber) {
const phoneNumberPlus = `+${phoneNumber}`;
const messages = acc.has(phoneNumberPlus) ? acc.get(phoneNumberPlus) : [];
@@ -380,7 +392,7 @@ class ChatwootImport {
public async getContactsOrderByRecentConversations(
inbox: inbox,
provider: ChatwootRaw,
provider: ChatwootModel,
limit = 50,
): Promise<{ id: number; phone_number: string; identifier: string }[]> {
try {
@@ -394,7 +406,7 @@ class ChatwootImport {
ORDER BY conversations.last_activity_at DESC
LIMIT $3`;
return (await pgClient.query(sql, [provider.account_id, inbox.id, limit]))?.rows;
return (await pgClient.query(sql, [provider.accountId, inbox.id, limit]))?.rows;
} catch (error) {
this.logger.error(`Error on get recent conversations: ${error.toString()}`);
}

View File

@@ -1,3 +1,4 @@
import { JsonValue } from '@prisma/client/runtime/library';
import * as amqp from 'amqplib/callback_api';
import { configService, Rabbitmq } from '../../../../config/env.config';
@@ -107,12 +108,14 @@ export const initQueues = (instanceName: string, events: string[]) => {
});
};
export const removeQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
export const removeQueues = (instanceName: string, events: JsonValue) => {
const eventsArray = Array.isArray(events) ? events.map((event) => String(event)) : [];
if (!events || !eventsArray.length) return;
const channel = getAMQP();
const queues = events.map((event) => {
const queues = eventsArray.map((event) => {
return `${event.replace(/_/g, '.').toLowerCase()}`;
});

View File

@@ -1,18 +0,0 @@
import { Schema } from 'mongoose';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class RabbitmqRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const rabbitmqSchema = new Schema<RabbitmqRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const RabbitmqModel = mongodbServer?.model(RabbitmqRaw.name, rabbitmqSchema, 'rabbitmq');
export type IRabbitmqModel = typeof RabbitmqModel;

View File

@@ -1,62 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { IInsert, Repository } from '../../../abstract/abstract.repository';
import { IRabbitmqModel, RabbitmqRaw } from '../../../models';
export class RabbitmqRepository extends Repository {
constructor(private readonly rabbitmqModel: IRabbitmqModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('RabbitmqRepository');
public async create(data: RabbitmqRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating rabbitmq');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving rabbitmq to db');
const insert = await this.rabbitmqModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('rabbitmq saved to db: ' + insert.modifiedCount + ' rabbitmq');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving rabbitmq to store');
this.writeStore<RabbitmqRaw>({
path: join(this.storePath, 'rabbitmq'),
fileName: instance,
data,
});
this.logger.verbose('rabbitmq saved to store in path: ' + join(this.storePath, 'rabbitmq') + '/' + instance);
this.logger.verbose('rabbitmq created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<RabbitmqRaw> {
try {
this.logger.verbose('finding rabbitmq');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding rabbitmq in db');
return await this.rabbitmqModel.findOne({ _id: instance });
}
this.logger.verbose('finding rabbitmq in store');
return JSON.parse(
readFileSync(join(this.storePath, 'rabbitmq', instance + '.json'), {
encoding: 'utf-8',
}),
) as RabbitmqRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -1,6 +1,7 @@
import { Rabbitmq } from '@prisma/client';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { RabbitmqRaw } from '../../../models';
import { WAMonitoringService } from '../../../services/monitor.service';
import { RabbitmqDto } from '../dto/rabbitmq.dto';
import { initQueues } from '../libs/amqp.server';
@@ -18,7 +19,7 @@ export class RabbitmqService {
return { rabbitmq: { ...instance, rabbitmq: data } };
}
public async find(instance: InstanceDto): Promise<RabbitmqRaw> {
public async find(instance: InstanceDto): Promise<Rabbitmq> {
try {
this.logger.verbose('find rabbitmq: ' + instance.instanceName);
const result = await this.waMonitor.waInstances[instance.instanceName].findRabbitmq();
@@ -29,7 +30,7 @@ export class RabbitmqService {
return result;
} catch (error) {
return { enabled: false, events: [] };
return null;
}
}
}

View File

@@ -1,4 +1,5 @@
import { SQS } from '@aws-sdk/client-sqs';
import { JsonValue } from '@prisma/client/runtime/library';
import { configService, Sqs } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
@@ -59,12 +60,13 @@ export const initQueues = (instanceName: string, events: string[]) => {
});
};
export const removeQueues = (instanceName: string, events: string[]) => {
if (!events || !events.length) return;
export const removeQueues = (instanceName: string, events: JsonValue) => {
const eventsArray = Array.isArray(events) ? events.map((event) => String(event)) : [];
if (!events || !eventsArray.length) return;
const sqs = getSQS();
const queues = events.map((event) => {
const queues = eventsArray.map((event) => {
return `${event.replace(/_/g, '_').toLowerCase()}`;
});

View File

@@ -1,18 +0,0 @@
import { Schema } from 'mongoose';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class SqsRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const sqsSchema = new Schema<SqsRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const SqsModel = mongodbServer?.model(SqsRaw.name, sqsSchema, 'sqs');
export type ISqsModel = typeof SqsModel;

View File

@@ -1,62 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { IInsert, Repository } from '../../../abstract/abstract.repository';
import { ISqsModel, SqsRaw } from '../../../models';
export class SqsRepository extends Repository {
constructor(private readonly sqsModel: ISqsModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('SqsRepository');
public async create(data: SqsRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating sqs');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving sqs to db');
const insert = await this.sqsModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('sqs saved to db: ' + insert.modifiedCount + ' sqs');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving sqs to store');
this.writeStore<SqsRaw>({
path: join(this.storePath, 'sqs'),
fileName: instance,
data,
});
this.logger.verbose('sqs saved to store in path: ' + join(this.storePath, 'sqs') + '/' + instance);
this.logger.verbose('sqs created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<SqsRaw> {
try {
this.logger.verbose('finding sqs');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding sqs in db');
return await this.sqsModel.findOne({ _id: instance });
}
this.logger.verbose('finding sqs in store');
return JSON.parse(
readFileSync(join(this.storePath, 'sqs', instance + '.json'), {
encoding: 'utf-8',
}),
) as SqsRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -1,6 +1,7 @@
import { Sqs } from '@prisma/client';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { SqsRaw } from '../../../models';
import { WAMonitoringService } from '../../../services/monitor.service';
import { SqsDto } from '../dto/sqs.dto';
import { initQueues } from '../libs/sqs.server';
@@ -18,7 +19,7 @@ export class SqsService {
return { sqs: { ...instance, sqs: data } };
}
public async find(instance: InstanceDto): Promise<SqsRaw> {
public async find(instance: InstanceDto): Promise<Sqs> {
try {
this.logger.verbose('find sqs: ' + instance.instanceName);
const result = await this.waMonitor.waInstances[instance.instanceName].findSqs();
@@ -29,7 +30,7 @@ export class SqsService {
return result;
} catch (error) {
return { enabled: false, events: [] };
return null;
}
}
}

View File

@@ -1,3 +1,5 @@
import { TypebotSession } from '@prisma/client';
export class Session {
remoteJid?: string;
sessionId?: string;
@@ -19,9 +21,9 @@ export class TypebotDto {
url: string;
typebot?: string;
expire?: number;
keyword_finish?: string;
delay_message?: number;
unknown_message?: string;
listening_from_me?: boolean;
sessions?: Session[];
keywordFinish?: string;
delayMessage?: number;
unknownMessage?: string;
listeningFromMe?: boolean;
sessions?: TypebotSession[];
}

View File

@@ -1,58 +0,0 @@
import { Schema } from 'mongoose';
import { mongodbServer } from '../../../../libs/mongodb.connect';
class Session {
remoteJid?: string;
sessionId?: string;
status?: string;
createdAt?: number;
updateAt?: number;
prefilledVariables?: {
remoteJid?: string;
pushName?: string;
additionalData?: { [key: string]: any };
};
}
export class TypebotRaw {
_id?: string;
enabled?: boolean;
url: string;
typebot?: string;
expire?: number;
keyword_finish?: string;
delay_message?: number;
unknown_message?: string;
listening_from_me?: boolean;
sessions?: Session[];
}
const typebotSchema = new Schema<TypebotRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
url: { type: String, required: true },
typebot: { type: String, required: true },
expire: { type: Number, required: true },
keyword_finish: { type: String, required: true },
delay_message: { type: Number, required: true },
unknown_message: { type: String, required: true },
listening_from_me: { type: Boolean, required: true },
sessions: [
{
remoteJid: { type: String, required: true },
sessionId: { type: String, required: true },
status: { type: String, required: true },
createdAt: { type: Number, required: true },
updateAt: { type: Number, required: true },
prefilledVariables: {
remoteJid: { type: String, required: false },
pushName: { type: String, required: false },
additionalData: { type: Schema.Types.Mixed, required: false },
},
},
],
});
export const TypebotModel = mongodbServer?.model(TypebotRaw.name, typebotSchema, 'typebot');
export type ITypebotModel = typeof TypebotModel;

View File

@@ -1,68 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { IInsert, Repository } from '../../../abstract/abstract.repository';
import { ITypebotModel, TypebotRaw } from '../../../models';
export class TypebotRepository extends Repository {
constructor(private readonly typebotModel: ITypebotModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('TypebotRepository');
public async create(data: TypebotRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating typebot');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving typebot to db');
const insert = await this.typebotModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('typebot saved to db: ' + insert.modifiedCount + ' typebot');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving typebot to store');
this.writeStore<TypebotRaw>({
path: join(this.storePath, 'typebot'),
fileName: instance,
data,
});
this.logger.verbose('typebot saved to store in path: ' + join(this.storePath, 'typebot') + '/' + instance);
this.logger.verbose('typebot created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<TypebotRaw> {
try {
this.logger.verbose('finding typebot');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding typebot in db');
return await this.typebotModel.findOne({ _id: instance });
}
this.logger.verbose('finding typebot in store');
return JSON.parse(
readFileSync(join(this.storePath, 'typebot', instance + '.json'), {
encoding: 'utf-8',
}),
) as TypebotRaw;
} catch (error) {
return {
enabled: false,
url: '',
typebot: '',
expire: 0,
sessions: [],
};
}
}
}

View File

@@ -1,13 +1,13 @@
import { Message } from '@prisma/client';
import axios from 'axios';
import EventEmitter2 from 'eventemitter2';
import { ConfigService, Typebot } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { MessageRaw } from '../../../models';
import { WAMonitoringService } from '../../../services/monitor.service';
import { Events } from '../../../types/wa.types';
import { Session, TypebotDto } from '../dto/typebot.dto';
import { TypebotDto } from '../dto/typebot.dto';
export class TypebotService {
constructor(
@@ -64,10 +64,10 @@ export class TypebotService {
url: findData.url,
typebot: findData.typebot,
expire: findData.expire,
keyword_finish: findData.keyword_finish,
delay_message: findData.delay_message,
unknown_message: findData.unknown_message,
listening_from_me: findData.listening_from_me,
keywordFinish: findData.keywordFinish,
delayMessage: findData.delayMessage,
unknownMessage: findData.unknownMessage,
listeningFromMe: findData.listeningFromMe,
sessions: findData.sessions,
};
@@ -82,19 +82,19 @@ export class TypebotService {
}
});
} else if (status === 'paused') {
const session: Session = {
remoteJid: remoteJid,
sessionId: Math.floor(Math.random() * 10000000000).toString(),
status: status,
createdAt: Date.now(),
updateAt: Date.now(),
prefilledVariables: {
remoteJid: remoteJid,
pushName: '',
additionalData: {},
},
};
findData.sessions.push(session);
// const session: Session = {
// remoteJid: remoteJid,
// sessionId: Math.floor(Math.random() * 10000000000).toString(),
// status: status,
// createdAt: Date.now(),
// updateAt: Date.now(),
// prefilledVariables: {
// remoteJid: remoteJid,
// pushName: '',
// additionalData: {},
// },
// };
// findData.sessions.push(session);
}
const typebotData = {
@@ -102,10 +102,10 @@ export class TypebotService {
url: findData.url,
typebot: findData.typebot,
expire: findData.expire,
keyword_finish: findData.keyword_finish,
delay_message: findData.delay_message,
unknown_message: findData.unknown_message,
listening_from_me: findData.listening_from_me,
keywordFinish: findData.keywordFinish,
delayMessage: findData.delayMessage,
unknownMessage: findData.unknownMessage,
listeningFromMe: findData.listeningFromMe,
sessions: findData.sessions,
};
@@ -124,7 +124,8 @@ export class TypebotService {
public async clearSessions(instance: InstanceDto, remoteJid: string) {
const findTypebot = await this.find(instance);
const sessions = (findTypebot.sessions as Session[]) ?? [];
const sessions = [];
// const sessions = (findTypebot.sessions as Session[]) ?? [];
const sessionWithRemoteJid = sessions.filter((session) => session.remoteJid === remoteJid);
@@ -138,10 +139,10 @@ export class TypebotService {
url: findTypebot.url,
typebot: findTypebot.typebot,
expire: findTypebot.expire,
keyword_finish: findTypebot.keyword_finish,
delay_message: findTypebot.delay_message,
unknown_message: findTypebot.unknown_message,
listening_from_me: findTypebot.listening_from_me,
keywordFinish: findTypebot.keywordFinish,
delayMessage: findTypebot.delayMessage,
unknownMessage: findTypebot.unknownMessage,
listeningFromMe: findTypebot.listeningFromMe,
sessions,
};
@@ -163,10 +164,10 @@ export class TypebotService {
const variables = data.variables;
const findTypebot = await this.find(instance);
const expire = findTypebot.expire;
const keyword_finish = findTypebot.keyword_finish;
const delay_message = findTypebot.delay_message;
const unknown_message = findTypebot.unknown_message;
const listening_from_me = findTypebot.listening_from_me;
const keywordFinish = findTypebot.keywordFinish;
const delayMessage = findTypebot.delayMessage;
const unknownMessage = findTypebot.unknownMessage;
const listeningFromMe = findTypebot.listeningFromMe;
const prefilledVariables = {
remoteJid: remoteJid,
@@ -188,10 +189,10 @@ export class TypebotService {
typebot: typebot,
remoteJid: remoteJid,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
prefilledVariables: prefilledVariables,
});
@@ -467,10 +468,10 @@ export class TypebotService {
url: data.url,
typebot: data.typebot,
expire: data.expire,
keyword_finish: data.keyword_finish,
delay_message: data.delay_message,
unknown_message: data.unknown_message,
listening_from_me: data.listening_from_me,
keywordFinish: data.keywordFinish,
delayMessage: data.delayMessage,
unknownMessage: data.unknownMessage,
listeningFromMe: data.listeningFromMe,
sessions: data.sessions,
};
@@ -585,7 +586,7 @@ export class TypebotService {
await instance.textMessage({
number: remoteJid.split('@')[0],
options: {
delay: instance.localTypebot.delay_message || 1000,
delay: instance.localTypebot.delayMessage || 1000,
presence: 'composing',
},
textMessage: {
@@ -598,7 +599,7 @@ export class TypebotService {
await instance.mediaMessage({
number: remoteJid.split('@')[0],
options: {
delay: instance.localTypebot.delay_message || 1000,
delay: instance.localTypebot.delayMessage || 1000,
presence: 'composing',
},
mediaMessage: {
@@ -612,7 +613,7 @@ export class TypebotService {
await instance.mediaMessage({
number: remoteJid.split('@')[0],
options: {
delay: instance.localTypebot.delay_message || 1000,
delay: instance.localTypebot.delayMessage || 1000,
presence: 'composing',
},
mediaMessage: {
@@ -626,7 +627,7 @@ export class TypebotService {
await instance.audioWhatsapp({
number: remoteJid.split('@')[0],
options: {
delay: instance.localTypebot.delay_message || 1000,
delay: instance.localTypebot.delayMessage || 1000,
presence: 'recording',
encoding: true,
},
@@ -658,7 +659,7 @@ export class TypebotService {
await instance.textMessage({
number: remoteJid.split('@')[0],
options: {
delay: instance.localTypebot.delay_message || 1000,
delay: instance.localTypebot.delayMessage || 1000,
presence: 'composing',
},
textMessage: {
@@ -675,16 +676,17 @@ export class TypebotService {
}
}
public async sendTypebot(instance: InstanceDto, remoteJid: string, msg: MessageRaw) {
public async sendTypebot(instance: InstanceDto, remoteJid: string, msg: Message) {
const findTypebot = await this.find(instance);
const url = findTypebot.url;
const typebot = findTypebot.typebot;
const sessions = (findTypebot.sessions as Session[]) ?? [];
// const sessions = (findTypebot.sessions as Session[]) ?? [];
const sessions = [];
const expire = findTypebot.expire;
const keyword_finish = findTypebot.keyword_finish;
const delay_message = findTypebot.delay_message;
const unknown_message = findTypebot.unknown_message;
const listening_from_me = findTypebot.listening_from_me;
const keywordFinish = findTypebot.keywordFinish;
const delayMessage = findTypebot.delayMessage;
const unknownMessage = findTypebot.unknownMessage;
const listeningFromMe = findTypebot.listeningFromMe;
const messageType = this.getTypeMessage(msg.message).messageType;
const session = sessions.find((session) => session.remoteJid === remoteJid);
@@ -705,10 +707,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
remoteJid: remoteJid,
pushName: msg.pushName,
@@ -720,22 +722,22 @@ export class TypebotService {
const content = this.getConversationMessage(msg.message);
if (!content) {
if (unknown_message) {
if (unknownMessage) {
this.waMonitor.waInstances[instance.instanceName].textMessage({
number: remoteJid.split('@')[0],
options: {
delay: delay_message || 1000,
delay: delayMessage || 1000,
presence: 'composing',
},
textMessage: {
text: unknown_message,
text: unknownMessage,
},
});
}
return;
}
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
@@ -743,10 +745,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};
@@ -801,10 +803,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: sessions,
remoteJid: remoteJid,
pushName: msg.pushName,
@@ -819,22 +821,22 @@ export class TypebotService {
const content = this.getConversationMessage(msg.message);
if (!content) {
if (unknown_message) {
if (unknownMessage) {
this.waMonitor.waInstances[instance.instanceName].textMessage({
number: remoteJid.split('@')[0],
options: {
delay: delay_message || 1000,
delay: delayMessage || 1000,
presence: 'composing',
},
textMessage: {
text: unknown_message,
text: unknownMessage,
},
});
}
return;
}
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
@@ -842,10 +844,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};
@@ -899,10 +901,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions,
};
@@ -911,22 +913,22 @@ export class TypebotService {
const content = this.getConversationMessage(msg.message);
if (!content) {
if (unknown_message) {
if (unknownMessage) {
this.waMonitor.waInstances[instance.instanceName].textMessage({
number: remoteJid.split('@')[0],
options: {
delay: delay_message || 1000,
delay: delayMessage || 1000,
presence: 'composing',
},
textMessage: {
text: unknown_message,
text: unknownMessage,
},
});
}
return;
}
if (keyword_finish && content.toLowerCase() === keyword_finish.toLowerCase()) {
if (keywordFinish && content.toLowerCase() === keywordFinish.toLowerCase()) {
const newSessions = await this.clearSessions(instance, remoteJid);
const typebotData = {
@@ -934,10 +936,10 @@ export class TypebotService {
url: url,
typebot: typebot,
expire: expire,
keyword_finish: keyword_finish,
delay_message: delay_message,
unknown_message: unknown_message,
listening_from_me: listening_from_me,
keywordFinish: keywordFinish,
delayMessage: delayMessage,
unknownMessage: unknownMessage,
listeningFromMe: listeningFromMe,
sessions: newSessions,
};

View File

@@ -1,18 +0,0 @@
import { Schema } from 'mongoose';
import { mongodbServer } from '../../../../libs/mongodb.connect';
export class WebsocketRaw {
_id?: string;
enabled?: boolean;
events?: string[];
}
const websocketSchema = new Schema<WebsocketRaw>({
_id: { type: String, _id: true },
enabled: { type: Boolean, required: true },
events: { type: [String], required: true },
});
export const WebsocketModel = mongodbServer?.model(WebsocketRaw.name, websocketSchema, 'websocket');
export type IWebsocketModel = typeof WebsocketModel;

View File

@@ -1,62 +0,0 @@
import { readFileSync } from 'fs';
import { join } from 'path';
import { ConfigService } from '../../../../config/env.config';
import { Logger } from '../../../../config/logger.config';
import { IInsert, Repository } from '../../../abstract/abstract.repository';
import { IWebsocketModel, WebsocketRaw } from '../../../models';
export class WebsocketRepository extends Repository {
constructor(private readonly websocketModel: IWebsocketModel, private readonly configService: ConfigService) {
super(configService);
}
private readonly logger = new Logger('WebsocketRepository');
public async create(data: WebsocketRaw, instance: string): Promise<IInsert> {
try {
this.logger.verbose('creating websocket');
if (this.dbSettings.ENABLED) {
this.logger.verbose('saving websocket to db');
const insert = await this.websocketModel.replaceOne({ _id: instance }, { ...data }, { upsert: true });
this.logger.verbose('websocket saved to db: ' + insert.modifiedCount + ' websocket');
return { insertCount: insert.modifiedCount };
}
this.logger.verbose('saving websocket to store');
this.writeStore<WebsocketRaw>({
path: join(this.storePath, 'websocket'),
fileName: instance,
data,
});
this.logger.verbose('websocket saved to store in path: ' + join(this.storePath, 'websocket') + '/' + instance);
this.logger.verbose('websocket created');
return { insertCount: 1 };
} catch (error) {
return error;
}
}
public async find(instance: string): Promise<WebsocketRaw> {
try {
this.logger.verbose('finding websocket');
if (this.dbSettings.ENABLED) {
this.logger.verbose('finding websocket in db');
return await this.websocketModel.findOne({ _id: instance });
}
this.logger.verbose('finding websocket in store');
return JSON.parse(
readFileSync(join(this.storePath, 'websocket', instance + '.json'), {
encoding: 'utf-8',
}),
) as WebsocketRaw;
} catch (error) {
return {};
}
}
}

View File

@@ -1,6 +1,7 @@
import { Websocket } from '@prisma/client';
import { Logger } from '../../../../config/logger.config';
import { InstanceDto } from '../../../dto/instance.dto';
import { WebsocketRaw } from '../../../models';
import { WAMonitoringService } from '../../../services/monitor.service';
import { WebsocketDto } from '../dto/websocket.dto';
@@ -16,7 +17,7 @@ export class WebsocketService {
return { websocket: { ...instance, websocket: data } };
}
public async find(instance: InstanceDto): Promise<WebsocketRaw> {
public async find(instance: InstanceDto): Promise<Websocket> {
try {
this.logger.verbose('find websocket: ' + instance.instanceName);
const result = await this.waMonitor.waInstances[instance.instanceName].findWebsocket();
@@ -27,7 +28,7 @@ export class WebsocketService {
return result;
} catch (error) {
return { enabled: false, events: [] };
return null;
}
}
}