feat: update Baileys library and add fake call feature

Updated the Baileys library reference in package.json and refactored imports across multiple files to use the new library. Added a new feature to handle fake calls in sendMessage.controller.ts and related DTOs. This change improves the integration with the Baileys library and introduces the ability to simulate calls, enhancing the testing capabilities. Main files modified: package.json, instance.controller.ts, sendMessage.controller.ts, chat.dto.ts, instance.dto.ts, sendMessage.dto.ts, chatwoot.service.ts, chatwoot-import-helper.ts, sendMessage.router.ts, cache.service.ts, channel.service.ts, whatsapp.baileys.service.ts, whatsapp.business.service.ts, wa.types.ts, rediscache.ts, use-multi-file-auth-state-prisma.ts, use-multi-file-auth-state-provider-files.ts, use-multi-file-auth-state-redis-db.ts, message.schema.ts.
This commit is contained in:
Davidson Gomes 2024-06-14 08:44:19 -03:00
parent 61d6ddfa81
commit 7dfc09ff16
19 changed files with 91 additions and 46 deletions

View File

@ -52,9 +52,9 @@
"@hapi/boom": "^10.0.1", "@hapi/boom": "^10.0.1",
"@prisma/client": "^5.15.0", "@prisma/client": "^5.15.0",
"@sentry/node": "^7.59.2", "@sentry/node": "^7.59.2",
"@whiskeysockets/baileys": "6.7.5",
"amqplib": "^0.10.3", "amqplib": "^0.10.3",
"axios": "^1.6.5", "axios": "^1.6.5",
"baileys": "github:bobslavtriev/Baileys",
"class-validator": "^0.14.1", "class-validator": "^0.14.1",
"compression": "^1.7.4", "compression": "^1.7.4",
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@ -1,5 +1,5 @@
import { JsonValue } from '@prisma/client/runtime/library'; import { JsonValue } from '@prisma/client/runtime/library';
import { delay } from '@whiskeysockets/baileys'; import { delay } from 'baileys';
import { isArray, isURL } from 'class-validator'; import { isArray, isURL } from 'class-validator';
import EventEmitter2 from 'eventemitter2'; import EventEmitter2 from 'eventemitter2';
import { v4 } from 'uuid'; import { v4 } from 'uuid';

View File

@ -3,6 +3,7 @@ import { isBase64, isURL } from 'class-validator';
import { BadRequestException } from '../../exceptions'; import { BadRequestException } from '../../exceptions';
import { InstanceDto } from '../dto/instance.dto'; import { InstanceDto } from '../dto/instance.dto';
import { import {
FakeCallDto,
SendAudioDto, SendAudioDto,
SendButtonDto, SendButtonDto,
SendContactDto, SendContactDto,
@ -84,4 +85,8 @@ export class SendMessageController {
public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto) { public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto) {
return await this.waMonitor.waInstances[instanceName].statusMessage(data); return await this.waMonitor.waInstances[instanceName].statusMessage(data);
} }
public async fakeCall({ instanceName }: InstanceDto, data: FakeCallDto) {
return await this.waMonitor.waInstances[instanceName].fakeCall(data);
}
} }

View File

