Skip to content

Commit

Permalink
chore: Improve performance of status update and message sending in gr…
Browse files Browse the repository at this point in the history
…oups

The performance of sending status updates and messages in groups has been significantly improved. The batch size for sending messages has been reduced from 200 to 1, which allows for more efficient processing.

The `whatsapp.baileys.service.ts` file has been modified to implement this change. The previous batch size was set to 200, which has been updated to 1. This change reduces the number of participants processed in each batch, resulting in improved performance.

This modification also includes a conditional statement to ensure that no further processing is performed when there are no more batches left. This enhancement aims to optimize the overall process of sending status updates and messages in groups.
  • Loading branch information
dgcode-tec committed Jun 27, 2024
1 parent d342a7b commit 5ea2763
Showing 1 changed file with 172 additions and 104 deletions.
276 changes: 172 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,65 @@ 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 = 1;

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;

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

await Promise.allSettled(
batches.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 5ea2763

Please sign in to comment.