|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { delay } = require('@whiskeysockets/baileys'); |
|
|
|
|
|
class PresenceSimulator { |
|
|
constructor(sock) { |
|
|
this.sock = sock; |
|
|
this.logger = console; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async simulateTyping(jid, durationMs = 3000) { |
|
|
try { |
|
|
|
|
|
await this.sock.sendPresenceUpdate('available', jid); |
|
|
await delay(300); |
|
|
|
|
|
|
|
|
await this.sock.sendPresenceUpdate('composing', jid); |
|
|
this.logger.log(`⌨️ [DIGITANDO] Simulando digitação por ${(durationMs / 1000).toFixed(1)}s...`); |
|
|
|
|
|
|
|
|
await delay(durationMs); |
|
|
|
|
|
|
|
|
await this.sock.sendPresenceUpdate('paused', jid); |
|
|
await delay(300); |
|
|
|
|
|
|
|
|
await this.sock.sendPresenceUpdate('available', jid); |
|
|
this.logger.log('✅ [PRONTO] Digitação simulada concluída'); |
|
|
|
|
|
return true; |
|
|
} catch (error) { |
|
|
this.logger.error('❌ Erro ao simular digitação:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async simulateRecording(jid, durationMs = 2000) { |
|
|
try { |
|
|
this.logger.log(`🎤 [GRAVANDO] Preparando áudio por ${(durationMs / 1000).toFixed(1)}s...`); |
|
|
|
|
|
|
|
|
await this.sock.sendPresenceUpdate('recording', jid); |
|
|
|
|
|
|
|
|
await delay(durationMs); |
|
|
|
|
|
|
|
|
await this.sock.sendPresenceUpdate('paused', jid); |
|
|
|
|
|
this.logger.log('✅ [PRONTO] Áudio preparado para envio'); |
|
|
|
|
|
return true; |
|
|
} catch (error) { |
|
|
this.logger.error('❌ Erro ao simular gravação:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async simulateTicks(m, wasActivated = true, isAudio = false) { |
|
|
try { |
|
|
const isGroup = String(m.key.remoteJid || '').endsWith('@g.us'); |
|
|
const jid = m.key.remoteJid; |
|
|
const participant = m.key.participant; |
|
|
const messageId = m.key.id; |
|
|
|
|
|
if (isGroup) { |
|
|
|
|
|
if (!wasActivated) { |
|
|
|
|
|
try { |
|
|
await this.sock.sendReadReceipt(jid, participant, [messageId]); |
|
|
this.logger.log('✓ [ENTREGUE] Grupo - Um tick (mensagem entregue)'); |
|
|
return true; |
|
|
} catch (err1) { |
|
|
try { |
|
|
await this.sock.sendReceipt(jid, participant, [messageId]); |
|
|
this.logger.log('✓ [ENTREGUE] Grupo - Método alternativo'); |
|
|
return true; |
|
|
} catch (err2) { |
|
|
this.logger.warn('⚠️ Não conseguiu enviar tick em grupo'); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
try { |
|
|
await this.sock.readMessages([m.key]); |
|
|
this.logger.log('✓✓ [LIDO] Grupo - Dois ticks azuis (mensagem lida)'); |
|
|
return true; |
|
|
} catch (err) { |
|
|
this.logger.warn('⚠️ Não conseguiu marcar como lido em grupo'); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
if (wasActivated || isAudio) { |
|
|
|
|
|
try { |
|
|
await this.sock.readMessages([m.key]); |
|
|
if (isAudio) { |
|
|
this.logger.log('▶️ [REPRODUZIDO] PV - Áudio marcado como reproduzido (✓✓)'); |
|
|
} else { |
|
|
this.logger.log('✓✓ [LIDO] PV - Marcado como lido (dois ticks azuis)'); |
|
|
} |
|
|
return true; |
|
|
} catch (err) { |
|
|
this.logger.warn('⚠️ Não conseguiu marcar como lido em PV'); |
|
|
return false; |
|
|
} |
|
|
} else { |
|
|
|
|
|
try { |
|
|
await this.sock.sendReadReceipt(m.key.remoteJid, m.key.participant, [messageId]); |
|
|
this.logger.log('✓ [ENTREGUE] PV - Um tick (mensagem entregue)'); |
|
|
return true; |
|
|
} catch (err) { |
|
|
this.logger.warn('⚠️ Não conseguiu enviar tick em PV'); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
this.logger.error('❌ Erro ao simular ticks:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async markAsRead(m) { |
|
|
try { |
|
|
await this.sock.readMessages([m.key]); |
|
|
this.logger.log('✓✓ [LIDO] Mensagem marcada como lida'); |
|
|
return true; |
|
|
} catch (error) { |
|
|
this.logger.warn('⚠️ Não conseguiu marcar como lido:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async simulateMessageStatus(m, wasActivated = true) { |
|
|
try { |
|
|
const isGroup = String(m.key.remoteJid || '').endsWith('@g.us'); |
|
|
|
|
|
|
|
|
if (isGroup) { |
|
|
try { |
|
|
await this.sock.sendReadReceipt(m.key.remoteJid, m.key.participant, [m.key.id]); |
|
|
this.logger.log('✓ [ENTREGUE] Grupo'); |
|
|
await delay(300); |
|
|
} catch (e) { |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (wasActivated) { |
|
|
await delay(500); |
|
|
await this.markAsRead(m); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} catch (error) { |
|
|
this.logger.error('❌ Erro ao simular status completo:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async simulateFullResponse(sock, m, responseText, isAudio = false) { |
|
|
try { |
|
|
const jid = m.key.remoteJid; |
|
|
const isGroup = String(jid || '').endsWith('@g.us'); |
|
|
|
|
|
|
|
|
if (isGroup) { |
|
|
await this.simulateTicks(m, false, false); |
|
|
await delay(300); |
|
|
} |
|
|
|
|
|
|
|
|
if (isAudio) { |
|
|
const estimatedDuration = Math.min( |
|
|
Math.max((responseText.length / 10) * 100, 2000), |
|
|
5000 |
|
|
); |
|
|
await this.simulateRecording(jid, estimatedDuration); |
|
|
} else { |
|
|
const estimatedDuration = Math.min( |
|
|
Math.max(responseText.length * 50, 2000), |
|
|
10000 |
|
|
); |
|
|
await this.simulateTyping(jid, estimatedDuration); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await delay(500); |
|
|
await this.simulateTicks(m, true, isAudio); |
|
|
|
|
|
return true; |
|
|
} catch (error) { |
|
|
this.logger.error('❌ Erro ao simular resposta completa:', error.message); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculateTypingDuration(text, minMs = 1000, maxMs = 15000) { |
|
|
const estimatedMs = Math.max(text.length * 40, minMs); |
|
|
return Math.min(estimatedMs, maxMs); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculateRecordingDuration(text, minMs = 2000, maxMs = 10000) { |
|
|
const estimatedMs = Math.max((text.length / 10) * 100, minMs); |
|
|
return Math.min(estimatedMs, maxMs); |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = PresenceSimulator; |
|
|
|