/** * GET /api/telephony/recordings/audio?file=[&download=1] * Streams one recording from the PBX recordings service (shared secret stays * server-side) for the in-app player / download. Staff only. */ import { gateFromEvent } from '../../../utils/chatAccess' import { fetchPlayableRecording, validRecordingName } from '../../../utils/telephony/recordings' export default defineEventHandler(async (event) => { await gateFromEvent(event) const q = getQuery(event) const file = validRecordingName(q.file) if (!file) throw createError({ statusCode: 400, statusMessage: 'Invalid recording name' }) try { const { buffer, type } = await fetchPlayableRecording(file) // A .gsm source comes back transcoded to mp3 (see fetchPlayableRecording) — // give the download its real extension instead of a mislabeled .gsm file. const downloadName = type === 'audio/mpeg' && !/\.mp3$/i.test(file) ? file.replace(/\.\w+$/, '') + '.mp3' : file setHeader(event, 'Content-Type', type || 'audio/wav') setHeader(event, 'Content-Length', buffer.length) setHeader(event, 'Cache-Control', 'private, max-age=3600') setHeader(event, 'Content-Disposition', `${q.download ? 'attachment' : 'inline'}; filename="${downloadName}"`) return buffer } catch (err: any) { const code = Number(err?.statusCode || err?.response?.status) || 502 throw createError({ statusCode: code === 404 ? 404 : 502, statusMessage: code === 404 ? 'Recording not found' : 'Recordings service unavailable' }) } })