Spaces:
Runtime error
Runtime error
| # 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") | |