| import express from "express"; |
| import fetch from "node-fetch"; |
| import { checkUserQuota, recordUserHit, enqueue } from "../lib/rateLimiter.js"; |
|
|
| const router = express.Router(); |
| const INVOKE_URL = "https://ai.api.nvidia.com/v1/genai/black-forest-labs/flux.1-dev"; |
|
|
| |
| router.post("/image", async (req, res) => { |
| try { |
| const { prompt, clientId = "anon" } = req.body; |
| if (!prompt || !prompt.trim()) { |
| return res.status(400).json({ error: "missing_prompt" }); |
| } |
|
|
| |
| const quota = checkUserQuota(clientId); |
| if (!quota.allowed) { |
| const mins = Math.ceil(quota.retryMs / 60000); |
| return res.status(429).json({ |
| error: "rate_limited", |
| message: `وصلت إلى حد 3 صور كل 3 ساعات. حاول مجدداً بعد ${mins} دقيقة.`, |
| retryMs: quota.retryMs, |
| }); |
| } |
|
|
| |
| const payload = { |
| prompt: `${prompt}, ultra realistic, highly detailed, photorealistic, 8k, sharp focus, natural lighting, professional photography`, |
| mode: "base", |
| cfg_scale: 3.5, |
| width: 1024, |
| height: 1024, |
| seed: Math.floor(Math.random() * 1_000_000), |
| steps: 50, |
| }; |
|
|
| |
| const data = await enqueue(async () => { |
| const r = await fetch(INVOKE_URL, { |
| method: "POST", |
| headers: { |
| Authorization: `Bearer ${process.env.NVIDIA_API_KEY}`, |
| Accept: "application/json", |
| "Content-Type": "application/json", |
| }, |
| body: JSON.stringify(payload), |
| }); |
| if (r.status !== 200) { |
| const errBody = await r.text(); |
| throw new Error(`NVIDIA ${r.status}: ${errBody}`); |
| } |
| return r.json(); |
| }); |
|
|
| recordUserHit(clientId); |
|
|
| |
| const b64 = |
| data?.artifacts?.[0]?.base64 || |
| data?.image || |
| data?.data?.[0]?.b64_json || |
| null; |
|
|
| if (!b64) { |
| return res.status(502).json({ error: "no_image", raw: data }); |
| } |
|
|
| res.json({ image: `data:image/png;base64,${b64}`, remaining: quota.remaining - 1 }); |
| } catch (err) { |
| console.error("image error:", err); |
| res.status(500).json({ error: "image_failed", message: String(err?.message || err) }); |
| } |
| }); |
|
|
| export default router; |
|
|