File size: 1,974 Bytes
732ca45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# utils/generators/factory.py
import io
import aiohttp
import discord
import logging
import asyncio
from database.db import db

logger = logging.getLogger(__name__)

HF_API_URL = "https://amit9011-gacha-forge.hf.space/generate"

# 🚦 THE NETWORK THROTTLE: Protects your IP from Hugging Face DDoS limits.
# Allows exactly 15 simultaneous renders. The rest wait patiently in line.
NETWORK_QUEUE = asyncio.Semaphore(15)

async def generate_card_factory(image_url: str, char_name: str, print_num: int, rarity: str, element: str) -> discord.File:
    
    async with db.pool.acquire() as conn:
        custom_frame_url = await conn.fetchval("SELECT custom_frame_url FROM characters WHERE name = $1", char_name)

    payload = {
        "image_url": image_url,
        "char_name": char_name,
        "print_num": print_num,
        "rarity": rarity,
        "element": element,
        "custom_frame_url": custom_frame_url
    }

    # Wait in line to ensure we don't trigger server firewalls
    async with NETWORK_QUEUE:
        try:
            async with aiohttp.ClientSession() as session:
                # 25 second timeout covers cold-starts and queued renders
                async with session.post(HF_API_URL, json=payload, timeout=25) as resp:
                    if resp.status != 200:
                        error_text = await resp.text()
                        logger.error(f"Cloud Forge Error [{resp.status}]: {error_text}")
                        raise ValueError("The rendering server is currently overloaded.")
                    
                    # Receive the finished WEBP bytes
                    image_bytes = await resp.read()

        except Exception as e:
            logger.error(f"Failed to reach Cloud Forge: {e}")
            raise ValueError("The rendering server is offline.")

    safe_name = char_name.replace(" ", "_").replace("-", "_").lower()
    
    return discord.File(fp=io.BytesIO(image_bytes), filename=f"{safe_name}.webp")