Spaces:
Build error
Build error
| const axios = require('axios'); | |
| const crypto = require('crypto'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const { createCanvas, loadImage } = require('canvas'); | |
| const { HfInference } = require("@huggingface/inference"); | |
| require("dotenv").config() | |
| // Cache directory to store generated images | |
| const CACHE_DIR = `/home/root/code/public/image_out` | |
| if (!fs.existsSync(CACHE_DIR)) { | |
| fs.mkdirSync(CACHE_DIR); | |
| } | |
| const available_models = ["alimama-creative/FLUX.1-Turbo-Alpha", "black-forest-labs/FLUX.1-dev", "black-forest-labs/FLUX.1-schnell", "CompVis/stable-diffusion-v1-4", "Corcelio/mobius", "digiplay/AnalogMadness-realistic-model-v7", "digiplay/AsianBrmBeautyrealmix_v2.0", "digiplay/DonutHoleMix_Beta", "digiplay/KawaiiRealisticAsian_v0.7", "digiplay/m0nst3rfy3-testfix", "digiplay/m3u", "digiplay/MilkyWonderland_v1", "digiplay/Realisian_v6", "digiplay/realmixUnrealjourney_v1", "digiplay/STRANGER", "digiplay/STRANGER-ANIME", "dreamlike-art/dreamlike-diffusion-1.0", "dreamlike-art/dreamlike-photoreal-2.0", "fluently/Fluently-XL-v2", "GraydientPlatformAPI/yamers-nsfw4-xl", "John6666/3x3x3mixxl-v2-sdxl", "John6666/4th-tail-merges-050tponynai-sdxl", "John6666/4th-tail-merges-050wai70-sdxl", "John6666/big-lust-v1-sdxl", "John6666/carnival-unchained-v10-fp8-flux", "John6666/convtest", "John6666/convtest2", "John6666/dgs-4th-darkness-03ad-sdxl", "John6666/digital-af-xlp-v1-sdxl", "John6666/josei-realistic-v11-sdxl", "John6666/lyh-anime-flux-v2a1-fp8-flux", "John6666/mala-anime-mix-nsfw-pony-xl-v5-sdxl-spo", "John6666/mala-anime-mix-nsfw-pony-xl-v5new-sdxl", "John6666/mala-anime-mix-nsfw-pony-xl-v5new-sdxl-spo", "John6666/mala-smooth-v1-sdxl", "John6666/mikoshi-pony-v1-sdxl", "John6666/mklan-aio-nsfw-aio-nextgen-xlv2-sdxl", "John6666/nova-reality-v50-sdxl", "John6666/optimal-criminal-pony-v10-sdxl", "John6666/photo-realistic-pony-v5-sdxl", "John6666/pornworks-real-porn-v03-sdxl", "John6666/pornworks-real-porn-v04-sdxl", "John6666/real-mix-pony-v01-sdxl", "John6666/real-mix-pony-v2-sdxl", "John6666/reasianpony-merge-v10-sdxl", "John6666/relh-checkpoint-v30-sdxl", "John6666/sakuramoon-v10-sdxl", "John6666/sapianf-nude-men-women-for-flux-v20fp16-fp8-flux", "John6666/sorkh-pony-v1-sdxl", "John6666/speciosa-anime-v14-sdxl", "John6666/st2-bedamnrealpony-v1-sdxl", "John6666/suimix-xl-v10-sdxl", "John6666/sumeshi-flux1s-v002e-fp8-flux", "John6666/titania-juggernaut-mix-v1-sdxl", "John6666/titania-mix-realistic-pony-gbv10-sdxl", "John6666/uber-realistic-porn-merge-xl-urpmxl-v6final-sdxl", "John6666/ultimate-realistic-mix-v1-sdxl", "John6666/unlimited-porn-x-sdxl", "John6666/unlimited-porn-xreal-sdxl", "John6666/wai-ani-hentai-pony-v5-sdxl", "John6666/wai-c-v3-sdxl", "John6666/wai-doll-cn-v2-sdxl", "John6666/wai-simpleuse-for-real-pony-v1-sdxl", "Niggendar/duchaitenPonyXLNo_v35", "sd-community/sdxl-flash", "stabilityai/stable-diffusion-2-1", "stabilityai/stable-diffusion-2-base", "stabilityai/stable-diffusion-3-medium-diffusers", "stabilityai/stable-diffusion-xl-base-1.0", "stable-diffusion-v1-5/stable-diffusion-v1-5", "stablediffusionapi/disney-pixar-cartoon", "stablediffusionapi/dreamshaper-v6", "stablediffusionapi/mklan-xxx-nsfw-pony", "stablediffusionapi/newrealityxl-global-nsfw", "UnfilteredAI/NSFW-gen-v2", "Yntec/3DKX", "Yntec/BetterPonyDiffusion", "Yntec/Chip_n_DallE", "Yntec/DramaLlama", "Yntec/DreamlikeShaper", "Yntec/DreamPhotoGASM", "Yntec/DreamWorld", "Yntec/DucHaitenGODofSIMP", "Yntec/ElldrethSDaydreamMix", "Yntec/epiCPhotoGasm", "Yntec/MeinaAlter", "Yntec/MGM", "Yntec/MostClassical", "Yntec/nuipenimix2", "Yntec/Ponygraphy", "Yntec/RevAnimatedV2Rebirth", "Yntec/SCMIX_NightSkyMeina", "Yntec/TrueSight", "Yntec/WoopWoopAnime", "Yntec/YiffyMix", "Yntec/ZootVisionEpsilon"] | |
| // Hugging Face Inference API configuration | |
| const HF_API_URL = 'https://api-inference.huggingface.co/models/'; | |
| const HF_API_TOKEN = process.env.HF_API_TOKEN || ''; // Replace with your actual API token | |
| const inferenceClient = new HfInference(HF_API_TOKEN); | |
| const DEFAULT_USER_API_KEY = 'PUBLIC'; // Default API key for demonstration purposes | |
| //const DEFAULT_GUIDANCE_SCALE = 5.0; // Default guidance scale for the diffusion model | |
| const DEFAULT_WIDTH = 1024; // Default width of the generated image | |
| const DEFAULT_HEIGHT = 1024; // Default height of the generated image | |
| // In-memory store for user credits (for demonstration purposes) | |
| // In production, consider using a database | |
| const userCredits = { | |
| 'PUBLIC': 20000, | |
| 'user_api_key_1': 100, // Example API key with 10 credits | |
| 'user_api_key_2': 5 // Example API key with 5 credits | |
| }; | |
| const generateImage = async(requestPayload, res, responseFormat) => { | |
| const prompt = requestPayload.prompt; | |
| const seed = requestPayload.seed ? parseInt(requestPayload.seed) : parseInt(Math.random() * 100000); | |
| const modelId = requestPayload.model || 'black-forest-labs/FLUX.1-schnell'; | |
| const apiKey = requestPayload.api_key || DEFAULT_USER_API_KEY; | |
| const cfg_scale = requestPayload.guidance_scale ? parseFloat(requestPayload.guidance_scale) : 7.0; | |
| const steps = requestPayload.steps ? parseInt(requestPayload.steps) : 4; | |
| const width = requestPayload.width ? parseInt(requestPayload.width) : DEFAULT_WIDTH; | |
| const height = requestPayload.height ? parseInt(requestPayload.height) : DEFAULT_HEIGHT; | |
| if (!prompt) { | |
| return res.status(400).send('Error: No prompt provided'); | |
| } | |
| if (!apiKey) { | |
| return res.status(400).send('Error: No API key provided'); | |
| } | |
| // Check if the API key is valid and if the user has enough credits | |
| if (!userCredits.hasOwnProperty(apiKey)) { | |
| return res.status(403).send('Error: Invalid API key'); | |
| } | |
| if (userCredits[apiKey] <= 0) { | |
| return res.status(403).send('Error: Insufficient credits'); | |
| } | |
| // Set the seed if provided (for caching purposes, does affect HF API) | |
| const seedStr = `_${seed}` | |
| // Create a hash of the prompt, seed, and modelId to use as the cache key | |
| const cacheKey = crypto.createHash('sha256').update(`${prompt}${seedStr}_${modelId}`).digest('hex'); | |
| const cachePath = path.join(CACHE_DIR, `${cacheKey}.png`); | |
| console.log(cachePath) | |
| // Check if the image already exists in the cache | |
| if (fs.existsSync(cachePath)) { | |
| console.log("Found in cache! "+cacheKey) | |
| return res.sendFile(cachePath); | |
| } | |
| try { | |
| // Prepare payload for Hugging Face Inference API | |
| const payload = ({ | |
| "inputs": prompt, | |
| "parameters": {"width": width, "height": height}, | |
| "seed": seed | |
| //seed, | |
| //cfg_scale, | |
| //steps | |
| }); | |
| console.log("Payload: ", JSON.stringify(payload, null, 2)); | |
| console.log("Endpoint: ", `${HF_API_URL}${modelId}`); | |
| // Send request to Hugging Face Inference API to generate the image | |
| const response = await axios.post( | |
| `${HF_API_URL}${modelId}`, | |
| payload, | |
| { | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| authorization: `Bearer ${HF_API_TOKEN}` | |
| }, | |
| responseType: 'arraybuffer' | |
| } | |
| ); | |
| if (response.status !== 200) { | |
| return res.status(500).send(`Error: Failed to generate image, see response fuckup here: ${JSON.stringify(response)}`); | |
| } | |
| // Deduct one credit from the user's balance | |
| userCredits[apiKey] -= 1; | |
| // Save the image to the cache directory | |
| fs.writeFileSync(cachePath, response.data); | |
| // Send either the image directly or a link to the image | |
| if (responseFormat == "url") { | |
| res.setHeader("Content-Type", "application/json") | |
| res.json({"image_url": "https://defactofficial-mmapi.hf.space/image_out/"+ cachePath.split("/").at(-1)}) | |
| res.end() | |
| } else { | |
| res.setHeader('Content-Type', 'application/octet-stream'); | |
| res.sendFile(cachePath); | |
| res.end() | |
| } | |
| } catch (error) { | |
| res.status(500).send(`Error: Failed to generate image - ${error.message}`); | |
| } | |
| } | |
| /* | |
| app.get('/models', async(req, res) =>{ | |
| res.send(available_models) | |
| }) | |
| //for prompt-in-url: <img src="https://yourserver.com/generate/image?prompt=A%20large%20hamster&width=1024&height=1024" | |
| app.get('/generate/image', async (req, res) => { | |
| await generateImage(req.query, res) | |
| }); | |
| app.post("/generate", async(req, res)=> { | |
| await generateImage(req.body, res) | |
| }) */ | |
| module.exports = {generateImage} | |