From 7dfc09ff16e940a056cdb39e770e167838671b7e Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 14 Jun 2024 08:44:19 -0300 Subject: [PATCH] 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. --- package.json | 2 +- src/api/controllers/instance.controller.ts | 2 +- src/api/controllers/sendMessage.controller.ts | 5 ++ src/api/dto/chat.dto.ts | 2 +- src/api/dto/instance.dto.ts | 2 +- src/api/dto/sendMessage.dto.ts | 7 ++- .../chatwoot/services/chatwoot.service.ts | 2 +- .../chatwoot/utils/chatwoot-import-helper.ts | 2 +- src/api/routes/sendMessage.router.ts | 12 ++++ src/api/services/cache.service.ts | 2 +- src/api/services/channel.service.ts | 2 +- .../channels/whatsapp.baileys.service.ts | 58 +++++++++++++------ .../channels/whatsapp.business.service.ts | 3 + src/api/types/wa.types.ts | 2 +- src/cache/rediscache.ts | 2 +- src/utils/use-multi-file-auth-state-prisma.ts | 2 +- ...se-multi-file-auth-state-provider-files.ts | 9 +-- .../use-multi-file-auth-state-redis-db.ts | 8 +-- src/validate/message.schema.ts | 13 +++++ 19 files changed, 91 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 45a5685b..37b58b4a 100644 --- a/package.json +++ b/package.json @@ -52,9 +52,9 @@ "@hapi/boom": "^10.0.1", "@prisma/client": "^5.15.0", "@sentry/node": "^7.59.2", - "@whiskeysockets/baileys": "6.7.5", "amqplib": "^0.10.3", "axios": "^1.6.5", + "baileys": "github:bobslavtriev/Baileys", "class-validator": "^0.14.1", "compression": "^1.7.4", "cors": "^2.8.5", diff --git a/src/api/controllers/instance.controller.ts b/src/api/controllers/instance.controller.ts index a055579b..bffdf5b3 100644 --- a/src/api/controllers/instance.controller.ts +++ b/src/api/controllers/instance.controller.ts @@ -1,5 +1,5 @@ import { JsonValue } from '@prisma/client/runtime/library'; -import { delay } from '@whiskeysockets/baileys'; +import { delay } from 'baileys'; import { isArray, isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; import { v4 } from 'uuid'; diff --git a/src/api/controllers/sendMessage.controller.ts b/src/api/controllers/sendMessage.controller.ts index 8c005094..f6ce54c3 100644 --- a/src/api/controllers/sendMessage.controller.ts +++ b/src/api/controllers/sendMessage.controller.ts @@ -3,6 +3,7 @@ import { isBase64, isURL } from 'class-validator'; import { BadRequestException } from '../../exceptions'; import { InstanceDto } from '../dto/instance.dto'; import { + FakeCallDto, SendAudioDto, SendButtonDto, SendContactDto, @@ -84,4 +85,8 @@ export class SendMessageController { public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto) { return await this.waMonitor.waInstances[instanceName].statusMessage(data); } + + public async fakeCall({ instanceName }: InstanceDto, data: FakeCallDto) { + return await this.waMonitor.waInstances[instanceName].fakeCall(data); + } } diff --git a/src/api/dto/chat.dto.ts b/src/api/dto/chat.dto.ts index 6865faf2..0d03987e 100644 --- a/src/api/dto/chat.dto.ts +++ b/src/api/dto/chat.dto.ts @@ -1,4 +1,4 @@ -import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '@whiskeysockets/baileys'; +import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from 'baileys'; export class OnWhatsAppDto { constructor( diff --git a/src/api/dto/instance.dto.ts b/src/api/dto/instance.dto.ts index ff465e8e..3a32f636 100644 --- a/src/api/dto/instance.dto.ts +++ b/src/api/dto/instance.dto.ts @@ -1,4 +1,4 @@ -import { WAPresence } from '@whiskeysockets/baileys'; +import { WAPresence } from 'baileys'; export class InstanceDto { instanceName: string; diff --git a/src/api/dto/sendMessage.dto.ts b/src/api/dto/sendMessage.dto.ts index cfd9d47d..7387a243 100644 --- a/src/api/dto/sendMessage.dto.ts +++ b/src/api/dto/sendMessage.dto.ts @@ -1,4 +1,4 @@ -import { proto, WAPresence } from '@whiskeysockets/baileys'; +import { proto, WAPresence } from 'baileys'; export class Quoted { key: proto.IMessageKey; @@ -131,6 +131,11 @@ export class SendListDto extends Metadata { sections: Section[]; } +export class FakeCallDto extends Metadata { + number: string; + delay: number; +} + export class ContactMessage { fullName: string; wuid: string; diff --git a/src/api/integrations/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatwoot/services/chatwoot.service.ts index fed5b787..de0c3a59 100644 --- a/src/api/integrations/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatwoot/services/chatwoot.service.ts @@ -9,8 +9,8 @@ import ChatwootClient, { } from '@figuro/chatwoot-sdk'; 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 { proto } from '@whiskeysockets/baileys'; import axios from 'axios'; +import { proto } from 'baileys'; import FormData from 'form-data'; import { createReadStream, unlinkSync, writeFileSync } from 'fs'; import Jimp from 'jimp'; diff --git a/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts b/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts index eea3831b..cf4b3f89 100644 --- a/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts +++ b/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts @@ -1,6 +1,6 @@ import { inbox } from '@figuro/chatwoot-sdk'; 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 { Chatwoot, configService } from '../../../../config/env.config'; diff --git a/src/api/routes/sendMessage.router.ts b/src/api/routes/sendMessage.router.ts index 006b49ef..223bbd3f 100644 --- a/src/api/routes/sendMessage.router.ts +++ b/src/api/routes/sendMessage.router.ts @@ -3,6 +3,7 @@ import { RequestHandler, Router } from 'express'; import { audioMessageSchema, contactMessageSchema, + fakeCallSchema, listMessageSchema, locationMessageSchema, mediaMessageSchema, @@ -15,6 +16,7 @@ import { } from '../../validate/validate.schema'; import { RouterBroker } from '../abstract/abstract.router'; import { + FakeCallDto, SendAudioDto, SendContactDto, SendListDto, @@ -143,6 +145,16 @@ export class MessageRouter extends RouterBroker { 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({ + request: req, + schema: fakeCallSchema, + ClassRef: FakeCallDto, + execute: (instance, data) => sendMessageController.fakeCall(instance, data), + }); + return res.status(HttpStatus.CREATED).json(response); }); // .post(this.routerPath('sendButtons'), ...guards, async (req, res) => { diff --git a/src/api/services/cache.service.ts b/src/api/services/cache.service.ts index 3cd1e87e..b528b157 100644 --- a/src/api/services/cache.service.ts +++ b/src/api/services/cache.service.ts @@ -1,4 +1,4 @@ -import { BufferJSON } from '@whiskeysockets/baileys'; +import { BufferJSON } from 'baileys'; import { Logger } from '../../config/logger.config'; import { ICache } from '../abstract/abstract.cache'; diff --git a/src/api/services/channel.service.ts b/src/api/services/channel.service.ts index 52eb3297..87527818 100644 --- a/src/api/services/channel.service.ts +++ b/src/api/services/channel.service.ts @@ -1,6 +1,6 @@ import { Contact, Message } from '@prisma/client'; -import { WASocket } from '@whiskeysockets/baileys'; import axios from 'axios'; +import { WASocket } from 'baileys'; import { isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; import { join } from 'path'; diff --git a/src/api/services/channels/whatsapp.baileys.service.ts b/src/api/services/channels/whatsapp.baileys.service.ts index efa5fc9e..d280d008 100644 --- a/src/api/services/channels/whatsapp.baileys.service.ts +++ b/src/api/services/channels/whatsapp.baileys.service.ts @@ -1,6 +1,7 @@ import ffmpegPath from '@ffmpeg-installer/ffmpeg'; import { Boom } from '@hapi/boom'; import { Instance } from '@prisma/client'; +import axios from 'axios'; import makeWASocket, { AnyMessageContent, BufferedEventData, @@ -20,6 +21,7 @@ import makeWASocket, { GroupMetadata, isJidBroadcast, isJidGroup, + isJidNewsletter, isJidUser, makeCacheableSignalKeyStore, MessageUpsertType, @@ -34,10 +36,9 @@ import makeWASocket, { WAMessageUpdate, WAPresence, WASocket, -} from '@whiskeysockets/baileys'; -import { Label } from '@whiskeysockets/baileys/lib/Types/Label'; -import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation'; -import axios from 'axios'; +} from 'baileys'; +import { Label } from 'baileys/lib/Types/Label'; +import { LabelAssociation } from 'baileys/lib/Types/LabelAssociation'; import { isBase64, isURL } from 'class-validator'; import { randomBytes } from 'crypto'; import EventEmitter2 from 'eventemitter2'; @@ -108,6 +109,7 @@ import { InstanceDto, SetPresenceDto } from '../../dto/instance.dto'; import { HandleLabelDto, LabelDto } from '../../dto/label.dto'; import { ContactMessage, + FakeCallDto, MediaMessage, Options, SendAudioDto, @@ -244,7 +246,7 @@ export class BaileysStartupService extends ChannelStartupService { public async getProfileStatus() { const status = await this.client.fetchStatus(this.instance.wuid); - return status.status; + return status[0]?.status; } public get profilePictureUrl() { @@ -588,7 +590,7 @@ export class BaileysStartupService extends ChannelStartupService { shouldIgnoreJid: (jid) => { const isGroupJid = this.localSettings.groupsIgnore && isJidGroup(jid); const isBroadcast = !this.localSettings.readStatus && isJidBroadcast(jid); - const isNewsletter = jid.includes('newsletter'); + const isNewsletter = isJidNewsletter(jid); return isGroupJid || isBroadcast || isNewsletter; }, @@ -601,6 +603,7 @@ export class BaileysStartupService extends ChannelStartupService { }, userDevicesCache: this.userDevicesCache, transactionOpts: { maxCommitRetries: 5, delayBetweenTriesMs: 2500 }, + cachedGroupMetadata: this.getGroupMetadataCache, patchMessageBeforeSending(message) { if ( message.deviceSentMessage?.message?.listMessage?.listType === @@ -1626,7 +1629,7 @@ export class BaileysStartupService extends ChannelStartupService { try { return { wuid: jid, - status: (await this.client.fetchStatus(jid))?.status, + status: (await this.client.fetchStatus(jid))[0]?.status, }; } catch (error) { return { @@ -1822,11 +1825,11 @@ export class BaileysStartupService extends ChannelStartupService { } as unknown as AnyMessageContent, { ...option, - cachedGroupMetadata: + useCachedGroupMetadata: !this.configService.get('CACHE').REDIS.ENABLED && !this.configService.get('CACHE').LOCAL.ENABLED - ? null - : this.getGroupMetadataCache, + ? false + : true, } as unknown as MiscMessageGenerationOptions, ); } @@ -1841,11 +1844,11 @@ export class BaileysStartupService extends ChannelStartupService { } as unknown as AnyMessageContent, { ...option, - cachedGroupMetadata: + useCachedGroupMetadata: !this.configService.get('CACHE').REDIS.ENABLED && !this.configService.get('CACHE').LOCAL.ENABLED - ? null - : this.getGroupMetadataCache, + ? false + : true, } as unknown as MiscMessageGenerationOptions, ); } @@ -1862,11 +1865,11 @@ export class BaileysStartupService extends ChannelStartupService { }, { ...option, - cachedGroupMetadata: + useCachedGroupMetadata: !this.configService.get('CACHE').REDIS.ENABLED && !this.configService.get('CACHE').LOCAL.ENABLED - ? null - : this.getGroupMetadataCache, + ? false + : true, } as unknown as MiscMessageGenerationOptions, ); } @@ -1888,11 +1891,11 @@ export class BaileysStartupService extends ChannelStartupService { message as unknown as AnyMessageContent, { ...option, - cachedGroupMetadata: + useCachedGroupMetadata: !this.configService.get('CACHE').REDIS.ENABLED && !this.configService.get('CACHE').LOCAL.ENABLED - ? null - : this.getGroupMetadataCache, + ? false + : true, } as unknown as MiscMessageGenerationOptions, ); })(); @@ -3437,4 +3440,21 @@ export class BaileysStartupService extends ChannelStartupService { public async templateMessage() { 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()); + } + } } diff --git a/src/api/services/channels/whatsapp.business.service.ts b/src/api/services/channels/whatsapp.business.service.ts index 7c7cf781..cc0cd893 100644 --- a/src/api/services/channels/whatsapp.business.service.ts +++ b/src/api/services/channels/whatsapp.business.service.ts @@ -1351,4 +1351,7 @@ export class BusinessStartupService extends ChannelStartupService { public async receiveMobileCode() { throw new BadRequestException('Method not available on WhatsApp Business API'); } + public async fakeCall() { + throw new BadRequestException('Method not available on WhatsApp Business API'); + } } diff --git a/src/api/types/wa.types.ts b/src/api/types/wa.types.ts index f6c05366..3d7fb796 100644 --- a/src/api/types/wa.types.ts +++ b/src/api/types/wa.types.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-namespace */ import { JsonValue } from '@prisma/client/runtime/library'; -import { AuthenticationState, WAConnectionState } from '@whiskeysockets/baileys'; +import { AuthenticationState, WAConnectionState } from 'baileys'; export enum Events { APPLICATION_STARTUP = 'application.startup', diff --git a/src/cache/rediscache.ts b/src/cache/rediscache.ts index 6e209ef1..c4e98968 100644 --- a/src/cache/rediscache.ts +++ b/src/cache/rediscache.ts @@ -1,4 +1,4 @@ -import { BufferJSON } from '@whiskeysockets/baileys'; +import { BufferJSON } from 'baileys'; import { RedisClientType } from 'redis'; import { ICache } from '../api/abstract/abstract.cache'; diff --git a/src/utils/use-multi-file-auth-state-prisma.ts b/src/utils/use-multi-file-auth-state-prisma.ts index 17bcb2ba..f1cfddf2 100644 --- a/src/utils/use-multi-file-auth-state-prisma.ts +++ b/src/utils/use-multi-file-auth-state-prisma.ts @@ -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 path from 'path'; diff --git a/src/utils/use-multi-file-auth-state-provider-files.ts b/src/utils/use-multi-file-auth-state-provider-files.ts index 1051af8f..ec4d7e6c 100644 --- a/src/utils/use-multi-file-auth-state-provider-files.ts +++ b/src/utils/use-multi-file-auth-state-provider-files.ts @@ -34,14 +34,7 @@ * └──────────────────────────────────────────────────────────────────────────────┘ */ -import { - AuthenticationCreds, - AuthenticationState, - BufferJSON, - initAuthCreds, - proto, - SignalDataTypeMap, -} from '@whiskeysockets/baileys'; +import { AuthenticationCreds, AuthenticationState, BufferJSON, initAuthCreds, proto, SignalDataTypeMap } from 'baileys'; import { isNotEmpty } from 'class-validator'; import { ProviderFiles } from '../api/provider/sessions'; diff --git a/src/utils/use-multi-file-auth-state-redis-db.ts b/src/utils/use-multi-file-auth-state-redis-db.ts index 66bb89ea..d077b894 100644 --- a/src/utils/use-multi-file-auth-state-redis-db.ts +++ b/src/utils/use-multi-file-auth-state-redis-db.ts @@ -1,10 +1,4 @@ -import { - AuthenticationCreds, - AuthenticationState, - initAuthCreds, - proto, - SignalDataTypeMap, -} from '@whiskeysockets/baileys'; +import { AuthenticationCreds, AuthenticationState, initAuthCreds, proto, SignalDataTypeMap } from 'baileys'; import { CacheService } from '../api/services/cache.service'; import { Logger } from '../config/logger.config'; diff --git a/src/validate/message.schema.ts b/src/validate/message.schema.ts index 1f7548b1..e2a01c59 100644 --- a/src/validate/message.schema.ts +++ b/src/validate/message.schema.ts @@ -358,3 +358,16 @@ export const listMessageSchema: JSONSchema7 = { }, 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'], +};