@ -1,4 +1,4 @@
import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '@whiskeysockets/baileys'; import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from 'baileys';
export class OnWhatsAppDto { export class OnWhatsAppDto {
constructor( constructor(

View File

@ -1,4 +1,4 @@
import { WAPresence } from '@whiskeysockets/baileys'; import { WAPresence } from 'baileys';
export class InstanceDto { export class InstanceDto {
instanceName: string; instanceName: string;

View File

@ -1,4 +1,4 @@
import { proto, WAPresence } from '@whiskeysockets/baileys'; import { proto, WAPresence } from 'baileys';
export class Quoted { export class Quoted {
key: proto.IMessageKey; key: proto.IMessageKey;
@ -131,6 +131,11 @@ export class SendListDto extends Metadata {
sections: Section[]; sections: Section[];
} }
export class FakeCallDto extends Metadata {
number: string;
delay: number;
}
export class ContactMessage { export class ContactMessage {
fullName: string; fullName: string;
wuid: string; wuid: string;

View File

@ -9,8 +9,8 @@ import ChatwootClient, {
} from '@figuro/chatwoot-sdk'; } from '@figuro/chatwoot-sdk';
import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request'; import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request';
import { Chatwoot as ChatwootModel, Contact as ContactModel, Message as MessageModel } from '@prisma/client'; import { Chatwoot as ChatwootModel, Contact as ContactModel, Message as MessageModel } from '@prisma/client';
import { proto } from '@whiskeysockets/baileys';
import axios from 'axios'; import axios from 'axios';
import { proto } from 'baileys';
import FormData from 'form-data'; import FormData from 'form-data';
import { createReadStream, unlinkSync, writeFileSync } from 'fs'; import { createReadStream, unlinkSync, writeFileSync } from 'fs';
import Jimp from 'jimp'; import Jimp from 'jimp';

View File

@ -1,6 +1,6 @@
import { inbox } from '@figuro/chatwoot-sdk'; import { inbox } from '@figuro/chatwoot-sdk';
import { Chatwoot as ChatwootModel, Contact, Message } from '@prisma/client'; import { Chatwoot as ChatwootModel, Contact, Message } from '@prisma/client';
import { proto } from '@whiskeysockets/baileys'; import { proto } from 'baileys';
import { InstanceDto } from '../../../../api/dto/instance.dto'; import { InstanceDto } from '../../../../api/dto/instance.dto';
import { Chatwoot, configService } from '../../../../config/env.config'; import { Chatwoot, configService } from '../../../../config/env.config';

View File

@ -3,6 +3,7 @@ import { RequestHandler, Router } from 'express';
import { import {
audioMessageSchema, audioMessageSchema,
contactMessageSchema, contactMessageSchema,
fakeCallSchema,
listMessageSchema, listMessageSchema,
locationMessageSchema, locationMessageSchema,
mediaMessageSchema, mediaMessageSchema,
@ -15,6 +16,7 @@ import {
} from '../../validate/validate.schema'; } from '../../validate/validate.schema';
import { RouterBroker } from '../abstract/abstract.router'; import { RouterBroker } from '../abstract/abstract.router';
import { import {
FakeCallDto,
SendAudioDto, SendAudioDto,
SendContactDto, SendContactDto,
SendListDto, SendListDto,
@ -143,6 +145,16 @@ export class MessageRouter extends RouterBroker {
execute: (instance, data) => sendMessageController.sendList(instance, data), execute: (instance, data) => sendMessageController.sendList(instance, data),
}); });
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('fakeCall'), ...guards, async (req, res) => {
const response = await this.dataValidate<FakeCallDto>({
request: req,
schema: fakeCallSchema,
ClassRef: FakeCallDto,
execute: (instance, data) => sendMessageController.fakeCall(instance, data),
});
return res.status(HttpStatus.CREATED).json(response); return res.status(HttpStatus.CREATED).json(response);
}); });
// .post(this.routerPath('sendButtons'), ...guards, async (req, res) => { // .post(this.routerPath('sendButtons'), ...guards, async (req, res) => {

View File

@ -1,4 +1,4 @@
import { BufferJSON } from '@whiskeysockets/baileys'; import { BufferJSON } from 'baileys';
import { Logger } from '../../config/logger.config'; import { Logger } from '../../config/logger.config';
import { ICache } from '../abstract/abstract.cache'; import { ICache } from '../abstract/abstract.cache';

View File

@ -1,6 +1,6 @@
import { Contact, Message } from '@prisma/client'; import { Contact, Message } from '@prisma/client';
import { WASocket } from '@whiskeysockets/baileys';
import axios from 'axios'; import axios from 'axios';
import { WASocket } from 'baileys';
import { isURL } from 'class-validator'; import { isURL } from 'class-validator';
import EventEmitter2 from 'eventemitter2'; import EventEmitter2 from 'eventemitter2';
import { join } from 'path'; import { join } from 'path';

View File

@ -1,6 +1,7 @@
import ffmpegPath from '@ffmpeg-installer/ffmpeg'; import ffmpegPath from '@ffmpeg-installer/ffmpeg';
import { Boom } from '@hapi/boom'; import { Boom } from '@hapi/boom';
import { Instance } from '@prisma/client'; import { Instance } from '@prisma/client';
import axios from 'axios';
import makeWASocket, { import makeWASocket, {
AnyMessageContent, AnyMessageContent,
BufferedEventData, BufferedEventData,
@ -20,6 +21,7 @@ import makeWASocket, {
GroupMetadata, GroupMetadata,
isJidBroadcast, isJidBroadcast,
isJidGroup, isJidGroup,
isJidNewsletter,
isJidUser, isJidUser,
makeCacheableSignalKeyStore, makeCacheableSignalKeyStore,
MessageUpsertType, MessageUpsertType,
@ -34,10 +36,9 @@ import makeWASocket, {
WAMessageUpdate, WAMessageUpdate,
WAPresence, WAPresence,
WASocket, WASocket,
} from '@whiskeysockets/baileys'; } from 'baileys';
import { Label } from '@whiskeysockets/baileys/lib/Types/Label'; import { Label } from 'baileys/lib/Types/Label';
import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation'; import { LabelAssociation } from 'baileys/lib/Types/LabelAssociation';
import axios from 'axios';
import { isBase64, isURL } from 'class-validator'; import { isBase64, isURL } from 'class-validator';
import { randomBytes } from 'crypto'; import { randomBytes } from 'crypto';
import EventEmitter2 from 'eventemitter2'; import EventEmitter2 from 'eventemitter2';
@ -108,6 +109,7 @@ import { InstanceDto, SetPresenceDto } from '../../dto/instance.dto';
import { HandleLabelDto, LabelDto } from '../../dto/label.dto'; import { HandleLabelDto, LabelDto } from '../../dto/label.dto';
import { import {
ContactMessage, ContactMessage,
FakeCallDto,
MediaMessage, MediaMessage,
Options, Options,
SendAudioDto, SendAudioDto,
@ -244,7 +246,7 @@ export class BaileysStartupService extends ChannelStartupService {
public async getProfileStatus() { public async getProfileStatus() {
const status = await this.client.fetchStatus(this.instance.wuid); const status = await this.client.fetchStatus(this.instance.wuid);
return status.status; return status[0]?.status;
} }
public get profilePictureUrl() { public get profilePictureUrl() {
@ -588,7 +590,7 @@ export class BaileysStartupService extends ChannelStartupService {
shouldIgnoreJid: (jid) => { shouldIgnoreJid: (jid) => {
const isGroupJid = this.localSettings.groupsIgnore && isJidGroup(jid); const isGroupJid = this.localSettings.groupsIgnore && isJidGroup(jid);
const isBroadcast = !this.localSettings.readStatus && isJidBroadcast(jid); const isBroadcast = !this.localSettings.readStatus && isJidBroadcast(jid);
const isNewsletter = jid.includes('newsletter'); const isNewsletter = isJidNewsletter(jid);
return isGroupJid || isBroadcast || isNewsletter; return isGroupJid || isBroadcast || isNewsletter;
}, },
@ -601,6 +603,7 @@ export class BaileysStartupService extends ChannelStartupService {
}, },
userDevicesCache: this.userDevicesCache, userDevicesCache: this.userDevicesCache,
transactionOpts: { maxCommitRetries: 5, delayBetweenTriesMs: 2500 }, transactionOpts: { maxCommitRetries: 5, delayBetweenTriesMs: 2500 },
cachedGroupMetadata: this.getGroupMetadataCache,
patchMessageBeforeSending(message) { patchMessageBeforeSending(message) {
if ( if (
message.deviceSentMessage?.message?.listMessage?.listType === message.deviceSentMessage?.message?.listMessage?.listType ===
@ -1626,7 +1629,7 @@ export class BaileysStartupService extends ChannelStartupService {
try { try {
return { return {
wuid: jid, wuid: jid,
status: (await this.client.fetchStatus(jid))?.status, status: (await this.client.fetchStatus(jid))[0]?.status,
}; };
} catch (error) { } catch (error) {
return { return {
@ -1822,11 +1825,11 @@ export class BaileysStartupService extends ChannelStartupService {
} as unknown as AnyMessageContent, } as unknown as AnyMessageContent,
{ {
...option, ...option,
cachedGroupMetadata: useCachedGroupMetadata:
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED && !this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED !this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
? null ? false
: this.getGroupMetadataCache, : true,
} as unknown as MiscMessageGenerationOptions, } as unknown as MiscMessageGenerationOptions,
); );
} }
@ -1841,11 +1844,11 @@ export class BaileysStartupService extends ChannelStartupService {
} as unknown as AnyMessageContent, } as unknown as AnyMessageContent,
{ {
...option, ...option,
cachedGroupMetadata: useCachedGroupMetadata:
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED && !this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED !this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
? null ? false
: this.getGroupMetadataCache, : true,
} as unknown as MiscMessageGenerationOptions, } as unknown as MiscMessageGenerationOptions,
); );
} }
@ -1862,11 +1865,11 @@ export class BaileysStartupService extends ChannelStartupService {
}, },
{ {
...option, ...option,
cachedGroupMetadata: useCachedGroupMetadata:
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED && !this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED !this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
? null ? false
: this.getGroupMetadataCache, : true,
} as unknown as MiscMessageGenerationOptions, } as unknown as MiscMessageGenerationOptions,
); );
} }
@ -1888,11 +1891,11 @@ export class BaileysStartupService extends ChannelStartupService {
message as unknown as AnyMessageContent, message as unknown as AnyMessageContent,
{ {
...option, ...option,
cachedGroupMetadata: useCachedGroupMetadata:
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED && !this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED !this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
? null ? false
: this.getGroupMetadataCache, : true,
} as unknown as MiscMessageGenerationOptions, } as unknown as MiscMessageGenerationOptions,
); );
})(); })();
@ -3437,4 +3440,21 @@ export class BaileysStartupService extends ChannelStartupService {
public async templateMessage() { public async templateMessage() {
throw new Error('Method not available in the Baileys service'); throw new Error('Method not available in the Baileys service');
} }
public async fakeCall(data: FakeCallDto) {
try {
const number = this.createJid(data.number);
const mdDelay = data.delay ?? 0;
const call = await this.client.offerCall(number);
await delay(mdDelay);
await this.client.rejectCall(call.callId, call.toJid);
return call;
} catch (error) {
throw new BadRequestException('Error making fake call', error.toString());
}
}
} }

