diff --git a/bot.py b/bot.py index 34d354c..6c15dd8 100644 --- a/bot.py +++ b/bot.py @@ -1520,6 +1520,7 @@ class Giveaway: self.participants = [] self.prize_uuid = uuid.uuid4() # Generiert eine eindeutige UUID für das Gewinnspiel self.game_key = f"PREDEFINED_GAME_KEY" # Platzhalter für den tatsächlichen Game-Key + self.message_id = None # Store the giveaway message ID for editing # Erstelle nur die Gewinner-Einträge, KEINEN Haupt-Eintrag self.winner_uuids = create_winner_slots_in_db(self.guild_id, self.platform, self.title, self.num_winners, self.game_key) @@ -1551,6 +1552,7 @@ class Giveaway: giveaway.game_key = data.get("game_key", "PREDEFINED_GAME_KEY") giveaway.winner_uuids = data.get("winner_uuids", []) giveaway.process_uuid = None + giveaway.message_id = data.get("message_id", None) # Restore message ID return giveaway def create_process_entry(self): @@ -1597,15 +1599,139 @@ class Giveaway: logger.error(f"Error creating process entry for giveaway: {e}") def update_process_data(self, giveaway_id): - """Updates the process data with the giveaway ID (now using process UUID)""" + """Updates the process data with the giveaway ID and current data""" try: - # Since giveaway_id is now the process UUID, we don't need to update it - # This method is kept for compatibility but doesn't need to do anything - logger.info(f"Giveaway using process UUID as ID: {giveaway_id}") - pass + # Update process data with current giveaway information + giveaway_data = { + "guild_id": self.guild_id, + "channel_id": self.ctx.channel.id, + "platform": self.platform, + "prize": self.prize, + "num_winners": self.num_winners, + "title": self.title, + "subtitle": self.subtitle, + "sponsor": self.sponsor, + "sponsor_display": self.sponsor_display, + "game_url": self.game_url, + "game_info": self.game_info, + "winner_uuids": [str(uuid) for uuid in self.winner_uuids], + "prize_uuid": str(self.prize_uuid), + "game_key": self.game_key, + "message_id": self.message_id, # Include message ID + "participants": [{"id": p.id, "name": p.name} for p in self.participants] + } + + if self.process_uuid: + update_process_status(self.process_uuid, "active", data=giveaway_data) + logger.info(f"Updated process data for giveaway {giveaway_id}") except Exception as e: logger.error(f"Error updating process data: {e}") + def save_giveaway_data(self): + """Save current giveaway data to database""" + try: + giveaway_data = { + "guild_id": self.guild_id, + "channel_id": self.ctx.channel.id, + "platform": self.platform, + "prize": self.prize, + "num_winners": self.num_winners, + "title": self.title, + "subtitle": self.subtitle, + "sponsor": self.sponsor, + "sponsor_display": self.sponsor_display, + "game_url": self.game_url, + "game_info": self.game_info, + "winner_uuids": [str(uuid) for uuid in self.winner_uuids], + "prize_uuid": str(self.prize_uuid), + "game_key": self.game_key, + "message_id": self.message_id, # Include message ID + "participants": [{"id": p.id, "name": p.name} for p in self.participants] + } + + if self.process_uuid: + update_process_status(self.process_uuid, "active", data=giveaway_data) + except Exception as e: + logger.error(f"Error saving giveaway data: {e}") + + async def update_giveaway_message(self): + """Update the original giveaway message with current data""" + try: + if not self.message_id: + logger.warning("No message ID stored for giveaway, cannot update message") + return False + + # Get the channel and message + channel = self.ctx.channel + try: + message = await channel.fetch_message(self.message_id) + except discord.NotFound: + logger.warning(f"Giveaway message {self.message_id} not found") + return False + except discord.Forbidden: + logger.warning(f"No permission to access message {self.message_id}") + return False + + # Recreate the embed with updated data + unix_end_time = int(time.mktime(self.end_time.timetuple())) + + embed = discord.Embed( + title=f"🎉 {self.title}", + description=f"✨ {self.subtitle}", + color=0xFFD700, + timestamp=self.end_time + ) + + # Game information with clickable link if available + if self.game_info and self.game_info.get('name'): + if self.game_url: + prize_text = f"**[{self.game_info['name']}]({self.game_url})**" + else: + prize_text = f"**{self.game_info['name']}**" + + # Add additional game details if available + if self.game_info.get('description'): + prize_text += f"\n*{self.game_info['description'][:100]}{'...' if len(self.game_info.get('description', '')) > 100 else ''}*" + else: + # Fallback to original prize text with URL if available + if self.game_url: + prize_text = f"**[{self.prize}]({self.game_url})**" + else: + prize_text = f"**{self.prize}**" + + # Main prize information + embed.add_field(name="🎁 Prize", value=prize_text, inline=True) + embed.add_field(name="🎮 Platform", value=f"**{self.platform}**", inline=True) + embed.add_field(name="👥 Winners", value=f"**{self.num_winners}**", inline=True) + + # Time information + embed.add_field(name="⏰ Ends", value=f"\n", inline=False) + + # Sponsor information if provided + if self.sponsor: + embed.add_field(name="💝 Sponsored by", value=f"**{self.sponsor}**", inline=False) + # Use sponsor_display for footer if available, otherwise fallback to sponsor + footer_sponsor = self.sponsor_display if self.sponsor_display else self.sponsor + embed.set_footer(text=f"Giveaway ID: {str(self.process_uuid)[:8]}... • Sponsored by {footer_sponsor}") + else: + embed.set_footer(text=f"Giveaway ID: {str(self.process_uuid)[:8]}... • Good luck!") + + # Set game image if available, otherwise use default + if self.game_info and self.game_info.get('image_url'): + embed.set_image(url=self.game_info['image_url']) + embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png") + else: + embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png") + + # Update the message (keep the same view/buttons) + await message.edit(embed=embed) + logger.info(f"Updated giveaway message {self.message_id}") + return True + + except Exception as e: + logger.error(f"Error updating giveaway message: {e}") + return False + def add_participant(self, user): if user not in self.participants: self.participants.append(user) @@ -1760,7 +1886,12 @@ async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: else: embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png") - await ctx.send(embed=embed, view=view) + # Send the message and store the message ID + message = await ctx.send(embed=embed, view=view) + giveaway.message_id = message.id + + # Save the updated giveaway data including message_id + giveaway.save_giveaway_data() # Start the process manager if it's not already running if not process_manager.is_running(): @@ -1851,30 +1982,21 @@ async def editgiveaway(ctx, giveaway_id: str, field: str, *, new_value: str): except Exception as e: logger.error(f"Error updating process end_time: {e}") - # Update process data in database + # Save updated giveaway data to database try: - giveaway_data = { - "guild_id": matching_giveaway.guild_id, - "channel_id": matching_giveaway.ctx.channel.id, - "platform": matching_giveaway.platform, - "prize": matching_giveaway.prize, - "num_winners": matching_giveaway.num_winners, - "title": matching_giveaway.title, - "subtitle": matching_giveaway.subtitle, - "sponsor": matching_giveaway.sponsor, - "sponsor_display": matching_giveaway.sponsor_display, - "game_url": matching_giveaway.game_url, - "game_info": matching_giveaway.game_info, - "winner_uuids": [str(uuid) for uuid in matching_giveaway.winner_uuids], - "prize_uuid": str(matching_giveaway.prize_uuid), - "game_key": matching_giveaway.game_key, - "participants": [] - } - - update_process_status(matching_giveaway.process_uuid, "active", data=giveaway_data) + matching_giveaway.save_giveaway_data() except Exception as e: logger.error(f"Error updating process data: {e}") + # Update the giveaway message with new data + message_updated = False + try: + message_updated = await matching_giveaway.update_giveaway_message() + if not message_updated: + logger.warning(f"Could not update giveaway message for {matching_id[:8]}") + except Exception as e: + logger.error(f"Error updating giveaway message: {e}") + # Success message embed = discord.Embed( title="✅ Giveaway Updated", @@ -1894,7 +2016,13 @@ async def editgiveaway(ctx, giveaway_id: str, field: str, *, new_value: str): value=f"\n", inline=False) - embed.set_footer(text="Changes are immediately effective") + # Show message update status + if message_updated: + embed.add_field(name="📝 Message Status", value="✅ Original post updated", inline=False) + embed.set_footer(text="Changes are immediately effective • Original giveaway post updated") + else: + embed.add_field(name="📝 Message Status", value="⚠️ Could not update original post", inline=False) + embed.set_footer(text="Changes are effective • Original post may need manual update") await ctx.send(embed=embed) @@ -1904,6 +2032,64 @@ async def editgiveaway(ctx, giveaway_id: str, field: str, *, new_value: str): logger.error(f"Error editing giveaway: {e}") await ctx.send(f"❌ Error editing giveaway: {str(e)}") +@client.hybrid_command() +async def updategiveawaymessage(ctx, giveaway_id: str): + """Manually update a giveaway message (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 update giveaway messages.") + return + + # Find giveaway by partial ID + matching_giveaway = None + matching_id = None + + 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 matching_giveaway: + await ctx.send(f"❌ No active giveaway found with ID starting with `{giveaway_id}`") + return + + try: + # Try to update the message + message_updated = await matching_giveaway.update_giveaway_message() + + if message_updated: + embed = discord.Embed( + title="✅ Message Updated", + description=f"Successfully updated the giveaway message!", + color=0x00ff00, + timestamp=datetime.now() + ) + embed.add_field(name="🆔 Giveaway ID", value=f"`{matching_id[:8]}...`", inline=True) + embed.add_field(name="📝 Updated by", value=ctx.author.mention, inline=True) + embed.set_footer(text="Original giveaway post has been refreshed") + else: + embed = discord.Embed( + title="❌ Update Failed", + description=f"Could not update the giveaway message.", + color=0xff0000, + timestamp=datetime.now() + ) + embed.add_field(name="🆔 Giveaway ID", value=f"`{matching_id[:8]}...`", inline=True) + embed.add_field(name="❓ Possible Reasons", + value="• Message was deleted\n• Bot lacks permissions\n• Message ID not found", + inline=False) + embed.set_footer(text="Check logs for more details") + + await ctx.send(embed=embed) + + logger.info(f"Manual message update attempted for giveaway {matching_id[:8]} by {ctx.author.id}: {message_updated}") + + except Exception as e: + logger.error(f"Error updating giveaway message: {e}") + await ctx.send(f"❌ Error updating giveaway message: {str(e)}") + @client.hybrid_command() async def listgiveaways(ctx): """List all active giveaways in this server (Only available for admins)""" @@ -3080,7 +3266,12 @@ async def modhelp(ctx): "`/restorewarn ` - Reactivate a warning (Level 6+)\n" "`/modstats [user]` - View moderation statistics\n" "`/processes [type]` - Manage active processes\n" - "`/startgiveaway` - Create server giveaways\n" + "`/startgiveaway` - Create server giveaways with Steam/Epic integration\n" + "`/editgiveaway ` - Edit active giveaways (auto-updates post)\n" + "`/listgiveaways` - List all active giveaways (memory + database)\n" + "`/loadgiveaway ` - Load specific giveaway from database\n" + "`/loadallgiveaways` - Load all giveaways from database\n" + "`/updategiveawaymessage ` - Manually refresh giveaway post\n" "`/join` - Make bot join a server\n" "`/leave` - Make bot leave a server" ),