Feature: Agregar botón para crear webhook de debug automáticamente
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s

- Agregar botón "Crear Webhook de Debug" en WebhookReceiverSection
- Detectar si ya existe un webhook apuntando al receptor de debug
- Permitir eliminar el webhook de debug
- Incluir todos los eventos disponibles al crear el webhook
- También incluye mejoras previas de manejo de media y mensajes
This commit is contained in:
2025-12-02 21:21:33 -06:00
parent 71593b25e9
commit 80d0042c7e
21 changed files with 3722 additions and 112 deletions

View File

@@ -47,6 +47,8 @@ export interface InstanceEvents {
'message.received': { instanceId: string; message: any }
'message.sent': { instanceId: string; message: any }
'message.status': { instanceId: string; messageId: string; status: string }
'message.reaction': { instanceId: string; reaction: any }
'presence.update': { instanceId: string; jid: string; presences: Record<string, { lastKnownPresence: string; lastSeen?: number }> }
}
const logger = pino({ level: 'warn' })
@@ -372,6 +374,74 @@ class BaileysManager extends EventEmitter {
}
})
// Presence update
socket.ev.on('presence.update', async (update) => {
console.log(`[BaileysManager] presence.update:`, JSON.stringify(update))
this.emit('presence.update', {
instanceId,
jid: update.id,
presences: update.presences
})
// Cache presence in database
for (const [participantJid, presence] of Object.entries(update.presences)) {
try {
await query(
`INSERT INTO presence_cache (instance_id, jid, presence, last_seen)
VALUES ($1, $2, $3, $4)
ON CONFLICT (instance_id, jid) DO UPDATE SET
presence = EXCLUDED.presence,
last_seen = COALESCE(EXCLUDED.last_seen, presence_cache.last_seen)`,
[
instanceId,
participantJid,
presence.lastKnownPresence,
presence.lastSeen ? new Date(presence.lastSeen * 1000) : null
]
)
} catch (err) {
console.error(`[BaileysManager] Error caching presence:`, err)
}
}
})
// Message reactions
socket.ev.on('messages.reaction', async (reactions) => {
for (const reaction of reactions) {
console.log(`[BaileysManager] message.reaction:`, JSON.stringify(reaction))
this.emit('message.reaction', { instanceId, reaction })
// Save reaction to database
try {
const { key, reaction: reactionData } = reaction
if (reactionData.text) {
// Add reaction
await query(
`INSERT INTO message_reactions (message_id, reactor_jid, emoji)
SELECT m.id, $2, $3
FROM messages m
WHERE m.instance_id = $1 AND m.message_id = $4
ON CONFLICT (message_id, reactor_jid) DO UPDATE SET
emoji = EXCLUDED.emoji,
timestamp = NOW()`,
[instanceId, key.participant || key.fromMe ? 'me' : key.remoteJid, reactionData.text, reactionData.key.id]
)
} else {
// Remove reaction (empty text)
await query(
`DELETE FROM message_reactions
WHERE message_id IN (
SELECT id FROM messages WHERE instance_id = $1 AND message_id = $2
) AND reactor_jid = $3`,
[instanceId, reactionData.key.id, key.participant || key.fromMe ? 'me' : key.remoteJid]
)
}
} catch (err) {
console.error(`[BaileysManager] Error saving reaction:`, err)
}
}
})
// History sync - save chats and messages from history
socket.ev.on('messaging-history.set', async ({ chats, contacts, messages, syncType }) => {
console.log(`[BaileysManager] History sync received: ${chats?.length || 0} chats, ${contacts?.length || 0} contacts, ${messages?.length || 0} messages, type: ${syncType}`)
@@ -477,6 +547,53 @@ class BaileysManager extends EventEmitter {
return managed.socket
}
/**
* Subscribe to presence updates for a JID
*/
async subscribeToPresence(instanceId: string, jid: string): Promise<void> {
const managed = this.instances.get(instanceId)
if (!managed?.socket) {
throw new Error('Instance not connected')
}
await managed.socket.presenceSubscribe(jid)
console.log(`[BaileysManager] Subscribed to presence: ${jid}`)
}
/**
* Send presence update (composing, recording, available, unavailable, paused)
*/
async sendPresence(instanceId: string, jid: string, presence: 'composing' | 'recording' | 'available' | 'unavailable' | 'paused'): Promise<void> {
const managed = this.instances.get(instanceId)
if (!managed?.socket) {
throw new Error('Instance not connected')
}
await managed.socket.sendPresenceUpdate(presence, jid)
console.log(`[BaileysManager] Sent presence ${presence} to ${jid}`)
}
/**
* Send a reaction to a message
*/
async sendReaction(instanceId: string, jid: string, messageId: string, emoji: string): Promise<void> {
const managed = this.instances.get(instanceId)
if (!managed?.socket) {
throw new Error('Instance not connected')
}
await managed.socket.sendMessage(jid, {
react: {
text: emoji,
key: {
remoteJid: jid,
id: messageId
}
}
})
console.log(`[BaileysManager] Sent reaction ${emoji} to message ${messageId}`)
}
/**
* Update instance status in database
*/