137 lines
3.7 KiB
JavaScript
137 lines
3.7 KiB
JavaScript
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");
|