From d50da79f22bd3d4dc2c4c33c08b409448b39f1ad Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 11 Oct 2024 07:45:50 -0300 Subject: [PATCH] feat: Add support for splitMessages and timePerChar in Integrations --- CHANGELOG.md | 1 + prisma/mysql-schema.prisma | 16 +++ prisma/postgresql-schema.prisma | 16 +++ .../dify/controllers/dify.controller.ts | 34 +++++- .../integrations/chatbot/dify/dto/dify.dto.ts | 4 + .../chatbot/dify/services/dify.service.ts | 110 ++++++++++++++--- .../chatbot/dify/validate/dify.schema.ts | 8 ++ .../controllers/evolutionBot.controller.ts | 32 ++++- .../evolutionBot/dto/evolutionBot.dto.ts | 4 + .../services/evolutionBot.service.ts | 111 +++++++++++++++--- .../validate/evolutionBot.schema.ts | 8 ++ .../flowise/controllers/flowise.controller.ts | 32 ++++- .../chatbot/flowise/dto/flowise.dto.ts | 4 + .../flowise/services/flowise.service.ts | 111 +++++++++++++++--- .../openai/controllers/openai.controller.ts | 33 +++++- .../chatbot/openai/dto/openai.dto.ts | 4 + .../chatbot/openai/services/openai.service.ts | 111 +++++++++++++++--- 17 files changed, 566 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 916565e5..e8aaaa83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fake Call function * Added unreadMessages to chats * Pusher event integration +* Add support for splitMessages and timePerChar in Integrations ### Fixed diff --git a/prisma/mysql-schema.prisma b/prisma/mysql-schema.prisma index c3216153..d3df1c96 100644 --- a/prisma/mysql-schema.prisma +++ b/prisma/mysql-schema.prisma @@ -413,6 +413,8 @@ model OpenaiBot { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -436,6 +438,8 @@ model OpenaiSetting { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int speechToText Boolean? @default(false) createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp @@ -475,6 +479,8 @@ model Dify { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -496,6 +502,8 @@ model DifySetting { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback Dify? @relation(fields: [difyIdFallback], references: [id]) @@ -519,6 +527,8 @@ model EvolutionBot { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -540,6 +550,8 @@ model EvolutionBotSetting { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback EvolutionBot? @relation(fields: [botIdFallback], references: [id]) @@ -563,6 +575,8 @@ model Flowise { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -584,6 +598,8 @@ model FlowiseSetting { keepOpen Boolean? @default(false) debounceTime Int? @db.Int ignoreJids Json? + splitMessages Boolean? @default(false) + timePerChar Int? @default(50) @db.Int createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback Flowise? @relation(fields: [flowiseIdFallback], references: [id]) diff --git a/prisma/postgresql-schema.prisma b/prisma/postgresql-schema.prisma index a6b18173..1b7f060c 100644 --- a/prisma/postgresql-schema.prisma +++ b/prisma/postgresql-schema.prisma @@ -395,6 +395,8 @@ model OpenaiBot { stopBotFromMe Boolean? @default(false) @db.Boolean keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer ignoreJids Json? triggerType TriggerType? triggerOperator TriggerOperator? @@ -438,6 +440,8 @@ model OpenaiSetting { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer speechToText Boolean? @default(false) @db.Boolean createdAt DateTime? @default(now()) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp @@ -477,6 +481,8 @@ model Dify { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -498,6 +504,8 @@ model DifySetting { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer createdAt DateTime? @default(now()) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback Dify? @relation(fields: [difyIdFallback], references: [id]) @@ -521,6 +529,8 @@ model EvolutionBot { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -542,6 +552,8 @@ model EvolutionBotSetting { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer createdAt DateTime? @default(now()) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback EvolutionBot? @relation(fields: [botIdFallback], references: [id]) @@ -565,6 +577,8 @@ model Flowise { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer triggerType TriggerType? triggerOperator TriggerOperator? triggerValue String? @@ -586,6 +600,8 @@ model FlowiseSetting { keepOpen Boolean? @default(false) @db.Boolean debounceTime Int? @db.Integer ignoreJids Json? + splitMessages Boolean? @default(false) @db.Boolean + timePerChar Int? @default(50) @db.Integer createdAt DateTime? @default(now()) @db.Timestamp updatedAt DateTime @updatedAt @db.Timestamp Fallback Flowise? @relation(fields: [flowiseIdFallback], references: [id]) diff --git a/src/api/integrations/chatbot/dify/controllers/dify.controller.ts b/src/api/integrations/chatbot/dify/controllers/dify.controller.ts index 17961024..809d3ceb 100644 --- a/src/api/integrations/chatbot/dify/controllers/dify.controller.ts +++ b/src/api/integrations/chatbot/dify/controllers/dify.controller.ts @@ -54,7 +54,9 @@ export class DifyController extends ChatbotController implements ChatbotControll !data.stopBotFromMe || !data.keepOpen || !data.debounceTime || - !data.ignoreJids + !data.ignoreJids || + !data.splitMessages || + !data.timePerChar ) { const defaultSettingCheck = await this.settingsRepository.findFirst({ where: { @@ -71,6 +73,8 @@ export class DifyController extends ChatbotController implements ChatbotControll if (!data.keepOpen) data.keepOpen = defaultSettingCheck?.keepOpen || false; if (!data.debounceTime) data.debounceTime = defaultSettingCheck?.debounceTime || 0; if (!data.ignoreJids) data.ignoreJids = defaultSettingCheck?.ignoreJids || []; + if (!data.splitMessages) data.splitMessages = defaultSettingCheck?.splitMessages || false; + if (!data.timePerChar) data.timePerChar = defaultSettingCheck?.timePerChar || 0; if (!defaultSettingCheck) { await this.settings(instance, { @@ -83,6 +87,8 @@ export class DifyController extends ChatbotController implements ChatbotControll keepOpen: data.keepOpen, debounceTime: data.debounceTime, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }); } } @@ -168,6 +174,8 @@ export class DifyController extends ChatbotController implements ChatbotControll triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -349,6 +357,8 @@ export class DifyController extends ChatbotController implements ChatbotControll triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -438,6 +448,8 @@ export class DifyController extends ChatbotController implements ChatbotControll debounceTime: data.debounceTime, difyIdFallback: data.difyIdFallback, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -452,6 +464,8 @@ export class DifyController extends ChatbotController implements ChatbotControll debounceTime: updateSettings.debounceTime, difyIdFallback: updateSettings.difyIdFallback, ignoreJids: updateSettings.ignoreJids, + splitMessages: updateSettings.splitMessages, + timePerChar: updateSettings.timePerChar, }; } @@ -468,6 +482,8 @@ export class DifyController extends ChatbotController implements ChatbotControll difyIdFallback: data.difyIdFallback, ignoreJids: data.ignoreJids, instanceId: instanceId, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -482,6 +498,8 @@ export class DifyController extends ChatbotController implements ChatbotControll debounceTime: newSetttings.debounceTime, difyIdFallback: newSetttings.difyIdFallback, ignoreJids: newSetttings.ignoreJids, + splitMessages: newSetttings.splitMessages, + timePerChar: newSetttings.timePerChar, }; } catch (error) { this.logger.error(error); @@ -520,6 +538,8 @@ export class DifyController extends ChatbotController implements ChatbotControll stopBotFromMe: false, keepOpen: false, ignoreJids: [], + splitMessages: false, + timePerChar: 0, difyIdFallback: '', fallback: null, }; @@ -534,6 +554,8 @@ export class DifyController extends ChatbotController implements ChatbotControll stopBotFromMe: settings.stopBotFromMe, keepOpen: settings.keepOpen, ignoreJids: settings.ignoreJids, + splitMessages: settings.splitMessages, + timePerChar: settings.timePerChar, difyIdFallback: settings.difyIdFallback, fallback: settings.Fallback, }; @@ -763,6 +785,8 @@ export class DifyController extends ChatbotController implements ChatbotControll let keepOpen = findBot?.keepOpen; let debounceTime = findBot?.debounceTime; let ignoreJids = findBot?.ignoreJids; + let splitMessages = findBot?.splitMessages; + let timePerChar = findBot?.timePerChar; if (!expire) expire = settings.expire; if (!keywordFinish) keywordFinish = settings.keywordFinish; @@ -771,8 +795,10 @@ export class DifyController extends ChatbotController implements ChatbotControll if (!listeningFromMe) listeningFromMe = settings.listeningFromMe; if (!stopBotFromMe) stopBotFromMe = settings.stopBotFromMe; if (!keepOpen) keepOpen = settings.keepOpen; - if (!debounceTime) debounceTime = settings.debounceTime; + if (debounceTime === undefined || debounceTime === null) debounceTime = settings.debounceTime; if (!ignoreJids) ignoreJids = settings.ignoreJids; + if (splitMessages === undefined || splitMessages === null) splitMessages = settings?.splitMessages ?? false; + if (timePerChar === undefined || timePerChar === null) timePerChar = settings?.timePerChar ?? 0; const key = msg.key as { id: string; @@ -819,6 +845,8 @@ export class DifyController extends ChatbotController implements ChatbotControll keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, debouncedContent, msg?.pushName, @@ -841,6 +869,8 @@ export class DifyController extends ChatbotController implements ChatbotControll keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, content, msg?.pushName, diff --git a/src/api/integrations/chatbot/dify/dto/dify.dto.ts b/src/api/integrations/chatbot/dify/dto/dify.dto.ts index 734e7dd5..ff9bba05 100644 --- a/src/api/integrations/chatbot/dify/dto/dify.dto.ts +++ b/src/api/integrations/chatbot/dify/dto/dify.dto.ts @@ -18,6 +18,8 @@ export class DifyDto { triggerOperator?: TriggerOperator; triggerValue?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } export class DifySettingDto { @@ -31,4 +33,6 @@ export class DifySettingDto { debounceTime?: number; difyIdFallback?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } diff --git a/src/api/integrations/chatbot/dify/services/dify.service.ts b/src/api/integrations/chatbot/dify/services/dify.service.ts index cbb86e79..9f7b6127 100644 --- a/src/api/integrations/chatbot/dify/services/dify.service.ts +++ b/src/api/integrations/chatbot/dify/services/dify.service.ts @@ -382,16 +382,54 @@ export class DifyService { } if (mediaType) { + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); - textBuffer = ''; + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } if (mediaType === 'audio') { @@ -428,15 +466,53 @@ export class DifyService { } } + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + } } sendTelemetry('/message/sendText'); diff --git a/src/api/integrations/chatbot/dify/validate/dify.schema.ts b/src/api/integrations/chatbot/dify/validate/dify.schema.ts index d244bbe4..3201a65f 100644 --- a/src/api/integrations/chatbot/dify/validate/dify.schema.ts +++ b/src/api/integrations/chatbot/dify/validate/dify.schema.ts @@ -41,6 +41,8 @@ export const difySchema: JSONSchema7 = { keepOpen: { type: 'boolean' }, debounceTime: { type: 'integer' }, ignoreJids: { type: 'array', items: { type: 'string' } }, + splitMessages: { type: 'boolean' }, + timePerChar: { type: 'integer' }, }, required: ['enabled', 'botType', 'triggerType'], ...isNotEmpty('enabled', 'botType', 'triggerType'), @@ -71,6 +73,8 @@ export const difySettingSchema: JSONSchema7 = { debounceTime: { type: 'integer' }, ignoreJids: { type: 'array', items: { type: 'string' } }, difyIdFallback: { type: 'string' }, + splitMessages: { type: 'boolean' }, + timePerChar: { type: 'integer' }, }, required: [ 'expire', @@ -82,6 +86,8 @@ export const difySettingSchema: JSONSchema7 = { 'keepOpen', 'debounceTime', 'ignoreJids', + 'splitMessages', + 'timePerChar', ], ...isNotEmpty( 'expire', @@ -93,6 +99,8 @@ export const difySettingSchema: JSONSchema7 = { 'keepOpen', 'debounceTime', 'ignoreJids', + 'splitMessages', + 'timePerChar', ), }; diff --git a/src/api/integrations/chatbot/evolutionBot/controllers/evolutionBot.controller.ts b/src/api/integrations/chatbot/evolutionBot/controllers/evolutionBot.controller.ts index 96f89092..195928a7 100644 --- a/src/api/integrations/chatbot/evolutionBot/controllers/evolutionBot.controller.ts +++ b/src/api/integrations/chatbot/evolutionBot/controllers/evolutionBot.controller.ts @@ -50,7 +50,9 @@ export class EvolutionBotController extends ChatbotController implements Chatbot !data.stopBotFromMe || !data.keepOpen || !data.debounceTime || - !data.ignoreJids + !data.ignoreJids || + !data.splitMessages || + !data.timePerChar ) { const defaultSettingCheck = await this.settingsRepository.findFirst({ where: { @@ -67,6 +69,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot if (!data.keepOpen) data.keepOpen = defaultSettingCheck?.keepOpen || false; if (!data.debounceTime) data.debounceTime = defaultSettingCheck?.debounceTime || 0; if (!data.ignoreJids) data.ignoreJids = defaultSettingCheck?.ignoreJids || []; + if (!data.splitMessages) data.splitMessages = defaultSettingCheck?.splitMessages || false; + if (!data.timePerChar) data.timePerChar = defaultSettingCheck?.timePerChar || 0; if (!defaultSettingCheck) { await this.settings(instance, { @@ -79,6 +83,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot keepOpen: data.keepOpen, debounceTime: data.debounceTime, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }); } } @@ -162,6 +168,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -335,6 +343,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -420,6 +430,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot debounceTime: data.debounceTime, botIdFallback: data.botIdFallback, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -434,6 +446,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot debounceTime: updateSettings.debounceTime, botIdFallback: updateSettings.botIdFallback, ignoreJids: updateSettings.ignoreJids, + splitMessages: updateSettings.splitMessages, + timePerChar: updateSettings.timePerChar, }; } @@ -449,6 +463,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot debounceTime: data.debounceTime, botIdFallback: data.botIdFallback, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, instanceId: instanceId, }, }); @@ -464,6 +480,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot debounceTime: newSetttings.debounceTime, botIdFallback: newSetttings.botIdFallback, ignoreJids: newSetttings.ignoreJids, + splitMessages: newSetttings.splitMessages, + timePerChar: newSetttings.timePerChar, }; } catch (error) { this.logger.error(error); @@ -500,6 +518,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot stopBotFromMe: false, keepOpen: false, ignoreJids: [], + splitMessages: false, + timePerChar: 0, botIdFallback: '', fallback: null, }; @@ -514,6 +534,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot stopBotFromMe: settings.stopBotFromMe, keepOpen: settings.keepOpen, ignoreJids: settings.ignoreJids, + splitMessages: settings.splitMessages, + timePerChar: settings.timePerChar, botIdFallback: settings.botIdFallback, fallback: settings.Fallback, }; @@ -735,6 +757,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot let keepOpen = findBot?.keepOpen; let debounceTime = findBot?.debounceTime; let ignoreJids = findBot?.ignoreJids; + let splitMessages = findBot?.splitMessages; + let timePerChar = findBot?.timePerChar; if (!expire) expire = settings.expire; if (!keywordFinish) keywordFinish = settings.keywordFinish; @@ -745,6 +769,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot if (!keepOpen) keepOpen = settings.keepOpen; if (!debounceTime) debounceTime = settings.debounceTime; if (!ignoreJids) ignoreJids = settings.ignoreJids; + if (splitMessages === undefined || splitMessages === null) splitMessages = settings?.splitMessages ?? false; + if (timePerChar === undefined || timePerChar === null) timePerChar = settings?.timePerChar ?? 0; const key = msg.key as { id: string; @@ -791,6 +817,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, debouncedContent, msg?.pushName, @@ -813,6 +841,8 @@ export class EvolutionBotController extends ChatbotController implements Chatbot keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, content, msg?.pushName, diff --git a/src/api/integrations/chatbot/evolutionBot/dto/evolutionBot.dto.ts b/src/api/integrations/chatbot/evolutionBot/dto/evolutionBot.dto.ts index a4ea5781..de2d952c 100644 --- a/src/api/integrations/chatbot/evolutionBot/dto/evolutionBot.dto.ts +++ b/src/api/integrations/chatbot/evolutionBot/dto/evolutionBot.dto.ts @@ -17,6 +17,8 @@ export class EvolutionBotDto { triggerOperator?: TriggerOperator; triggerValue?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } export class EvolutionBotSettingDto { @@ -30,4 +32,6 @@ export class EvolutionBotSettingDto { debounceTime?: number; botIdFallback?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } diff --git a/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts b/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts index 29b22665..ed89f52b 100644 --- a/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts +++ b/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts @@ -143,16 +143,54 @@ export class EvolutionBotService { } if (mediaType) { + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); - textBuffer = ''; + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } if (mediaType === 'audio') { @@ -189,15 +227,54 @@ export class EvolutionBotService { } } + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } sendTelemetry('/message/sendText'); diff --git a/src/api/integrations/chatbot/evolutionBot/validate/evolutionBot.schema.ts b/src/api/integrations/chatbot/evolutionBot/validate/evolutionBot.schema.ts index 2c5fc752..9fd541f4 100644 --- a/src/api/integrations/chatbot/evolutionBot/validate/evolutionBot.schema.ts +++ b/src/api/integrations/chatbot/evolutionBot/validate/evolutionBot.schema.ts @@ -40,6 +40,8 @@ export const evolutionBotSchema: JSONSchema7 = { keepOpen: { type: 'boolean' }, debounceTime: { type: 'integer' }, ignoreJids: { type: 'array', items: { type: 'string' } }, + splitMessages: { type: 'boolean' }, + timePerChar: { type: 'integer' }, }, required: ['enabled', 'apiUrl', 'triggerType'], ...isNotEmpty('enabled', 'apiUrl', 'triggerType'), @@ -70,6 +72,8 @@ export const evolutionBotSettingSchema: JSONSchema7 = { debounceTime: { type: 'integer' }, ignoreJids: { type: 'array', items: { type: 'string' } }, botIdFallback: { type: 'string' }, + splitMessages: { type: 'boolean' }, + timePerChar: { type: 'integer' }, }, required: [ 'expire', @@ -81,6 +85,8 @@ export const evolutionBotSettingSchema: JSONSchema7 = { 'keepOpen', 'debounceTime', 'ignoreJids', + 'splitMessages', + 'timePerChar', ], ...isNotEmpty( 'expire', @@ -92,6 +98,8 @@ export const evolutionBotSettingSchema: JSONSchema7 = { 'keepOpen', 'debounceTime', 'ignoreJids', + 'splitMessages', + 'timePerChar', ), }; diff --git a/src/api/integrations/chatbot/flowise/controllers/flowise.controller.ts b/src/api/integrations/chatbot/flowise/controllers/flowise.controller.ts index 227bbcb5..eab68710 100644 --- a/src/api/integrations/chatbot/flowise/controllers/flowise.controller.ts +++ b/src/api/integrations/chatbot/flowise/controllers/flowise.controller.ts @@ -50,7 +50,9 @@ export class FlowiseController extends ChatbotController implements ChatbotContr !data.stopBotFromMe || !data.keepOpen || !data.debounceTime || - !data.ignoreJids + !data.ignoreJids || + !data.splitMessages || + !data.timePerChar ) { const defaultSettingCheck = await this.settingsRepository.findFirst({ where: { @@ -67,6 +69,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr if (!data.keepOpen) data.keepOpen = defaultSettingCheck?.keepOpen || false; if (!data.debounceTime) data.debounceTime = defaultSettingCheck?.debounceTime || 0; if (!data.ignoreJids) data.ignoreJids = defaultSettingCheck?.ignoreJids || []; + if (!data.splitMessages) data.splitMessages = defaultSettingCheck?.splitMessages || false; + if (!data.timePerChar) data.timePerChar = defaultSettingCheck?.timePerChar || 0; if (!defaultSettingCheck) { await this.settings(instance, { @@ -79,6 +83,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr keepOpen: data.keepOpen, debounceTime: data.debounceTime, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }); } } @@ -162,6 +168,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -335,6 +343,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -420,6 +430,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr debounceTime: data.debounceTime, flowiseIdFallback: data.flowiseIdFallback, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -434,6 +446,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr debounceTime: updateSettings.debounceTime, flowiseIdFallback: updateSettings.flowiseIdFallback, ignoreJids: updateSettings.ignoreJids, + splitMessages: updateSettings.splitMessages, + timePerChar: updateSettings.timePerChar, }; } @@ -450,6 +464,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr flowiseIdFallback: data.flowiseIdFallback, ignoreJids: data.ignoreJids, instanceId: instanceId, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -464,6 +480,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr debounceTime: newSetttings.debounceTime, flowiseIdFallback: newSetttings.flowiseIdFallback, ignoreJids: newSetttings.ignoreJids, + splitMessages: newSetttings.splitMessages, + timePerChar: newSetttings.timePerChar, }; } catch (error) { this.logger.error(error); @@ -500,6 +518,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr stopBotFromMe: false, keepOpen: false, ignoreJids: [], + splitMessages: false, + timePerChar: 0, flowiseIdFallback: '', fallback: null, }; @@ -514,6 +534,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr stopBotFromMe: settings.stopBotFromMe, keepOpen: settings.keepOpen, ignoreJids: settings.ignoreJids, + splitMessages: settings.splitMessages, + timePerChar: settings.timePerChar, flowiseIdFallback: settings.flowiseIdFallback, fallback: settings.Fallback, }; @@ -735,6 +757,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr let keepOpen = findBot?.keepOpen; let debounceTime = findBot?.debounceTime; let ignoreJids = findBot?.ignoreJids; + let splitMessages = findBot?.splitMessages; + let timePerChar = findBot?.timePerChar; if (!expire) expire = settings.expire; if (!keywordFinish) keywordFinish = settings.keywordFinish; @@ -745,6 +769,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr if (!keepOpen) keepOpen = settings.keepOpen; if (!debounceTime) debounceTime = settings.debounceTime; if (!ignoreJids) ignoreJids = settings.ignoreJids; + if (splitMessages === undefined || splitMessages === null) splitMessages = settings?.splitMessages ?? false; + if (timePerChar === undefined || timePerChar === null) timePerChar = settings?.timePerChar ?? 0; const key = msg.key as { id: string; @@ -791,6 +817,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, debouncedContent, msg?.pushName, @@ -813,6 +841,8 @@ export class FlowiseController extends ChatbotController implements ChatbotContr keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, content, msg?.pushName, diff --git a/src/api/integrations/chatbot/flowise/dto/flowise.dto.ts b/src/api/integrations/chatbot/flowise/dto/flowise.dto.ts index a840a75c..98e612ad 100644 --- a/src/api/integrations/chatbot/flowise/dto/flowise.dto.ts +++ b/src/api/integrations/chatbot/flowise/dto/flowise.dto.ts @@ -17,6 +17,8 @@ export class FlowiseDto { triggerOperator?: TriggerOperator; triggerValue?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } export class FlowiseSettingDto { @@ -30,4 +32,6 @@ export class FlowiseSettingDto { debounceTime?: number; flowiseIdFallback?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } diff --git a/src/api/integrations/chatbot/flowise/services/flowise.service.ts b/src/api/integrations/chatbot/flowise/services/flowise.service.ts index d091dc1e..d1ab4e2f 100644 --- a/src/api/integrations/chatbot/flowise/services/flowise.service.ts +++ b/src/api/integrations/chatbot/flowise/services/flowise.service.ts @@ -143,16 +143,54 @@ export class FlowiseService { } if (mediaType) { + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); - textBuffer = ''; + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } if (mediaType === 'audio') { @@ -189,15 +227,54 @@ export class FlowiseService { } } + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } sendTelemetry('/message/sendText'); diff --git a/src/api/integrations/chatbot/openai/controllers/openai.controller.ts b/src/api/integrations/chatbot/openai/controllers/openai.controller.ts index 50e40685..95a61b32 100644 --- a/src/api/integrations/chatbot/openai/controllers/openai.controller.ts +++ b/src/api/integrations/chatbot/openai/controllers/openai.controller.ts @@ -191,7 +191,9 @@ export class OpenaiController extends ChatbotController implements ChatbotContro !data.stopBotFromMe || !data.keepOpen || !data.debounceTime || - !data.ignoreJids + !data.ignoreJids || + !data.splitMessages || + !data.timePerChar ) { const defaultSettingCheck = await this.settingsRepository.findFirst({ where: { @@ -209,6 +211,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro if (!data.keepOpen) data.keepOpen = defaultSettingCheck?.keepOpen || false; if (!data.debounceTime) data.debounceTime = defaultSettingCheck?.debounceTime || 0; if (!data.ignoreJids) data.ignoreJids = defaultSettingCheck?.ignoreJids || []; + if (!data.splitMessages) data.splitMessages = defaultSettingCheck?.splitMessages || false; + if (!data.timePerChar) data.timePerChar = defaultSettingCheck?.timePerChar || 0; if (!data.openaiCredsId) { throw new Error('Openai Creds Id is required'); @@ -226,6 +230,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro keepOpen: data.keepOpen, debounceTime: data.debounceTime, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }); } } @@ -338,6 +344,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -546,6 +554,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro triggerOperator: data.triggerOperator, triggerValue: data.triggerValue, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -637,6 +647,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro speechToText: data.speechToText, openaiIdFallback: data.openaiIdFallback, ignoreJids: data.ignoreJids, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -653,6 +665,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro speechToText: updateSettings.speechToText, openaiIdFallback: updateSettings.openaiIdFallback, ignoreJids: updateSettings.ignoreJids, + splitMessages: updateSettings.splitMessages, + timePerChar: updateSettings.timePerChar, }; } @@ -671,6 +685,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro ignoreJids: data.ignoreJids, speechToText: data.speechToText, instanceId: instanceId, + splitMessages: data.splitMessages, + timePerChar: data.timePerChar, }, }); @@ -686,6 +702,9 @@ export class OpenaiController extends ChatbotController implements ChatbotContro debounceTime: newSetttings.debounceTime, openaiIdFallback: newSetttings.openaiIdFallback, ignoreJids: newSetttings.ignoreJids, + speechToText: newSetttings.speechToText, + splitMessages: newSetttings.splitMessages, + timePerChar: newSetttings.timePerChar, }; } catch (error) { this.logger.error(error); @@ -726,6 +745,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro stopBotFromMe: false, keepOpen: false, ignoreJids: [], + splitMessages: false, + timePerChar: 0, openaiIdFallback: null, speechToText: false, fallback: null, @@ -742,6 +763,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro stopBotFromMe: settings.stopBotFromMe, keepOpen: settings.keepOpen, ignoreJids: settings.ignoreJids, + splitMessages: settings.splitMessages, + timePerChar: settings.timePerChar, openaiIdFallback: settings.openaiIdFallback, speechToText: settings.speechToText, fallback: settings.Fallback, @@ -972,6 +995,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro let keepOpen = findBot?.keepOpen; let debounceTime = findBot?.debounceTime; let ignoreJids = findBot?.ignoreJids; + let splitMessages = findBot?.splitMessages; + let timePerChar = findBot?.timePerChar; if (!expire) expire = settings.expire; if (!keywordFinish) keywordFinish = settings.keywordFinish; @@ -982,6 +1007,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro if (!keepOpen) keepOpen = settings.keepOpen; if (!debounceTime) debounceTime = settings.debounceTime; if (!ignoreJids) ignoreJids = settings.ignoreJids; + if (splitMessages === undefined || splitMessages === null) splitMessages = settings?.splitMessages ?? false; + if (timePerChar === undefined || timePerChar === null) timePerChar = settings?.timePerChar ?? 0; const key = msg.key as { id: string; @@ -1030,6 +1057,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, debouncedContent, ); @@ -1053,6 +1082,8 @@ export class OpenaiController extends ChatbotController implements ChatbotContro keepOpen, debounceTime, ignoreJids, + splitMessages, + timePerChar, }, debouncedContent, ); diff --git a/src/api/integrations/chatbot/openai/dto/openai.dto.ts b/src/api/integrations/chatbot/openai/dto/openai.dto.ts index e3c996cd..a8ac2e4d 100644 --- a/src/api/integrations/chatbot/openai/dto/openai.dto.ts +++ b/src/api/integrations/chatbot/openai/dto/openai.dto.ts @@ -29,6 +29,8 @@ export class OpenaiDto { triggerOperator?: TriggerOperator; triggerValue?: string; ignoreJids?: any; + splitMessages?: boolean; + timePerChar?: number; } export class OpenaiSettingDto { @@ -44,4 +46,6 @@ export class OpenaiSettingDto { openaiIdFallback?: string; ignoreJids?: any; speechToText?: boolean; + splitMessages?: boolean; + timePerChar?: number; } diff --git a/src/api/integrations/chatbot/openai/services/openai.service.ts b/src/api/integrations/chatbot/openai/services/openai.service.ts index 2a7f372e..440e3941 100644 --- a/src/api/integrations/chatbot/openai/services/openai.service.ts +++ b/src/api/integrations/chatbot/openai/services/openai.service.ts @@ -188,16 +188,54 @@ export class OpenaiService { } if (mediaType) { + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); - textBuffer = ''; + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } if (mediaType === 'audio') { @@ -234,15 +272,54 @@ export class OpenaiService { } } + const splitMessages = settings.splitMessages ?? false; + const timePerChar = settings.timePerChar ?? 0; + const minDelay = 1000; + const maxDelay = 20000; + if (textBuffer.trim()) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: textBuffer.trim(), - }, - false, - ); + if (splitMessages) { + const multipleMessages = textBuffer.trim().split('\n\n'); + + for (let index = 0; index < multipleMessages.length; index++) { + const message = multipleMessages[index]; + + const delay = Math.min(Math.max(message.length * timePerChar, minDelay), maxDelay); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.presenceSubscribe(remoteJid); + await instance.client.sendPresenceUpdate('composing', remoteJid); + } + + await new Promise((resolve) => { + setTimeout(async () => { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: message, + }, + false, + ); + resolve(); + }, delay); + }); + + if (instance.integration === Integration.WHATSAPP_BAILEYS) { + await instance.client.sendPresenceUpdate('paused', remoteJid); + } + } + } else { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } } sendTelemetry('/message/sendText');