// utils/saveMedia.js import fs from 'fs'; import path from 'path'; import axios from 'axios'; import mime from 'mime-types'; import { decryptMedia } from '@open-wa/wa-automate'; import { GoogleGenAI } from '@google/genai'; import { config } from '../config.js'; import { log } from '../logger.js'; const BASE_DIR = '/media'; const safe = s => (s || '').replace(/[\\/:*?"<>|]/g, '_'); const ai = new GoogleGenAI({ apiKey: config.GEMINI_KEY }); function getShortId(msgId = '') { return msgId.replace(/^true_|^false_|@c\.us_/g, '').split('_')[0]; } export async function saveMedia(msg) { if (msg.type === 'chat') return null; if (!msg.clientUrl) { log('warn', `Sin clientUrl: ${msg.id}`); return null; } const ext = mime.extension(msg.mimetype || 'application/octet-stream') || 'bin'; const chatId = safe(msg.chatId); const shortId = (`${msg.timestamp}${msg.type}`).toLocaleLowerCase(); // const shortId = getShortId(msg.id); const folder = path.join(BASE_DIR, chatId, safe(msg.type)); const filePath = path.join(folder, `${shortId}.${ext}`); const fileName = shortId // solo para Files API // Buscar primero en Files API try { const existing = await ai.files.get({ name: fileName }); log('info', `πŸ“‚ ya existe en Files API: ${fileName}`); return { [msg.id]: existing }; } catch (e) { if (e.message?.includes('INVALID_ARGUMENT')) { log('error', `files.get fallΓ³ para ${fileName}: ${e.message}`); } } // Buscar en disco if (fs.existsSync(filePath)) { log('info', `πŸ“ ya existe local: ${fileName}`, 'subiendo a Files API'); const uploaded = await ai.files.upload({ file: fileName, config: { mimeType: msg.mimetype || 'application/octet-stream', name: fileName }, }); log('info', `πŸ“€ subido a Files API: ${uploaded.name}`); return { [msg.id]: uploaded }; } try { const raw = await axios.get(msg.clientUrl, { responseType: 'arraybuffer' }); msg._data = { ...msg, _raw: raw.data }; const buf = await decryptMedia(msg); fs.mkdirSync(folder, { recursive: true }); fs.writeFileSync(filePath, buf); log('info', `βœ… guardado: ${filePath}`); const uploaded = await ai.files.upload({ file: filePath, config: { mimeType: msg.mimetype || 'application/octet-stream', name: fileName }, }); log('info', `πŸ“€ subido a Files API: ${uploaded.name}`); return { [msg.id]: uploaded }; } catch (err) { if (err.response?.status === 410) { log('warn', `URL expirada (410) para ${msg.id}`); } else { log('error', `Error al guardar media ${msg.id}: ${err.message}`); } return null; } }