neroxbailx
Version:
baileys whatsapp-api
170 lines (150 loc) • 6.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true })
/**
* Session Error Handler untuk mengatasi error "No sessions"
* @param {Object} options - Configuration options
* @param {Function} options.logger - Logger instance
* @param {Object} options.signalRepository - Signal repository instance
* @param {Object} options.authState - Authentication state
* @param {Function} options.assertSessions - Function to assert sessions
* @param {Function} options.query - Query function
* @returns {Object} Error handler functions
*/
function makeSessionErrorHandler({ logger, signalRepository, authState, assertSessions, query }) {
/**
* Handle session errors and attempt recovery
* @param {Error} error - The error that occurred
* @param {string} jid - The JID that caused the error
* @param {Function} retryFunction - Function to retry after session recovery
* @param {number} maxRetries - Maximum number of retry attempts
* @returns {Promise<any>} Result of retry or throws error
*/
const handleSessionError = async (error, jid, retryFunction, maxRetries = 3) => {
const errorMessage = error.message || error.toString()
// Check if this is a session-related error
if (errorMessage.includes('No sessions') ||
errorMessage.includes('No session') ||
errorMessage.includes('SessionError')) {
logger.warn({ jid, error: errorMessage }, 'Session error detected, attempting recovery')
try {
// Force fetch new session for this JID
await assertSessions([jid], true)
logger.info({ jid }, 'Session recovered, retrying operation')
// Retry the original operation
return await retryFunction()
} catch (recoveryError) {
logger.error({ jid, recoveryError }, 'Failed to recover session')
// If recovery fails, try to clear and recreate session
try {
await clearAndRecreateSession(jid)
return await retryFunction()
} catch (finalError) {
logger.error({ jid, finalError }, 'Final session recovery attempt failed')
throw new Error(`Session recovery failed for ${jid}: ${finalError.message}`)
}
}
}
// If not a session error, re-throw original error
throw error
}
/**
* Clear and recreate session for a JID
* @param {string} jid - The JID to recreate session for
*/
const clearAndRecreateSession = async (jid) => {
logger.debug({ jid }, 'Clearing and recreating session')
try {
// Clear existing session
const signalId = signalRepository.jidToSignalProtocolAddress(jid)
await authState.keys.set({ 'session': { [signalId]: null } })
// Force refetch session keys
const result = await query({
tag: 'iq',
attrs: {
xmlns: 'encrypt',
type: 'get',
to: 's.whatsapp.net',
},
content: [
{
tag: 'key',
attrs: {},
content: [{
tag: 'user',
attrs: { jid },
}]
}
]
})
// Check if result has proper structure before processing
if (!result || !result.content || !Array.isArray(result.content)) {
logger.warn({ jid, result }, 'Invalid query result structure')
return
}
// Inject new session with error handling
try {
const Utils_1 = require("../Utils")
await Utils_1.parseAndInjectE2ESessions(result, signalRepository)
logger.info({ jid }, 'Session successfully recreated')
} catch (parseError) {
logger.warn({ jid, parseError }, 'Failed to parse E2E sessions, but continuing')
// Don't throw here - session might still work
}
} catch (error) {
logger.error({ jid, error }, 'Failed to recreate session')
throw error
}
}
/**
* Wrap a function with session error handling
* @param {Function} fn - Function to wrap
* @param {string} jid - JID for session context
* @returns {Function} Wrapped function
*/
const withSessionErrorHandling = (fn, jid) => {
return async (...args) => {
try {
return await fn(...args)
} catch (error) {
return await handleSessionError(error, jid, () => fn(...args))
}
}
}
/**
* Check if JID has valid session
* @param {string} jid - JID to check
* @returns {Promise<boolean>} True if session exists
*/
const hasValidSession = async (jid) => {
try {
const signalId = signalRepository.jidToSignalProtocolAddress(jid)
const sessions = await authState.keys.get('session', [signalId])
return !!sessions[signalId]
} catch (error) {
logger.debug({ jid, error }, 'Error checking session validity')
return false
}
}
/**
* Ensure session exists for JID
* @param {string} jid - JID to ensure session for
* @returns {Promise<void>}
*/
const ensureSession = async (jid) => {
const hasSession = await hasValidSession(jid)
if (!hasSession) {
logger.debug({ jid }, 'Session not found, creating new session')
await assertSessions([jid], true)
}
}
return {
handleSessionError,
clearAndRecreateSession,
withSessionErrorHandling,
hasValidSession,
ensureSession
}
}
module.exports = {
makeSessionErrorHandler
}