import { proto } from '@whiskeysockets/baileys'; import { NormalizedMessage, NormalizedReaction } from '@tower/types'; function extractText(msg: proto.IWebMessageInfo): string { const m = msg.message; if (!m) return ''; return ( m.conversation || m.extendedTextMessage?.text || m.imageMessage?.caption || m.videoMessage?.caption || m.documentMessage?.caption || '' ); } export function normalizeMessage( msg: proto.IWebMessageInfo, accountId: string, ): NormalizedMessage | null { const key = msg.key; if (!key) return null; const remoteJid = key.remoteJid ?? ''; // only group messages (group JIDs end with @g.us) if (!remoteJid.endsWith('@g.us')) return null; // skip our own outgoing messages if (key.fromMe) return null; if (!msg.message) return null; const platformMsgId = key.id; if (!platformMsgId) return null; const content = extractText(msg); return { platformMsgId, sourceGroupJid: remoteJid, senderJid: key.participant ?? '', senderName: msg.pushName ?? undefined, content, accountId, }; } export function normalizeReaction( msg: proto.IWebMessageInfo, accountId: string, selfJid?: string, ): NormalizedReaction | null { const key = msg.key; if (!key) return null; const remoteJid = key.remoteJid ?? ''; // only group messages (group JIDs end with @g.us) if (!remoteJid.endsWith('@g.us')) return null; // Allow fromMe reactions — admin may star from the connected account const reaction = msg.message?.reactionMessage; if (!reaction) return null; const targetMsgId = reaction.key?.id; if (!targetMsgId) return null; // For fromMe reactions Baileys uses LID internally; use selfJid (PN format) to match TOWER_ADMIN_JIDS const reactorJid = key.fromMe ? (selfJid ?? key.participant) : key.participant; if (!reactorJid) return null; return { reactorJid, targetMsgId, sourceGroupJid: remoteJid, // emoji is empty string ('') when reaction was removed (retraction) emoji: reaction.text ?? '', accountId, }; }