Spaces:
Building
Building
// src/services/whatsappService.js | |
const { randomDelay, sleep } = require('../utils'); | |
const logger = require('../logger'); | |
const config = require('../config'); | |
let sockInstance = null; | |
/** | |
* Initializes the WhatsApp Service with the Baileys socket instance. | |
* Should be called once after connection is established. | |
* @param {object} sock - The Baileys socket instance. | |
*/ | |
function initialize(sock) { | |
if (!sockInstance) { | |
sockInstance = sock; | |
logger.info('WhatsApp Service Initialized.'); | |
} | |
} | |
/** | |
* Sends a presence update (typing, paused, available, unavailable). | |
* @param {'composing' | 'paused' | 'available' | 'unavailable'} status - The presence status. | |
* @param {string} jid - The target JID. | |
*/ | |
async function sendPresenceUpdate(status, jid) { | |
if (!sockInstance) return logger.error('WhatsApp Service not initialized for sendPresenceUpdate'); | |
try { | |
await sockInstance.sendPresenceUpdate(status, jid); | |
} catch (err) { | |
logger.error({ err, jid, status }, '[WhatsAppService] Failed to send presence update'); | |
} | |
} | |
/** | |
* Marks specific messages as read. | |
* @param {Array<object>} keys - An array of message key objects. | |
*/ | |
async function readReceipt(keys) { | |
if (!sockInstance) return logger.error('WhatsApp Service not initialized for readReceipt'); | |
try { | |
await sockInstance.readMessages(keys); | |
// Log the first key for brevity if needed | |
if (keys && keys[0]) { | |
logger.debug({ jid: keys[0].remoteJid, msgId: keys[0].id }, `[WhatsAppService] Marked message(s) as read`); | |
} | |
} catch (err) { | |
const jid = keys && keys[0] ? keys[0].remoteJid : 'unknown'; | |
logger.warn({ err, jid }, '[WhatsAppService] Failed to mark message(s) as read'); | |
} | |
} | |
/** | |
* Sends a message with simulated typing and random delay. | |
* @param {string} jid - The target JID. | |
* @param {object} message - The Baileys message object (e.g., { text: 'Hello' }). | |
* @param {object} [options={}] - Options object. | |
* @param {number} [options.minDelay] - Minimum delay (defaults to config.defaultMinDelay). | |
* @param {number} [options.maxDelay] - Maximum delay (defaults to config.defaultMaxDelay). | |
* @returns {Promise<object|null>} - The result from Baileys sendMessage or null on init error. | |
*/ | |
async function sendMessageWithTyping(jid, message, options = {}) { | |
if (!sockInstance) { | |
logger.error({ jid, message }, 'WhatsApp Service not initialized for sendMessage'); | |
return null; // Indicate failure | |
} | |
// Use provided delays or fall back to config defaults | |
const minDelayMs = options.minDelay ?? config.defaultMinDelay; | |
const maxDelayMs = options.maxDelay ?? config.defaultMaxDelay; | |
try { | |
await sendPresenceUpdate('composing', jid); | |
await randomDelay(minDelayMs, maxDelayMs); | |
await sendPresenceUpdate('paused', jid); // Clear composing state before sending | |
const result = await sockInstance.sendMessage(jid, message); | |
logger.debug({ jid, msgContent: message.text || '[Non-Text]' }, '[WhatsAppService] Message sent'); | |
return result; | |
} catch (err) { | |
logger.error({ err, jid, msgContent: message.text || '[Non-Text]' }, '[WhatsAppService] Failed to send message'); | |
// Re-throw error for the calling handler to potentially manage | |
// Avoid sending another message from here to prevent loops | |
throw err; | |
} | |
} | |
module.exports = { | |
initialize, | |
sendMessageWithTyping, | |
readReceipt, | |
// Only export specific actions needed by handlers | |
}; | |