const admin = require("firebase-admin"); const serviceAccount = require("./serviceAccountKey.json"); const { googleAI } = require("@genkit-ai/googleai"); const { GEMINI_API_KEY } = require("./config/keys"); const { genkit, z } = require("genkit"); const axios = require("axios"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), storageBucket: "musicland-d33f9.firebasestorage.app", }); exports.generateAI = async ({ system = "", prompt = "", schema }) => { const genkitInstance = genkit({ plugins: [ googleAI({ apiKey: GEMINI_API_KEY, }), ], model: googleAI.model("gemini-2.5-flash"), }); if (prompt?.length < 1) { throw new Error( "Vous devez spécifier un prompt pour effectuer cette action.", ); } const { output } = await genkitInstance.generate({ system, prompt, output: { schema }, }); return output; }; // Générateur d'images via appel direct REST Imagen 3.0 (retour base64 pur) exports.generateImage = async ({ system = "", prompt = "" }) => { if (typeof prompt !== "string" || prompt.trim().length < 1) { throw new Error( "Vous devez spécifier un prompt pour effectuer cette action.", ); } const baseUrl = "https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-002:predict"; const url = `${baseUrl}?key=${encodeURIComponent(GEMINI_API_KEY)}`; const mkBody = (p) => ({ instances: [ { prompt: p, }, ], parameters: { sampleCount: 1, aspectRatio: "1:1", personGeneration: "dont_allow", }, }); const combinedPrompt = [ system, "Contraintes supplémentaires: pas de personnes, pas de visages, style abstrait, formes géométriques, textures et motifs.", prompt, ] .filter(Boolean) .join("\n\n"); const tryOnce = async (p) => { const resp = await axios.post(url, mkBody(p), { headers: { "Content-Type": "application/json" }, timeout: 120000, }); const predictions = resp?.data?.predictions || []; const first = predictions.find((x) => x?.bytesBase64Encoded); return first ? { b64: first.bytesBase64Encoded, mimeType: first.mimeType || "image/png", } : { b64: "", mimeType: null }; }; // Primary try let result = { b64: "", mimeType: null }; try { result = await tryOnce(combinedPrompt); } catch (e) { const em = e?.response?.data || e?.message || e; console.error("Imagen predict error", em); } // Fallbacks on safety filters/no predictions if (!result?.b64) { const fallback = [ "Crée une image de pochette d'album 1024x1024, abstraite, moderne et colorée.", "Utilise des formes géométriques, textures et dégradés.", "Aucune personne, aucun visage, aucun texte, aucun logo.", ].join("\n"); try { result = await tryOnce(fallback); } catch (e2) { const em2 = e2?.response?.data || e2?.message || e2; console.error("Imagen predict fallback FR error", em2); } } if (!result?.b64) { const fallbackEn = [ "Create a 1024x1024 abstract, modern, colorful album cover.", "Use geometric shapes, textures, and gradients.", "No people, no faces, no text, no logos.", ].join("\n"); try { result = await tryOnce(fallbackEn); } catch (e3) { const em3 = e3?.response?.data || e3?.message || e3; console.error("Imagen predict fallback EN error", em3); } } if (!result?.b64) { throw new Error("NO_IMAGE_OUTPUT"); } return { b64: String(result.b64).trim(), mimeType: result.mimeType || "image/png", }; }; // Exporter toutes les fonctions exports.music = require("./src/music"); exports.lyrics = require("./src/lyrics"); exports.cover = require("./src/cover");