Spaces:
Runtime error
Runtime error
| # cogs/drops.py | |
| import discord | |
| from discord.ext import commands | |
| import logging | |
| from services.gacha_service import GachaService | |
| from utils.cdn import get_or_create_card_url | |
| from utils.code_converter import encode_id | |
| from utils.generators.factory import generate_card_factory | |
| # ⚡ GLOBAL COOLDOWN ENGINE | |
| from utils.cooldown import check_and_apply_cooldown | |
| logger = logging.getLogger(__name__) | |
| # 👇 PASTE YOUR 5 IMGBB/DISCORD GIF URLS HERE | |
| SUMMON_ANIMATIONS = { | |
| "UR": "https://i.ibb.co/yFWSmJNG/ezgif-7031fd259bcfbd7e.gif", | |
| "SSR": "https://i.ibb.co/WppwQXWj/In-Shot-20260410-175647573.gif", | |
| "SR": "https://i.ibb.co/RMLxvMc/In-Shot-20260410-185023687.gif", | |
| "R": "https://i.ibb.co/pBYRtgjX/In-Shot-20260410-180010137.gif", | |
| "C": "https://i.ibb.co/qL9KKxRw/In-Shot-20260410-184700192.gif" | |
| } | |
| class DropsCog(commands.Cog): | |
| def __init__(self, bot): | |
| self.bot = bot | |
| async def on_message(self, message: discord.Message): | |
| if message.author.bot: | |
| return | |
| if message.content.strip().lower() == "sp": | |
| # ⚡ INJECT GLOBAL COOLDOWN & MODERATION CHECKS HERE | |
| is_admin = getattr(message.author, "guild_permissions", None) and message.author.guild_permissions.administrator | |
| if not is_admin: | |
| from database.db import db | |
| async with db.pool.acquire() as conn: | |
| is_banned = await conn.fetchval("SELECT is_banned FROM users WHERE user_id = $1", message.author.id) | |
| if is_banned: | |
| return # Silently ignore banned users so they don't know the bot is online | |
| remaining = check_and_apply_cooldown(message.author.id) | |
| if remaining > 0: | |
| await message.channel.send( | |
| f"⏳ {message.author.mention}, please wait **{remaining:.1f}s** before commanding the bot again.", | |
| delete_after=5.0 | |
| ) | |
| return | |
| try: | |
| # 1. Hit the database INSTANTLY | |
| card = await GachaService.process_drop(message.author.id) | |
| # 2. Generate a hype message and fetch the correct GIF based on rarity | |
| rarity = card['rarity'] | |
| anim_url = SUMMON_ANIMATIONS.get(rarity, SUMMON_ANIMATIONS["C"]) | |
| if rarity == "UR": | |
| hype_text = "🟥 **A MYTHIC ANOMALY DETECTED!** Reality is tearing apart..." | |
| embed_color = discord.Color.red() | |
| elif rarity == "SSR": | |
| hype_text = "🟨 **A LEGENDARY SIGNAL!** Golden light pierces the void..." | |
| embed_color = discord.Color.gold() | |
| elif rarity == "SR": | |
| hype_text = "🟪 **AN EPIC PRESENCE!** Purple energy gathers..." | |
| embed_color = discord.Color.purple() | |
| elif rarity == "R": | |
| hype_text = "🟦 **A RARE SIGNAL!** Blue sparks ignite..." | |
| embed_color = discord.Color.blue() | |
| else: | |
| hype_text = "⬜ *A common soul answers your call...*" | |
| embed_color = discord.Color.light_grey() | |
| # 3. Build the suspense embed with the dynamic GIF | |
| temp_embed = discord.Embed( | |
| title="✨ Materializing Vanguard...", | |
| description=hype_text, | |
| color=embed_color | |
| ) | |
| temp_embed.set_image(url=anim_url) | |
| # Send the animation instantly | |
| temp_msg = await message.reply(embed=temp_embed, mention_author=False) | |
| # 4. Do the heavy CPU rendering in the background | |
| card_file = await generate_card_factory( | |
| image_url=card['image_url'], | |
| char_name=card['name'], | |
| print_num=card['print_num'], | |
| rarity=card['rarity'], | |
| element=card['element'] | |
| ) | |
| card_code = encode_id(card['instance_id']) | |
| # 5. Build the final reveal | |
| final_embed = discord.Embed( | |
| title=f"🎉 {message.author.display_name} dropped {card['name']}!", | |
| color=embed_color | |
| ) | |
| final_embed.add_field(name="Rarity", value=rarity, inline=True) | |
| final_embed.add_field(name="Element", value=card['element'] or "None", inline=True) | |
| final_embed.add_field(name="Series", value=card.get('series', 'Unknown') or "Unknown", inline=True) | |
| final_embed.add_field(name="Card Code", value=f"`{card_code}`", inline=True) | |
| # Attach the finished card image | |
| final_embed.set_image(url=f"attachment://{card_file.filename}") | |
| # 6. EDIT the suspense message | |
| await temp_msg.edit(embed=final_embed, attachments=[card_file]) | |
| # 7. Backup to Discord CDN invisibly | |
| async def backup_to_cdn(): | |
| try: | |
| await get_or_create_card_url( | |
| bot=self.bot, instance_id=card['instance_id'], image_url=card['image_url'], | |
| char_name=card['name'], print_num=card['print_num'], rarity=card['rarity'], element=card['element'] | |
| ) | |
| except Exception as e: | |
| logger.error(f"Background CDN upload failed for {card['instance_id']}: {e}") | |
| self.bot.loop.create_task(backup_to_cdn()) | |
| except ValueError as e: | |
| await message.channel.send(f"{message.author.mention} {str(e)}") | |
| except Exception as e: | |
| logger.error(f"Drop System Error: {e}", exc_info=True) | |
| error_embed = discord.Embed(title="⚠️ System Error", description="An unexpected error occurred during the drop.", color=discord.Color.red()) | |
| try: | |
| await temp_msg.edit(embed=error_embed, attachments=[]) | |
| except: | |
| await message.reply(embed=error_embed, mention_author=False) | |
| async def setup(bot): | |
| await bot.add_cog(DropsCog(bot)) | |