Skip to content

Commit

Permalink
chore: Improve performance of status and message sending in groups
Browse files Browse the repository at this point in the history
This commit introduces changes to improve the performance of sending status updates and messages in groups for the Node.js project. Modifications include updating the 'whatsapp.baileys.service.ts' file, specifically optimizing the 'sendMessage' function. The updated function includes improvements to handle various message types, such as audio, poll, sticker, conversation, and status messages, and better handling of group participants. These changes aim to enhance the overall efficiency and responsiveness of the application when sending status updates and messages in group contexts.
  • Loading branch information
dgcode-tec committed Jun 27, 2024
1 parent d342a7b commit b8f52e2
Showing 1 changed file with 170 additions and 104 deletions.
274 changes: 170 additions & 104 deletions src/api/services/channels/whatsapp.baileys.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import makeWASocket, {
getContentType,
getDevice,
GroupMetadata,
GroupParticipant,
isJidBroadcast,
isJidGroup,
isJidNewsletter,
Expand All @@ -40,7 +41,6 @@ import makeWASocket, {
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';
// import { exec } from 'child_process';
import ffmpeg from 'fluent-ffmpeg';
Expand Down Expand Up @@ -1744,6 +1744,134 @@ export class BaileysStartupService extends ChannelStartupService {
}
}

private async sendMessage(
sender: string,
message: any,
mentions: any,
linkPreview: any,
quoted: any,
messageId?: string,
participants?: GroupParticipant[],
) {
const option: any = {
quoted,
};

if (messageId) option.messageId = messageId;

if (participants)
option.cachedGroupMetadata = async () => {
participants;
};
else
option.useCachedGroupMetadata =
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED;

if (
!message['audio'] &&
!message['poll'] &&
!message['sticker'] &&
!message['conversation'] &&
sender !== 'status@broadcast'
) {
if (message['reactionMessage']) {
return await this.client.sendMessage(
sender,
{
react: {
text: message['reactionMessage']['text'],
key: message['reactionMessage']['key'],
},
} as unknown as AnyMessageContent,
option as unknown as MiscMessageGenerationOptions,
);
}
}
if (message['conversation']) {
return await this.client.sendMessage(
sender,
{
text: message['conversation'],
mentions,
linkPreview: linkPreview,
} as unknown as AnyMessageContent,
option as unknown as MiscMessageGenerationOptions,
);
}

if (!message['audio'] && !message['poll'] && !message['sticker'] && sender != 'status@broadcast') {
return await this.client.sendMessage(
sender,
{
forward: {
key: { remoteJid: this.instance.wuid, fromMe: true },
message,
},
mentions,
},
option as unknown as MiscMessageGenerationOptions,
);
}

if (sender === 'status@broadcast') {
const jidList = message['status'].option.statusJidList;

const batchSize = 500;

const batches = Array.from({ length: Math.ceil(jidList.length / batchSize) }, (_, i) =>
jidList.slice(i * batchSize, i * batchSize + batchSize),
);

let msgId: string | null = null;

let firstMessage: WAMessage;

const firstBatch = batches.shift();

if (firstBatch) {
firstMessage = await this.client.sendMessage(
sender,
message['status'].content as unknown as AnyMessageContent,
{
backgroundColor: message['status'].option.backgroundColor,
font: message['status'].option.font,
statusJidList: firstBatch,
} as unknown as MiscMessageGenerationOptions,
);

msgId = firstMessage.key.id;
}

if (batches.length === 0) return firstMessage;

await Promise.allSettled(
batches.map(async (batch) => {
const messageSent = await this.client.sendMessage(
sender,
message['status'].content as unknown as AnyMessageContent,
{
backgroundColor: message['status'].option.backgroundColor,
font: message['status'].option.font,
statusJidList: batch,
messageId: msgId,
} as unknown as MiscMessageGenerationOptions,
);

return messageSent;
}),
);

return firstMessage;
}

return await this.client.sendMessage(
sender,
message as unknown as AnyMessageContent,
option as unknown as MiscMessageGenerationOptions,
);
}

private async sendMessageWithTyping<T = proto.IMessage>(
number: string,
message: T,
Expand Down Expand Up @@ -1818,125 +1946,63 @@ export class BaileysStartupService extends ChannelStartupService {
}
}

let messageSent: WAMessage;

let mentions: string[];
if (isJidGroup(sender)) {
let group;
try {
let group;

const cache = this.configService.get<CacheConf>('CACHE');
if (!cache.REDIS.ENABLED && !cache.LOCAL.ENABLED) group = await this.findGroup({ groupJid: sender }, 'inner');
else group = await this.getGroupMetadataCache(sender);

if (!group) {
throw new NotFoundException('Group not found');
}

if (options.mentionsEveryOne) {
mentions = group.participants.map((participant) => participant.id);
} else if (options.mentioned?.length) {
mentions = options.mentioned.map((mention) => {
const jid = this.createJid(mention);
if (isJidGroup(jid)) {
return null;
}
return jid;
});
}
} catch (error) {
throw new NotFoundException('Group not found');
}
}

const messageSent = await (async () => {
const option = {
quoted,
messageId: '3EB0' + randomBytes(18).toString('hex').toUpperCase(),
};

if (
!message['audio'] &&
!message['poll'] &&
!message['sticker'] &&
!message['conversation'] &&
sender !== 'status@broadcast'
) {
if (message['reactionMessage']) {
return await this.client.sendMessage(
sender,
{
react: {
text: message['reactionMessage']['text'],
key: message['reactionMessage']['key'],
},
} as unknown as AnyMessageContent,
{
...option,
useCachedGroupMetadata:
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
} as unknown as MiscMessageGenerationOptions,
);
}
}
if (message['conversation']) {
return await this.client.sendMessage(
sender,
{
text: message['conversation'],
mentions,
linkPreview: linkPreview,
} as unknown as AnyMessageContent,
{
...option,
useCachedGroupMetadata:
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
} as unknown as MiscMessageGenerationOptions,
);
if (!group) {
throw new NotFoundException('Group not found');
}

if (!message['audio'] && !message['poll'] && !message['sticker'] && sender != 'status@broadcast') {
return await this.client.sendMessage(
sender,
{
forward: {
key: { remoteJid: this.instance.wuid, fromMe: true },
message,
},
mentions,
},
{
...option,
useCachedGroupMetadata:
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
} as unknown as MiscMessageGenerationOptions,
);
const participansList = group.participants;

const batchSize = 200;

const batches = Array.from({ length: Math.ceil(participansList.length / batchSize) }, (_, i) =>
participansList.slice(i * batchSize, i * batchSize + batchSize),
);

if (options.mentionsEveryOne) {
mentions = group.participants.map((participant) => participant.id);
} else if (options.mentioned?.length) {
mentions = options.mentioned.map((mention) => {
const jid = this.createJid(mention);
if (isJidGroup(jid)) {
return null;
}
return jid;
});
}

if (sender === 'status@broadcast') {
return await this.client.sendMessage(
sender,
message['status'].content as unknown as AnyMessageContent,
{
backgroundColor: message['status'].option.backgroundColor,
font: message['status'].option.font,
statusJidList: message['status'].option.statusJidList,
} as unknown as MiscMessageGenerationOptions,
let msgId: string | null = null;

const firstBatch = batches.shift();

if (firstBatch) {
messageSent = await this.sendMessage(sender, message, mentions, linkPreview, quoted, null, firstBatch);

msgId = messageSent.key.id;

await Promise.allSettled(
firstBatch.map(async (batch: GroupParticipant[]) => {
const messageSent = await this.sendMessage(sender, message, mentions, linkPreview, quoted, msgId, batch);

return messageSent;
}),
);
}

return await this.client.sendMessage(
sender,
message as unknown as AnyMessageContent,
{
...option,
useCachedGroupMetadata:
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
} as unknown as MiscMessageGenerationOptions,
);
})();
} else {
messageSent = await this.sendMessage(sender, message, mentions, linkPreview, quoted);
}

const contentMsg = messageSent.message[getContentType(messageSent.message)] as any;

Expand Down

0 comments on commit b8f52e2

Please sign in to comment.