View File

@ -1351,4 +1351,7 @@ export class BusinessStartupService extends ChannelStartupService {
public async receiveMobileCode() { public async receiveMobileCode() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
} }
public async fakeCall() {
throw new BadRequestException('Method not available on WhatsApp Business API');
}
} }

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-namespace */ /* eslint-disable @typescript-eslint/no-namespace */
import { JsonValue } from '@prisma/client/runtime/library'; import { JsonValue } from '@prisma/client/runtime/library';
import { AuthenticationState, WAConnectionState } from '@whiskeysockets/baileys'; import { AuthenticationState, WAConnectionState } from 'baileys';
export enum Events { export enum Events {
APPLICATION_STARTUP = 'application.startup', APPLICATION_STARTUP = 'application.startup',

View File

@ -1,4 +1,4 @@
import { BufferJSON } from '@whiskeysockets/baileys'; import { BufferJSON } from 'baileys';
import { RedisClientType } from 'redis'; import { RedisClientType } from 'redis';
import { ICache } from '../api/abstract/abstract.cache'; import { ICache } from '../api/abstract/abstract.cache';

View File

@ -1,4 +1,4 @@
import { BufferJSON, initAuthCreds, WAProto as proto } from '@whiskeysockets/baileys'; import { BufferJSON, initAuthCreds, WAProto as proto } from 'baileys';
import fs from 'fs/promises'; import fs from 'fs/promises';
import path from 'path'; import path from 'path';

View File

@ -34,14 +34,7 @@
* *
*/ */
import { import { AuthenticationCreds, AuthenticationState, BufferJSON, initAuthCreds, proto, SignalDataTypeMap } from 'baileys';
AuthenticationCreds,
AuthenticationState,
BufferJSON,
initAuthCreds,
proto,
SignalDataTypeMap,
} from '@whiskeysockets/baileys';
import { isNotEmpty } from 'class-validator'; import { isNotEmpty } from 'class-validator';
import { ProviderFiles } from '../api/provider/sessions'; import { ProviderFiles } from '../api/provider/sessions';

View File

@ -1,10 +1,4 @@
import { import { AuthenticationCreds, AuthenticationState, initAuthCreds, proto, SignalDataTypeMap } from 'baileys';
AuthenticationCreds,
AuthenticationState,
initAuthCreds,
proto,
SignalDataTypeMap,
} from '@whiskeysockets/baileys';
import { CacheService } from '../api/services/cache.service'; import { CacheService } from '../api/services/cache.service';
import { Logger } from '../config/logger.config'; import { Logger } from '../config/logger.config';

View File

@ -358,3 +358,16 @@ export const listMessageSchema: JSONSchema7 = {
}, },
required: ['number', 'title', 'footerText', 'buttonText', 'sections'], required: ['number', 'title', 'footerText', 'buttonText', 'sections'],
}; };
export const fakeCallSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
number: { ...numberDefinition },
delay: {
type: 'integer',
description: 'Enter a value in milliseconds',
},
},
required: ['number', 'delay'],
};