Skip to content

Instantly share code, notes, and snippets.

@igortrinidad
Created July 9, 2025 21:11
Show Gist options
  • Save igortrinidad/b6036259c285c8876551a2281649e906 to your computer and use it in GitHub Desktop.
Save igortrinidad/b6036259c285c8876551a2281649e906 to your computer and use it in GitHub Desktop.
downloadMediaMessage
import { WAMessage, downloadMediaMessage as downloadMediaSource } from '@whiskeysockets/baileys'
import { saveMediaLocally } from '#helpers/general/saveMediaLocally'
import { deepSearchKey } from '@igortrindade/lazyfy'
import mime from 'mime-types'
import logger from '@adonisjs/core/services/logger'
import { MediaDownloadResult } from './types.js'
const getMediaExtension = (message: WAMessage): { mimetype: string, extension: string } => {
const mimetype = deepSearchKey(message, 'mimetype') as string
let extension = mime.extension(mimetype)
if(extension === 'oga') {
extension = 'ogg' // Normalize OGA to OGG
}
return { mimetype, extension }
}
// Fallback method 1: Retry with delay
const downloadWithRetry = async (message: WAMessage, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
// Add delay between retries
if (i > 0) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
}
const buffer = await downloadMediaSource(message, 'buffer', {})
if (buffer && buffer.length > 0) {
return buffer
}
} catch (error) {
logger.warn({ error, retry: i + 1 }, `Download retry ${i + 1} failed`)
if (i === maxRetries - 1) {
throw error
}
}
}
throw new Error('All retry attempts failed')
}
// Fallback method 2: Extract media info and save metadata
const saveMediaMetadata = async (message: WAMessage, errorDetails: string) => {
try {
const timestamp = new Date().getTime()
const mediaInfo = {
timestamp,
messageId: message.key?.id,
participant: message.key?.participant,
remoteJid: message.key?.remoteJid,
mediaType: message.message && Object.keys(message.message)[0],
error: errorDetails,
message: message
}
const metadataPath = await saveMediaLocally(
Buffer.from(JSON.stringify(mediaInfo, null, 2)),
`${timestamp}_media_metadata.json`,
'whatsapp_manager_events/failed_media_downloads'
)
return metadataPath
} catch (error) {
logger.error({ error }, 'Failed to save media metadata')
return null
}
}
// Fallback method 3: Try to extract base64 data from message
const extractBase64Media = async (message: WAMessage): Promise<Buffer | null> => {
try {
// Check if there's base64 data in the message
const base64Data = deepSearchKey(message, 'jpegThumbnail') ||
deepSearchKey(message, 'thumbnailDirectPath') ||
deepSearchKey(message, 'mediaData')
if (base64Data && typeof base64Data === 'string') {
return Buffer.from(base64Data, 'base64')
}
return null
} catch (error) {
logger.warn({ error }, 'Failed to extract base64 media')
return null
}
}
export const downloadMediaMessage = async (message: WAMessage): Promise<MediaDownloadResult> => {
const startTime = Date.now()
let attempts = 0
let lastError: Error | null = null
try {
attempts++
// Primary method: Standard download
const buffer = await downloadMediaSource(message, 'buffer', {})
if (!buffer || buffer.length === 0) {
throw new Error('Downloaded buffer is empty or null')
}
const { mimetype, extension } = getMediaExtension(message)
const local_path = await saveMediaLocally(
buffer,
`${new Date().getTime()}_media_.${extension}`,
'whatsapp_manager_events/messages_upsert'
)
return { mimetype, extension, local_path, success: true, method: 'primary' }
} catch (primaryError) {
lastError = primaryError as Error
logger.warn({
error: primaryError,
messageId: message.key?.id,
attempt: attempts
}, 'Primary download failed, trying fallback methods')
// Fallback method 1: Try different download options
try {
attempts++
const buffer = await downloadWithRetry(message)
if (buffer && buffer.length > 0) {
const { mimetype, extension } = getMediaExtension(message)
const local_path = await saveMediaLocally(
buffer,
`${new Date().getTime()}_media_fallback1_.${extension}`,
'whatsapp_manager_events/messages_upsert'
)
return { mimetype, extension, local_path, success: true, method: 'fallback1' }
}
} catch (fallback1Error) {
lastError = fallback1Error as Error
logger.warn({
error: fallback1Error,
messageId: message.key?.id,
attempt: attempts
}, 'Fallback method 1 failed')
}
// Fallback method 2: Try to extract base64 data
try {
attempts++
const buffer = await extractBase64Media(message)
if (buffer && buffer.length > 0) {
const { mimetype, extension } = getMediaExtension(message)
const local_path = await saveMediaLocally(
buffer,
`${new Date().getTime()}_media_fallback2_.${extension}`,
'whatsapp_manager_events/messages_upsert'
)
return { mimetype, extension, local_path, success: true, method: 'fallback2_base64' }
}
} catch (fallback2Error) {
lastError = fallback2Error as Error
logger.warn({
error: fallback2Error,
messageId: message.key?.id,
attempt: attempts
}, 'Fallback method 2 failed')
}
// Last resort: Save metadata for manual recovery
logger.error({
error: lastError,
messageId: message.key?.id,
totalAttempts: attempts,
duration: Date.now() - startTime
}, 'All download methods failed, saving metadata')
const metadataPath = await saveMediaMetadata(message, lastError?.message || 'Unknown error')
return {
mimetype: null,
extension: null,
local_path: null,
success: false,
method: 'metadata_only',
metadataPath: metadataPath || undefined,
error: lastError?.message || 'Unknown error',
attempts
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment