mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-13 15:14:49 -06:00
feat: evolution channel in instance create
This commit is contained in:
parent
2196f65b7a
commit
0e9cd21981
@ -7,6 +7,7 @@
|
||||
* Generic Bot Integration
|
||||
* Option to disable chatwoot bot contact with CHATWOOT_BOT_CONTACT
|
||||
* Added flowise integration
|
||||
* Added evolution channel on instance create
|
||||
|
||||
### Fixed
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
2
manager/dist/index.html
vendored
2
manager/dist/index.html
vendored
@ -5,7 +5,7 @@
|
||||
<link rel="icon" type="image/png" href="/assets/images/evolution-logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Evolution Manager</title>
|
||||
<script type="module" crossorigin src="/assets/index-CfE0Jl7j.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-BmAfUzu7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BJ9JMAl_.css">
|
||||
</head>
|
||||
<body>
|
||||
|
@ -36,11 +36,7 @@ export class InstanceController {
|
||||
|
||||
public async createInstance(instanceData: InstanceDto) {
|
||||
try {
|
||||
if (!instanceData.token && instanceData.integration === Integration.WHATSAPP_BUSINESS) {
|
||||
throw new BadRequestException('token is required');
|
||||
}
|
||||
|
||||
const instance = channelController.init(instanceData.integration, {
|
||||
const instance = channelController.init(instanceData, {
|
||||
configService: this.configService,
|
||||
eventEmitter: this.eventEmitter,
|
||||
prismaRepository: this.prismaRepository,
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { ProviderFiles } from '@api/provider/sessions';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { CacheService } from '@api/services/cache.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { ConfigService } from '@config/env.config';
|
||||
import { BadRequestException } from '@exceptions';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
|
||||
import { EvolutionStartupService } from './evolution/evolution.channel.service';
|
||||
import { BaileysStartupService } from './whatsapp/baileys/whatsapp.baileys.service';
|
||||
import { BusinessStartupService } from './whatsapp/business/whatsapp.business.service';
|
||||
|
||||
@ -19,8 +22,12 @@ type ChannelDataType = {
|
||||
};
|
||||
|
||||
export class ChannelController {
|
||||
public init(integration: string, data: ChannelDataType) {
|
||||
if (integration === Integration.WHATSAPP_BUSINESS) {
|
||||
public init(instanceData: InstanceDto, data: ChannelDataType) {
|
||||
if (!instanceData.token && instanceData.integration === Integration.WHATSAPP_BUSINESS) {
|
||||
throw new BadRequestException('token is required');
|
||||
}
|
||||
|
||||
if (instanceData.integration === Integration.WHATSAPP_BUSINESS) {
|
||||
return new BusinessStartupService(
|
||||
data.configService,
|
||||
data.eventEmitter,
|
||||
@ -32,6 +39,18 @@ export class ChannelController {
|
||||
);
|
||||
}
|
||||
|
||||
if (instanceData.integration === Integration.EVOLUTION) {
|
||||
return new EvolutionStartupService(
|
||||
data.configService,
|
||||
data.eventEmitter,
|
||||
data.prismaRepository,
|
||||
data.cache,
|
||||
data.chatwootCache,
|
||||
data.baileysCache,
|
||||
data.providerFiles,
|
||||
);
|
||||
}
|
||||
|
||||
return new BaileysStartupService(
|
||||
data.configService,
|
||||
data.eventEmitter,
|
||||
|
@ -0,0 +1,475 @@
|
||||
import { Options, SendAudioDto, SendMediaDto, SendTextDto } from '@api/dto/sendMessage.dto';
|
||||
import { ProviderFiles } from '@api/provider/sessions';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { chatbotController } from '@api/server.module';
|
||||
import { CacheService } from '@api/services/cache.service';
|
||||
import { ChannelStartupService } from '@api/services/channel.service';
|
||||
import { Events, wa } from '@api/types/wa.types';
|
||||
import { Chatwoot, ConfigService, Openai } from '@config/env.config';
|
||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||
import EventEmitter2 from 'eventemitter2';
|
||||
|
||||
export class EvolutionStartupService extends ChannelStartupService {
|
||||
constructor(
|
||||
public readonly configService: ConfigService,
|
||||
public readonly eventEmitter: EventEmitter2,
|
||||
public readonly prismaRepository: PrismaRepository,
|
||||
public readonly cache: CacheService,
|
||||
public readonly chatwootCache: CacheService,
|
||||
public readonly baileysCache: CacheService,
|
||||
private readonly providerFiles: ProviderFiles,
|
||||
) {
|
||||
super(configService, eventEmitter, prismaRepository, chatwootCache);
|
||||
|
||||
this.client = null;
|
||||
}
|
||||
|
||||
public client: any;
|
||||
|
||||
public stateConnection: wa.StateConnection = { state: 'open' };
|
||||
|
||||
public phoneNumber: string;
|
||||
public mobile: boolean;
|
||||
|
||||
public get connectionStatus() {
|
||||
return this.stateConnection;
|
||||
}
|
||||
|
||||
public async closeClient() {
|
||||
this.stateConnection = { state: 'close' };
|
||||
}
|
||||
|
||||
public get qrCode(): wa.QrCode {
|
||||
return {
|
||||
pairingCode: this.instance.qrcode?.pairingCode,
|
||||
code: this.instance.qrcode?.code,
|
||||
base64: this.instance.qrcode?.base64,
|
||||
count: this.instance.qrcode?.count,
|
||||
};
|
||||
}
|
||||
|
||||
public async logoutInstance() {
|
||||
await this.closeClient();
|
||||
}
|
||||
|
||||
public async profilePicture(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
|
||||
return {
|
||||
wuid: jid,
|
||||
profilePictureUrl: null,
|
||||
};
|
||||
}
|
||||
|
||||
public async getProfileName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public async profilePictureUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public async getProfileStatus() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public async connectToWhatsapp(data?: any): Promise<any> {
|
||||
if (!data) return;
|
||||
|
||||
try {
|
||||
this.loadChatwoot();
|
||||
|
||||
this.eventHandler(data);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new InternalServerErrorException(error?.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected async eventHandler(received: any) {
|
||||
try {
|
||||
let messageRaw: any;
|
||||
|
||||
if (received.message) {
|
||||
const key = {
|
||||
id: received.key.id,
|
||||
remoteJid: received.key.remoteJid,
|
||||
fromMe: received.key.fromMe,
|
||||
};
|
||||
messageRaw = {
|
||||
key,
|
||||
pushName: received.pushName,
|
||||
message: received.message,
|
||||
messageType: received.messageType,
|
||||
messageTimestamp: Math.round(new Date().getTime() / 1000),
|
||||
source: 'unknown',
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
if (this.configService.get<Openai>('OPENAI').ENABLED) {
|
||||
const openAiDefaultSettings = await this.prismaRepository.openaiSetting.findFirst({
|
||||
where: {
|
||||
instanceId: this.instanceId,
|
||||
},
|
||||
include: {
|
||||
OpenaiCreds: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
openAiDefaultSettings &&
|
||||
openAiDefaultSettings.openaiCredsId &&
|
||||
openAiDefaultSettings.speechToText &&
|
||||
received?.message?.audioMessage
|
||||
) {
|
||||
messageRaw.message.speechToText = await this.openaiService.speechToText(
|
||||
openAiDefaultSettings.OpenaiCreds,
|
||||
received,
|
||||
this.client.updateMediaMessage,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(messageRaw);
|
||||
|
||||
this.sendDataWebhook(Events.MESSAGES_UPSERT, messageRaw);
|
||||
|
||||
await chatbotController.emit({
|
||||
instance: { instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
msg: messageRaw,
|
||||
pushName: messageRaw.pushName,
|
||||
});
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled) {
|
||||
const chatwootSentMessage = await this.chatwootService.eventWhatsapp(
|
||||
Events.MESSAGES_UPSERT,
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
messageRaw,
|
||||
);
|
||||
|
||||
if (chatwootSentMessage?.id) {
|
||||
messageRaw.chatwootMessageId = chatwootSentMessage.id;
|
||||
messageRaw.chatwootInboxId = chatwootSentMessage.id;
|
||||
messageRaw.chatwootConversationId = chatwootSentMessage.id;
|
||||
}
|
||||
}
|
||||
|
||||
await this.prismaRepository.message.create({
|
||||
data: messageRaw,
|
||||
});
|
||||
|
||||
const contact = await this.prismaRepository.contact.findFirst({
|
||||
where: { instanceId: this.instanceId, remoteJid: key.remoteJid },
|
||||
});
|
||||
|
||||
const contactRaw: any = {
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
pushName: received.pushName,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
if (contactRaw.remoteJid === 'status@broadcast') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contact) {
|
||||
const contactRaw: any = {
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
pushName: received.pushName,
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPDATE, contactRaw);
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled) {
|
||||
await this.chatwootService.eventWhatsapp(
|
||||
Events.CONTACTS_UPDATE,
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
contactRaw,
|
||||
);
|
||||
}
|
||||
|
||||
await this.prismaRepository.contact.updateMany({
|
||||
where: { remoteJid: contact.remoteJid },
|
||||
data: contactRaw,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendDataWebhook(Events.CONTACTS_UPSERT, contactRaw);
|
||||
|
||||
this.prismaRepository.contact.create({
|
||||
data: contactRaw,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
protected async sendMessageWithTyping(number: string, message: any, options?: Options, isIntegration = false) {
|
||||
try {
|
||||
let quoted: any;
|
||||
let webhookUrl: any;
|
||||
|
||||
if (options?.quoted) {
|
||||
const m = options?.quoted;
|
||||
|
||||
const msg = m?.key;
|
||||
|
||||
if (!msg) {
|
||||
throw 'Message not found';
|
||||
}
|
||||
|
||||
quoted = msg;
|
||||
}
|
||||
|
||||
if (options?.webhookUrl) {
|
||||
webhookUrl = options.webhookUrl;
|
||||
}
|
||||
|
||||
const messageRaw: any = {
|
||||
key: { fromMe: true, id: 'ID', remoteJid: this.createJid(number) },
|
||||
message: {
|
||||
...message,
|
||||
quoted,
|
||||
},
|
||||
messageType: 'conversation',
|
||||
messageTimestamp: Math.round(new Date().getTime() / 1000),
|
||||
webhookUrl,
|
||||
source: 'unknown',
|
||||
instanceId: this.instanceId,
|
||||
};
|
||||
|
||||
this.logger.log(messageRaw);
|
||||
|
||||
this.sendDataWebhook(Events.SEND_MESSAGE, messageRaw);
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled && !isIntegration) {
|
||||
this.chatwootService.eventWhatsapp(
|
||||
Events.SEND_MESSAGE,
|
||||
{ instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
messageRaw,
|
||||
);
|
||||
}
|
||||
|
||||
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot.enabled && isIntegration)
|
||||
await chatbotController.emit({
|
||||
instance: { instanceName: this.instance.name, instanceId: this.instanceId },
|
||||
remoteJid: messageRaw.key.remoteJid,
|
||||
msg: messageRaw,
|
||||
pushName: messageRaw.pushName,
|
||||
});
|
||||
|
||||
await this.prismaRepository.message.create({
|
||||
data: messageRaw,
|
||||
});
|
||||
|
||||
return messageRaw;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new BadRequestException(error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public async textMessage(data: SendTextDto, isIntegration = false) {
|
||||
const res = await this.sendMessageWithTyping(
|
||||
data.number,
|
||||
{
|
||||
conversation: data.text,
|
||||
},
|
||||
{
|
||||
delay: data?.delay,
|
||||
presence: 'composing',
|
||||
quoted: data?.quoted,
|
||||
linkPreview: data?.linkPreview,
|
||||
mentionsEveryOne: data?.mentionsEveryOne,
|
||||
mentioned: data?.mentioned,
|
||||
},
|
||||
isIntegration,
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
public async mediaMessage(data: SendMediaDto, isIntegration = false) {
|
||||
const message = data;
|
||||
|
||||
return await this.sendMessageWithTyping(
|
||||
data.number,
|
||||
{ ...message },
|
||||
{
|
||||
delay: data?.delay,
|
||||
presence: 'composing',
|
||||
quoted: data?.quoted,
|
||||
linkPreview: data?.linkPreview,
|
||||
mentionsEveryOne: data?.mentionsEveryOne,
|
||||
mentioned: data?.mentioned,
|
||||
},
|
||||
isIntegration,
|
||||
);
|
||||
}
|
||||
|
||||
public async audioWhatsapp(data: SendAudioDto, isIntegration = false) {
|
||||
const message = data;
|
||||
|
||||
return await this.sendMessageWithTyping(
|
||||
data.number,
|
||||
{ ...message },
|
||||
{
|
||||
delay: data?.delay,
|
||||
presence: 'composing',
|
||||
quoted: data?.quoted,
|
||||
linkPreview: data?.linkPreview,
|
||||
mentionsEveryOne: data?.mentionsEveryOne,
|
||||
mentioned: data?.mentioned,
|
||||
},
|
||||
isIntegration,
|
||||
);
|
||||
}
|
||||
|
||||
public async buttonMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async locationMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async listMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async templateMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async contactMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async reactionMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async getBase64FromMediaMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async deleteMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async mediaSticker() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async pollMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async statusMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async reloadConnection() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async whatsappNumber() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async markMessageAsRead() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async archiveChat() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async markChatUnread() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fetchProfile() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async sendPresence() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async setPresence() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fetchPrivacySettings() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updatePrivacySettings() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fetchBusinessProfile() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateProfileName() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateProfileStatus() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateProfilePicture() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async removeProfilePicture() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async blockUser() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateMessage() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async createGroup() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateGroupPicture() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateGroupSubject() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateGroupDescription() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async findGroup() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fetchAllGroups() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async inviteCode() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async inviteInfo() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async sendInvite() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async acceptInviteCode() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async revokeInviteCode() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async findParticipants() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateGParticipant() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async updateGSetting() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async toggleEphemeral() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async leaveGroup() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fetchLabels() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async handleLabel() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async receiveMobileCode() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
public async fakeCall() {
|
||||
throw new BadRequestException('Method not available on Evolution Channel');
|
||||
}
|
||||
}
|
@ -85,17 +85,10 @@ export class BusinessStartupService extends ChannelStartupService {
|
||||
public async profilePicture(number: string) {
|
||||
const jid = this.createJid(number);
|
||||
|
||||
try {
|
||||
return {
|
||||
wuid: jid,
|
||||
profilePictureUrl: await this.client.profilePictureUrl(jid, 'image'),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
wuid: jid,
|
||||
profilePictureUrl: null,
|
||||
};
|
||||
}
|
||||
return {
|
||||
wuid: jid,
|
||||
profilePictureUrl: null,
|
||||
};
|
||||
}
|
||||
|
||||
public async getProfileName() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { Auth, ConfigService, HttpServer } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { Dify, DifySetting, IntegrationSession } from '@prisma/client';
|
||||
@ -91,9 +92,10 @@ export class DifyService {
|
||||
payload.query = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers: {
|
||||
@ -101,7 +103,8 @@ export class DifyService {
|
||||
},
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.answer;
|
||||
const conversationId = response?.data?.conversation_id;
|
||||
@ -149,9 +152,10 @@ export class DifyService {
|
||||
payload.inputs.query = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers: {
|
||||
@ -159,7 +163,8 @@ export class DifyService {
|
||||
},
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.answer;
|
||||
const conversationId = response?.data?.conversation_id;
|
||||
@ -207,9 +212,10 @@ export class DifyService {
|
||||
payload.query = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers: {
|
||||
@ -243,7 +249,8 @@ export class DifyService {
|
||||
});
|
||||
|
||||
reader.on('end', async () => {
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = answer;
|
||||
|
||||
@ -297,9 +304,10 @@ export class DifyService {
|
||||
payload.inputs.query = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const response = await axios.post(endpoint, payload, {
|
||||
headers: {
|
||||
@ -307,7 +315,8 @@ export class DifyService {
|
||||
},
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.data.outputs.text;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { Auth, ConfigService, HttpServer } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { Flowise, FlowiseSetting, IntegrationSession } from '@prisma/client';
|
||||
@ -76,9 +77,10 @@ export class FlowiseService {
|
||||
payload.question = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
let headers: any = {
|
||||
'Content-Type': 'application/json',
|
||||
@ -99,7 +101,8 @@ export class FlowiseService {
|
||||
headers,
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.text;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { Auth, ConfigService, HttpServer } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { GenericBot, GenericSetting, IntegrationSession } from '@prisma/client';
|
||||
@ -73,9 +74,10 @@ export class GenericService {
|
||||
payload.query = contentSplit[2] || content;
|
||||
}
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
let headers: any = {
|
||||
'Content-Type': 'application/json',
|
||||
@ -92,7 +94,8 @@ export class GenericService {
|
||||
headers,
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data?.answer;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { WAMonitoringService } from '@api/services/monitor.service';
|
||||
import { Integration } from '@api/types/wa.types';
|
||||
import { ConfigService, Language } from '@config/env.config';
|
||||
import { Logger } from '@config/logger.config';
|
||||
import { IntegrationSession, OpenaiBot, OpenaiCreds, OpenaiSetting } from '@prisma/client';
|
||||
@ -73,9 +74,10 @@ export class OpenaiService {
|
||||
|
||||
const messages: any[] = [...messagesSystem, ...messagesAssistant, ...messagesUser, messageData];
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const completions = await this.client.chat.completions.create({
|
||||
model: openaiBot.model,
|
||||
@ -83,7 +85,8 @@ export class OpenaiService {
|
||||
max_tokens: openaiBot.maxTokens,
|
||||
});
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = completions.choices[0].message.content;
|
||||
|
||||
@ -131,13 +134,15 @@ export class OpenaiService {
|
||||
assistant_id: openaiBot.assistantId,
|
||||
});
|
||||
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS) {
|
||||
await instance.client.presenceSubscribe(remoteJid);
|
||||
await instance.client.sendPresenceUpdate('composing', remoteJid);
|
||||
}
|
||||
|
||||
const response = await this.getAIResponse(threadId, runAssistant.id, openaiBot.functionUrl, remoteJid, pushName);
|
||||
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
if (instance.integration === Integration.WHATSAPP_BAILEYS)
|
||||
await instance.client.sendPresenceUpdate('paused', remoteJid);
|
||||
|
||||
const message = response?.data[0].content[0].text.value;
|
||||
|
||||
|
@ -187,7 +187,7 @@ export class WebhookController extends EventController implements EventControlle
|
||||
}
|
||||
}
|
||||
|
||||
public async receiveWebhook(data: any) {
|
||||
public async receiveWebhookMeta(data: any) {
|
||||
if (data.object === 'whatsapp_business_account') {
|
||||
if (data.entry[0]?.changes[0]?.field === 'message_template_status_update') {
|
||||
const template = await this.prismaRepository.template.findFirst({
|
||||
@ -213,7 +213,7 @@ export class WebhookController extends EventController implements EventControlle
|
||||
const numberId = entry.changes[0].value.metadata.phone_number_id;
|
||||
|
||||
if (!numberId) {
|
||||
this.logger.error('WebhookService -> receiveWebhook -> numberId not found');
|
||||
this.logger.error('WebhookService -> receiveWebhookMeta -> numberId not found');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ export class WebhookController extends EventController implements EventControlle
|
||||
});
|
||||
|
||||
if (!instance) {
|
||||
this.logger.error('WebhookService -> receiveWebhook -> instance not found');
|
||||
this.logger.error('WebhookService -> receiveWebhookMeta -> instance not found');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -234,4 +234,28 @@ export class WebhookController extends EventController implements EventControlle
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public async receiveWebhookEvolution(data: any) {
|
||||
const numberId = data.numberId;
|
||||
|
||||
if (!numberId) {
|
||||
this.logger.error('WebhookService -> receiveWebhookEvolution -> numberId not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const instance = await this.prismaRepository.instance.findFirst({
|
||||
where: { number: numberId },
|
||||
});
|
||||
|
||||
if (!instance) {
|
||||
this.logger.error('WebhookService -> receiveWebhook -> instance not found');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data);
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,20 @@ export class WebhookRouter extends RouterBroker {
|
||||
|
||||
res.status(HttpStatus.OK).json(response);
|
||||
})
|
||||
.get('meta', async (req, res) => {
|
||||
.get(this.routerPath('meta', false), async (req, res) => {
|
||||
if (req.query['hub.verify_token'] === configService.get<WaBusiness>('WA_BUSINESS').TOKEN_WEBHOOK)
|
||||
res.send(req.query['hub.challenge']);
|
||||
else res.send('Error, wrong validation token');
|
||||
})
|
||||
.post('meta', async (req, res) => {
|
||||
.post(this.routerPath('meta', false), async (req, res) => {
|
||||
const { body } = req;
|
||||
const response = await webhookController.receiveWebhook(body);
|
||||
const response = await webhookController.receiveWebhookMeta(body);
|
||||
|
||||
return res.status(200).json(response);
|
||||
})
|
||||
.post(this.routerPath('evolution', false), async (req, res) => {
|
||||
const { body } = req;
|
||||
const response = await webhookController.receiveWebhookEvolution(body);
|
||||
|
||||
return res.status(200).json(response);
|
||||
});
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { InstanceDto } from '@api/dto/instance.dto';
|
||||
import { BaileysStartupService } from '@api/integrations/channel/whatsapp/baileys/whatsapp.baileys.service';
|
||||
import { BusinessStartupService } from '@api/integrations/channel/whatsapp/business/whatsapp.business.service';
|
||||
import { ProviderFiles } from '@api/provider/sessions';
|
||||
import { PrismaRepository } from '@api/repository/repository.service';
|
||||
import { channelController } from '@api/server.module';
|
||||
@ -37,7 +35,7 @@ export class WAMonitoringService {
|
||||
private readonly redis: Partial<CacheConf> = {};
|
||||
|
||||
private readonly logger = new Logger('WAMonitoringService');
|
||||
public readonly waInstances: Record<string, BaileysStartupService | BusinessStartupService> = {};
|
||||
public readonly waInstances: Record<string, any> = {};
|
||||
|
||||
private readonly providerSession = Object.freeze(this.configService.get<ProviderSession>('PROVIDER'));
|
||||
|
||||
@ -196,7 +194,7 @@ export class WAMonitoringService {
|
||||
data: {
|
||||
id: data.instanceId,
|
||||
name: data.instanceName,
|
||||
connectionStatus: data.integration && data.integration === Integration.WHATSAPP_BUSINESS ? 'open' : 'close',
|
||||
connectionStatus: data.integration && data.integration === Integration.WHATSAPP_BAILEYS ? 'close' : 'open',
|
||||
number: data.number,
|
||||
integration: data.integration || Integration.WHATSAPP_BAILEYS,
|
||||
token: data.hash,
|
||||
@ -210,7 +208,7 @@ export class WAMonitoringService {
|
||||
}
|
||||
|
||||
private async setInstance(instanceData: InstanceDto) {
|
||||
const instance = channelController.init(instanceData.integration, {
|
||||
const instance = channelController.init(instanceData, {
|
||||
configService: this.configService,
|
||||
eventEmitter: this.eventEmitter,
|
||||
prismaRepository: this.prismaRepository,
|
||||
|
@ -146,4 +146,5 @@ export const MessageSubtype = [
|
||||
export const Integration = {
|
||||
WHATSAPP_BUSINESS: 'WHATSAPP-BUSINESS',
|
||||
WHATSAPP_BAILEYS: 'WHATSAPP-BAILEYS',
|
||||
EVOLUTION: 'EVOLUTION',
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user