From 52fa931140b2e998bd76a72d3cfdf00fabf2ce1b Mon Sep 17 00:00:00 2001 From: Caio Bleggi Date: Tue, 9 Dec 2025 12:03:47 -0300 Subject: [PATCH] feat(channel): add support for @newsletter in sendMessage and findChannels --- src/api/controllers/chat.controller.ts | 4 ++ .../whatsapp/whatsapp.baileys.service.ts | 68 ++++++++++++++++++- src/api/routes/chat.router.ts | 10 +++ src/utils/createJid.ts | 7 +- 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/src/api/controllers/chat.controller.ts b/src/api/controllers/chat.controller.ts index 22e90b9f..6a21fa56 100644 --- a/src/api/controllers/chat.controller.ts +++ b/src/api/controllers/chat.controller.ts @@ -113,4 +113,8 @@ export class ChatController { public async blockUser({ instanceName }: InstanceDto, data: BlockUserDto) { return await this.waMonitor.waInstances[instanceName].blockUser(data); } + + public async fetchChannels({ instanceName }: InstanceDto, query: Query) { + return await this.waMonitor.waInstances[instanceName].fetchChannels(query); + } } diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 60e857fc..db743fac 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -3511,9 +3511,24 @@ export class BaileysStartupService extends ChannelStartupService { users: { number: string; jid: string; name?: string }[]; } = { groups: [], broadcast: [], users: [] }; + const onWhatsapp: OnWhatsAppDto[] = []; + data.numbers.forEach((number) => { const jid = createJid(number); + if (isJidNewsletter(jid)) { + onWhatsapp.push( + new OnWhatsAppDto( + jid, + true, // Newsletters are always valid + number, + undefined, // Can be fetched later if needed + 'newsletter', // Indicate it's a newsletter type + ), + ); + return; + } + if (isJidGroup(jid)) { jids.groups.push({ number, jid }); } else if (jid === 'status@broadcast') { @@ -3523,8 +3538,6 @@ export class BaileysStartupService extends ChannelStartupService { } }); - const onWhatsapp: OnWhatsAppDto[] = []; - // BROADCAST onWhatsapp.push(...jids.broadcast.map(({ jid, number }) => new OnWhatsAppDto(jid, false, number))); @@ -4700,6 +4713,10 @@ export class BaileysStartupService extends ChannelStartupService { } } + if (isJidNewsletter(message.key.remoteJid) && message.key.fromMe) { + messageRaw.status = status[3]; // DELIVERED MESSAGE TO NEWSLETTER CHANNEL + } + return messageRaw; } @@ -5119,4 +5136,51 @@ export class BaileysStartupService extends ChannelStartupService { }, }; } + public async fetchChannels(query: Query) { + const page = Number((query as any)?.page ?? 1); + const limit = Number((query as any)?.limit ?? (query as any)?.rows ?? 50); + const skip = (page - 1) * limit; + + const messages = await this.prismaRepository.message.findMany({ + where: { + instanceId: this.instanceId, + AND: [{ key: { path: ['remoteJid'], not: null } }], + }, + orderBy: { messageTimestamp: 'desc' }, + select: { + key: true, + messageTimestamp: true, + }, + }); + + const channelMap = new Map(); + + for (const msg of messages) { + const key = msg.key as any; + const remoteJid = key?.remoteJid as string | undefined; + if (!remoteJid || !isJidNewsletter(remoteJid)) continue; + + if (!channelMap.has(remoteJid)) { + channelMap.set(remoteJid, { + remoteJid, + pushName: undefined, // Push name is never stored for channels, so we set it as undefined + lastMessageTimestamp: msg.messageTimestamp, + }); + } + } + + const allChannels = Array.from(channelMap.values()); + + const total = allChannels.length; + const pages = Math.ceil(total / limit); + const records = allChannels.slice(skip, skip + limit); + + return { + total, + pages, + currentPage: page, + limit, + records, + }; + } } diff --git a/src/api/routes/chat.router.ts b/src/api/routes/chat.router.ts index 158947ed..f372950f 100644 --- a/src/api/routes/chat.router.ts +++ b/src/api/routes/chat.router.ts @@ -281,6 +281,16 @@ export class ChatRouter extends RouterBroker { }); return res.status(HttpStatus.CREATED).json(response); + }) + .post(this.routerPath('findChannels'), ...guards, async (req, res) => { + const response = await this.dataValidate({ + request: req, + schema: contactValidateSchema, + ClassRef: Query, + execute: (instance, query) => chatController.fetchChannels(instance, query as any), + }); + + return res.status(HttpStatus.OK).json(response); }); } diff --git a/src/utils/createJid.ts b/src/utils/createJid.ts index a680e821..23a3afe1 100644 --- a/src/utils/createJid.ts +++ b/src/utils/createJid.ts @@ -35,7 +35,12 @@ function formatBRNumber(jid: string) { export function createJid(number: string): string { number = number.replace(/:\d+/, ''); - if (number.includes('@g.us') || number.includes('@s.whatsapp.net') || number.includes('@lid')) { + if ( + number.includes('@g.us') || + number.includes('@s.whatsapp.net') || + number.includes('@lid') || + number.includes('@newsletter') + ) { return number; }