From 02e9de031d050fe3b225f6ebf84bc31a6bc7b62d Mon Sep 17 00:00:00 2001 From: SimolZimol <70102430+SimolZimol@users.noreply.github.com> Date: Fri, 10 Oct 2025 13:36:22 +0200 Subject: [PATCH] modified: bot.py --- bot.py | 346 --------------------------------------------------------- 1 file changed, 346 deletions(-) diff --git a/bot.py b/bot.py index c5eecaf..6c15dd8 100644 --- a/bot.py +++ b/bot.py @@ -2090,350 +2090,6 @@ async def updategiveawaymessage(ctx, giveaway_id: str): logger.error(f"Error updating giveaway message: {e}") await ctx.send(f"❌ Error updating giveaway message: {str(e)}") -@client.hybrid_command() -async def endgiveaway(ctx, giveaway_id: str, force: bool = False): - """Manually end a giveaway and pick winners (Only available for admins) - - Parameters: - - giveaway_id: The giveaway ID (first 8 characters of UUID are enough) - - force: Force end even if not expired (default: False) - """ - guild_id = ctx.guild.id - user_data = load_user_data_sync(ctx.author.id, guild_id) - if user_data["permission"] < 5: - await ctx.send("You don't have permission to end giveaways.") - return - - # Find giveaway by partial ID (check both memory and database) - matching_giveaway = None - matching_id = None - source = "memory" - - # First check memory - for giv_id, giveaway in giveaways.items(): - if giv_id.startswith(giveaway_id) or giveaway_id in giv_id: - matching_giveaway = giveaway - matching_id = giv_id - break - - # If not in memory, check database - if not matching_giveaway: - active_processes = get_active_processes(process_type="giveaway", guild_id=guild_id) - - for process in active_processes: - if str(process["uuid"]).startswith(giveaway_id) or giveaway_id in str(process["uuid"]): - # Load giveaway from database - try: - guild = ctx.guild - channel = guild.get_channel(process["channel_id"]) - - if not channel: - await ctx.send(f"❌ Original channel not found for giveaway `{giveaway_id}`") - return - - # Create minimal context - class MinimalContext: - def __init__(self, channel): - self.channel = channel - self.guild = channel.guild - - temp_ctx = MinimalContext(channel) - matching_giveaway = Giveaway.from_process_data(temp_ctx, process["data"]) - matching_giveaway.end_time = process["end_time"] - matching_giveaway.process_uuid = process["uuid"] - - # Restore participants - stored_participants = process["data"].get("participants", []) - for participant_data in stored_participants: - try: - user = await client.fetch_user(participant_data["id"]) - matching_giveaway.participants.append(user) - except: - pass - - matching_id = str(process["uuid"]) - source = "database" - break - - except Exception as e: - logger.error(f"Error loading giveaway from database: {e}") - await ctx.send(f"❌ Error loading giveaway: {str(e)}") - return - - if not matching_giveaway: - await ctx.send(f"❌ No giveaway found with ID starting with `{giveaway_id}`") - return - - # Check if giveaway can be ended - is_expired = matching_giveaway.is_finished() - - if not is_expired and not force: - remaining = matching_giveaway.end_time - datetime.now() - embed = discord.Embed( - title="⚠️ Giveaway Not Expired", - description=f"This giveaway is still active and not expired yet.", - color=0xffa500, - timestamp=datetime.now() - ) - embed.add_field(name="🆔 Giveaway ID", value=f"`{matching_id[:8]}...`", inline=True) - embed.add_field(name="⏰ Time Left", value=f"", inline=True) - embed.add_field(name="🔧 Force End", value="Use `/endgiveaway True` to force end", inline=False) - - await ctx.send(embed=embed) - return - - # Check if giveaway has participants - if len(matching_giveaway.participants) == 0: - embed = discord.Embed( - title="❌ No Participants", - description=f"This giveaway has no participants, so no winners can be selected.", - color=0xff0000, - timestamp=datetime.now() - ) - embed.add_field(name="🆔 Giveaway ID", value=f"`{matching_id[:8]}...`", inline=True) - embed.add_field(name="👥 Participants", value="0", inline=True) - - # Still mark as completed - matching_giveaway.complete_giveaway() - if source == "memory" and matching_id in giveaways: - del giveaways[matching_id] - - await ctx.send(embed=embed) - return - - try: - # Pick winners - winners = matching_giveaway.pick_winners() - - if not winners: - await ctx.send(f"❌ Could not pick winners from {len(matching_giveaway.participants)} participants.") - return - - # Create winner announcement - winner_embed = discord.Embed( - title="🎉 Giveaway Ended - Winners Announced!", - description=f"**{matching_giveaway.title}** has been manually ended!", - color=0xFFD700, - timestamp=datetime.now() - ) - - # Enhanced prize display with game info - if hasattr(matching_giveaway, 'game_info') and matching_giveaway.game_info and matching_giveaway.game_info.get('name'): - if hasattr(matching_giveaway, 'game_url') and matching_giveaway.game_url: - prize_text = f"**[{matching_giveaway.game_info['name']}]({matching_giveaway.game_url})**" - else: - prize_text = f"**{matching_giveaway.game_info['name']}**" - else: - if hasattr(matching_giveaway, 'game_url') and matching_giveaway.game_url: - prize_text = f"**[{matching_giveaway.prize}]({matching_giveaway.game_url})**" - else: - prize_text = f"**{matching_giveaway.prize}**" - - winner_embed.add_field(name="🎁 Prize", value=prize_text, inline=True) - winner_embed.add_field(name="🎮 Platform", value=f"**{matching_giveaway.platform}**", inline=True) - winner_embed.add_field(name="👥 Total Participants", value=f"**{len(matching_giveaway.participants)}**", inline=True) - - # List winners - winner_list = [] - for i, winner in enumerate(winners, 1): - winner_list.append(f"🏆 **#{i}** {winner.mention}") - - winner_embed.add_field(name="🎊 Winners", value="\n".join(winner_list), inline=False) - - # Add sponsor info if available - if hasattr(matching_giveaway, 'sponsor') and matching_giveaway.sponsor: - winner_embed.add_field(name="💝 Sponsored by", value=f"**{matching_giveaway.sponsor}**", inline=False) - - # Add manual end notice - end_type = "🔧 Manually ended" if not is_expired else "⏰ Expired (manually processed)" - winner_embed.add_field(name="📋 Status", value=f"{end_type} by {ctx.author.mention}", inline=False) - - winner_embed.add_field(name="📧 Next Steps", - value="Winners have been sent a DM with prize claim instructions!", - inline=False) - - # Set game image if available - if hasattr(matching_giveaway, 'game_info') and matching_giveaway.game_info and matching_giveaway.game_info.get('image_url'): - winner_embed.set_image(url=matching_giveaway.game_info['image_url']) - winner_embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png") - else: - winner_embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png") - - winner_embed.set_footer(text="Congratulations to all winners! 🎉") - - await ctx.send(embed=winner_embed) - - # Process winners with enhanced DM - for i, winner in enumerate(winners): - try: - if i < len(matching_giveaway.winner_uuids): - winner_uuid = matching_giveaway.winner_uuids[i] - assign_winner_to_uuid(winner_uuid, winner.id) - - # Enhanced winner DM - dm_embed = discord.Embed( - title="🎉 Congratulations! You Won!", - description=f"You are a winner in the **{matching_giveaway.title}** giveaway!", - color=0xFFD700, - timestamp=datetime.now() - ) - - dm_embed.add_field(name="🎁 Prize", value=prize_text, inline=True) - dm_embed.add_field(name="🎮 Platform", value=f"**{matching_giveaway.platform}**", inline=True) - dm_embed.add_field(name="🏆 Position", value=f"Winner #{i+1}", inline=True) - - dm_embed.add_field(name="📋 Prize Claim Instructions", - value="Please contact the server administrators to claim your prize. " - "Make sure to mention this giveaway and your winner position!", - inline=False) - - if hasattr(matching_giveaway, 'sponsor') and matching_giveaway.sponsor: - dm_embed.add_field(name="💝 Sponsored by", value=f"**{matching_giveaway.sponsor}**", inline=False) - - dm_embed.set_footer(text=f"Server: {ctx.guild.name} • Giveaway ID: {matching_id[:8]}...") - - try: - await winner.send(embed=dm_embed) - logger.info(f"Sent winner DM to {winner.name} for giveaway {matching_id[:8]}") - except discord.Forbidden: - logger.warning(f"Could not send DM to winner {winner.name}") - # Notify in channel that DM failed - await ctx.send(f"⚠️ Could not send DM to {winner.mention}. Please contact them manually!") - - except Exception as e: - logger.error(f"Error processing winner {winner.name}: {e}") - - # Mark giveaway as completed and remove from memory - matching_giveaway.complete_giveaway() - if source == "memory" and matching_id in giveaways: - del giveaways[matching_id] - - logger.info(f"Manually ended giveaway {matching_id[:8]} by {ctx.author.id}, {len(winners)} winners selected") - - except Exception as e: - logger.error(f"Error ending giveaway: {e}") - await ctx.send(f"❌ Error ending giveaway: {str(e)}") - -@client.hybrid_command() -async def expiredgiveaways(ctx): - """List all expired giveaways that haven't been processed yet (Only available for admins)""" - guild_id = ctx.guild.id - user_data = load_user_data_sync(ctx.author.id, guild_id) - if user_data["permission"] < 5: - await ctx.send("You don't have permission to view expired giveaways.") - return - - expired_giveaways = [] - - # Check memory giveaways - for giv_id, giveaway in giveaways.items(): - if giveaway.guild_id == guild_id and giveaway.is_finished(): - expired_giveaways.append((giv_id, giveaway, "memory")) - - # Check database giveaways - try: - active_processes = get_active_processes(process_type="giveaway", guild_id=guild_id) - - for process in active_processes: - process_uuid = str(process["uuid"]) - - # Skip if already in memory - if process_uuid in giveaways: - continue - - # Check if expired - if process["end_time"] <= datetime.now(): - try: - # Create minimal giveaway object for display - class MinimalGiveaway: - def __init__(self, data, end_time, uuid): - self.title = data.get("title", "Unknown Giveaway") - self.prize = data.get("prize", "Unknown Prize") - self.platform = data.get("platform", "Unknown") - self.num_winners = data.get("num_winners", 1) - self.end_time = end_time - self.process_uuid = uuid - self.participants_count = len(data.get("participants", [])) - - temp_giveaway = MinimalGiveaway(process["data"], process["end_time"], process["uuid"]) - expired_giveaways.append((process_uuid, temp_giveaway, "database")) - - except Exception as e: - logger.error(f"Error processing expired giveaway {process_uuid}: {e}") - - except Exception as e: - logger.error(f"Error checking database for expired giveaways: {e}") - - if not expired_giveaways: - embed = discord.Embed( - title="✅ No Expired Giveaways", - description="There are currently no expired giveaways that need processing.", - color=0x00ff00 - ) - await ctx.send(embed=embed) - return - - # Create list embed - embed = discord.Embed( - title="⏰ Expired Giveaways", - description=f"Found **{len(expired_giveaways)}** expired giveaway(s) that need processing:", - color=0xff6b6b, - timestamp=datetime.now() - ) - - for giv_id, giveaway, source in expired_giveaways[:10]: # Limit to 10 - # Calculate how long expired - time_since_expired = datetime.now() - giveaway.end_time - days = time_since_expired.days - hours, remainder = divmod(time_since_expired.seconds, 3600) - - if days > 0: - expired_for = f"{days}d {hours}h ago" - elif hours > 0: - expired_for = f"{hours}h ago" - else: - minutes = remainder // 60 - expired_for = f"{minutes}m ago" - - # Source indicator - source_emoji = "🧠" if source == "memory" else "💾" - - # Participant count - if hasattr(giveaway, 'participants'): - participant_count = len(giveaway.participants) - else: - participant_count = getattr(giveaway, 'participants_count', 0) - - embed.add_field( - name=f"{source_emoji} {giveaway.title}", - value=( - f"**ID:** `{giv_id[:8]}...`\n" - f"**Prize:** {giveaway.prize}\n" - f"**Platform:** {giveaway.platform}\n" - f"**Winners:** {giveaway.num_winners}\n" - f"**Participants:** {participant_count}\n" - f"**Expired:** {expired_for}" - ), - inline=True - ) - - if len(expired_giveaways) > 10: - embed.add_field( - name="📋 Additional Info", - value=f"... and {len(expired_giveaways) - 10} more expired giveaways", - inline=False - ) - - embed.add_field( - name="🔧 How to Process", - value="Use `/endgiveaway ` to manually end and pick winners for any expired giveaway.", - inline=False - ) - - embed.set_footer(text="💾 = Database | 🧠 = Memory | Use /endgiveaway to process") - - await ctx.send(embed=embed) - @client.hybrid_command() async def listgiveaways(ctx): """List all active giveaways in this server (Only available for admins)""" @@ -3612,9 +3268,7 @@ async def modhelp(ctx): "`/processes [type]` - Manage active processes\n" "`/startgiveaway` - Create server giveaways with Steam/Epic integration\n" "`/editgiveaway ` - Edit active giveaways (auto-updates post)\n" - "`/endgiveaway [force]` - Manually end giveaway and pick winners\n" "`/listgiveaways` - List all active giveaways (memory + database)\n" - "`/expiredgiveaways` - Show expired giveaways that need processing\n" "`/loadgiveaway ` - Load specific giveaway from database\n" "`/loadallgiveaways` - Load all giveaways from database\n" "`/updategiveawaymessage ` - Manually refresh giveaway post\n"