/** * GET /api/media/:instanceId/:messageId * Download and serve media for a message * * This endpoint: * 1. Checks if media is already cached locally * 2. If not, downloads from WhatsApp using Baileys * 3. Caches the file locally * 4. Streams the file to the client */ import { createReadStream } from 'fs' import { stat } from 'fs/promises' import { downloadAndCacheMedia, getCachedMediaPath } from '../../../services/media/downloader' import { sendStream } from 'h3' export default defineEventHandler(async (event) => { const username = getHeader(event, 'x-authentik-username') if (!username) { throw createError({ statusCode: 401, message: 'Unauthorized' }) } const instanceId = getRouterParam(event, 'instanceId') const messageId = getRouterParam(event, 'messageId') if (!instanceId || !messageId) { throw createError({ statusCode: 400, message: 'Missing instanceId or messageId' }) } try { // First check if already cached let cached = await getCachedMediaPath(instanceId, messageId) // If not cached, download and cache if (!cached) { console.log(`[Media API] Downloading media for: ${messageId}`) const result = await downloadAndCacheMedia(instanceId, messageId) if (!result) { throw createError({ statusCode: 404, message: 'Media not found or could not be downloaded' }) } cached = { path: result.path, mimetype: result.mimetype } } // Get file stats for Content-Length const stats = await stat(cached.path) // Set response headers setHeader(event, 'Content-Type', cached.mimetype) setHeader(event, 'Content-Length', stats.size.toString()) setHeader(event, 'Cache-Control', 'public, max-age=86400') // Cache for 24 hours // For documents, suggest download with filename const query = getQuery(event) if (query.download === 'true' || cached.mimetype.startsWith('application/')) { const filename = (query.filename as string) || `media-${messageId}` setHeader(event, 'Content-Disposition', `attachment; filename="${filename}"`) } // Stream the file const stream = createReadStream(cached.path) return sendStream(event, stream) } catch (error: any) { console.error(`[Media API] Error serving media ${messageId}:`, error) if (error.statusCode) { throw error } throw createError({ statusCode: 500, message: 'Error retrieving media' }) } })