modified: bot.py

This commit is contained in:
SimolZimol
2025-10-09 01:27:28 +02:00
parent fc67ca2541
commit 04dd33dc03

311
bot.py
View File

@@ -14,6 +14,8 @@ import base64
import mysql.connector import mysql.connector
import mysql.connector.pooling import mysql.connector.pooling
import json import json
import re
import aiohttp
import logging import logging
import time import time
import random import random
@@ -836,22 +838,123 @@ async def handle_expired_giveaway(process_uuid, data):
# Execute giveaway ending logic # Execute giveaway ending logic
winners = giveaway.pick_winners() winners = giveaway.pick_winners()
if winners: if winners:
winner_mentions = ", ".join([winner.mention for winner in winners]) # Create enhanced winner announcement
await giveaway.ctx.send(f"🎉 Congratulations to the winners of the giveaway '{giveaway.title}'! The winners are: {winner_mentions}") winner_embed = discord.Embed(
title="🎉 Giveaway Winners Announced!",
description=f"**{giveaway.title}** has ended!",
color=0xFFD700,
timestamp=datetime.now()
)
# Enhanced prize display with game info
if hasattr(giveaway, 'game_info') and giveaway.game_info and giveaway.game_info.get('name'):
if hasattr(giveaway, 'game_url') and giveaway.game_url:
prize_text = f"**[{giveaway.game_info['name']}]({giveaway.game_url})**"
else:
prize_text = f"**{giveaway.game_info['name']}**"
else:
if hasattr(giveaway, 'game_url') and giveaway.game_url:
prize_text = f"**[{giveaway.prize}]({giveaway.game_url})**"
else:
prize_text = f"**{giveaway.prize}**"
winner_embed.add_field(name="🎁 Prize", value=prize_text, inline=True)
winner_embed.add_field(name="🎮 Platform", value=f"**{giveaway.platform}**", inline=True)
winner_embed.add_field(name="👥 Total Participants", value=f"**{len(giveaway.participants)}**", inline=True)
# List winners
winner_list = []
for i, winner in enumerate(winners, 1):
winner_list.append(f"<EFBFBD> **#{i}** {winner.mention}")
winner_embed.add_field(name="🎊 Winners", value="\n".join(winner_list), inline=False)
# Add sponsor info if available
if hasattr(giveaway, 'sponsor') and giveaway.sponsor:
winner_embed.add_field(name="💝 Sponsored by", value=f"**{giveaway.sponsor}**", 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(giveaway, 'game_info') and giveaway.game_info and giveaway.game_info.get('image_url'):
winner_embed.set_image(url=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 giveaway.ctx.send(embed=winner_embed)
# Process winners # Process winners with enhanced DM
for i, winner in enumerate(winners): for i, winner in enumerate(winners):
try: try:
if i < len(giveaway.winner_uuids): if i < len(giveaway.winner_uuids):
winner_uuid = giveaway.winner_uuids[i] winner_uuid = giveaway.winner_uuids[i]
assign_winner_to_uuid(winner_uuid, winner.id) assign_winner_to_uuid(winner_uuid, winner.id)
await winner.send(f"🎁 Congratulations! You won the giveaway '{giveaway.title}'!\n" # Enhanced winner DM
f"Please claim your prize using the following link: {GIVEAWAY_WEBSITE_URL}{giveaway.guild_id}/{winner_uuid}") dm_embed = discord.Embed(
title="<EFBFBD> Congratulations! You Won!",
description=f"You are a winner in the **{giveaway.title}** giveaway!",
color=0xFFD700,
timestamp=datetime.now()
)
# Enhanced prize display in DM
if hasattr(giveaway, 'game_info') and giveaway.game_info and giveaway.game_info.get('name'):
if hasattr(giveaway, 'game_url') and giveaway.game_url:
prize_text = f"**[{giveaway.game_info['name']}]({giveaway.game_url})**"
else:
prize_text = f"**{giveaway.game_info['name']}**"
else:
if hasattr(giveaway, 'game_url') and giveaway.game_url:
prize_text = f"**[{giveaway.prize}]({giveaway.game_url})**"
else:
prize_text = f"**{giveaway.prize}**"
dm_embed.add_field(name="🎁 Your Prize", value=prize_text, inline=True)
dm_embed.add_field(name="🎮 Platform", value=f"**{giveaway.platform}**", inline=True)
dm_embed.add_field(name="🏆 Position", value=f"**#{i+1}**", inline=True)
if hasattr(giveaway, 'sponsor') and giveaway.sponsor:
dm_embed.add_field(name="💝 Sponsored by", value=f"**{giveaway.sponsor}**", inline=False)
dm_embed.add_field(name="🔗 Claim Your Prize",
value=f"[Click here to claim your prize]({GIVEAWAY_WEBSITE_URL}{giveaway.guild_id}/{winner_uuid})",
inline=False)
dm_embed.set_footer(text=f"Server: {giveaway.ctx.guild.name}")
# Set game image in DM if available
if hasattr(giveaway, 'game_info') and giveaway.game_info and giveaway.game_info.get('image_url'):
dm_embed.set_thumbnail(url=giveaway.game_info['image_url'])
else:
dm_embed.set_thumbnail(url="https://cdn.discordapp.com/emojis/1028701098145587302.png")
await winner.send(embed=dm_embed)
except Exception as e: except Exception as e:
logger.error(f"Error processing winner {winner.name}: {e}") logger.error(f"Error processing winner {winner.name}: {e}")
else: else:
await giveaway.ctx.send(f"The giveaway '{giveaway.title}' has ended, but there were no participants.") # Enhanced "no participants" message
no_participants_embed = discord.Embed(
title="😔 Giveaway Ended",
description=f"**{giveaway.title}** has ended with no participants.",
color=0xFF6B6B,
timestamp=datetime.now()
)
no_participants_embed.add_field(name="🎁 Prize", value=f"**{giveaway.prize}**", inline=True)
no_participants_embed.add_field(name="🎮 Platform", value=f"**{giveaway.platform}**", inline=True)
if hasattr(giveaway, 'sponsor') and giveaway.sponsor:
no_participants_embed.add_field(name="💝 Sponsored by", value=f"**{giveaway.sponsor}**", inline=False)
no_participants_embed.set_footer(text="Better luck next time!")
await giveaway.ctx.send(embed=no_participants_embed)
# Clean up # Clean up
if giveaway_id in giveaways: if giveaway_id in giveaways:
@@ -1239,6 +1342,82 @@ def save_winner_to_db(guild_id, platform, name, winner_dc_id, game_key="PREDEFIN
if connection: if connection:
close_database_connection(connection) close_database_connection(connection)
async def extract_game_info(game_url: str):
"""Extract game information from various game store URLs"""
try:
# Steam URL pattern
steam_pattern = r'https?://store\.steampowered\.com/app/(\d+)'
steam_match = re.search(steam_pattern, game_url)
if steam_match:
app_id = steam_match.group(1)
return await get_steam_game_info(app_id)
# Epic Games Store URL pattern
epic_pattern = r'https?://store\.epicgames\.com/[^/]+/p/([^/?]+)'
epic_match = re.search(epic_pattern, game_url)
if epic_match:
game_slug = epic_match.group(1)
return {
'name': game_slug.replace('-', ' ').title(),
'image_url': None,
'store_url': game_url,
'platform': 'Epic Games'
}
# Generic fallback
return {
'name': None,
'image_url': None,
'store_url': game_url,
'platform': 'Unknown'
}
except Exception as e:
logger.error(f"Error extracting game info from URL {game_url}: {e}")
return None
async def get_steam_game_info(app_id: str):
"""Get game information from Steam API"""
try:
async with aiohttp.ClientSession() as session:
# Steam Store API
steam_api_url = f"https://store.steampowered.com/api/appdetails?appids={app_id}"
async with session.get(steam_api_url) as response:
if response.status == 200:
data = await response.json()
if app_id in data and data[app_id]['success']:
game_data = data[app_id]['data']
return {
'name': game_data.get('name', 'Unknown Game'),
'image_url': game_data.get('header_image'),
'store_url': f"https://store.steampowered.com/app/{app_id}",
'platform': 'Steam',
'description': game_data.get('short_description', ''),
'price': game_data.get('price_overview', {}).get('final_formatted', 'Free')
}
# Fallback if API fails
return {
'name': None,
'image_url': f"https://cdn.akamai.steamstatic.com/steam/apps/{app_id}/header.jpg",
'store_url': f"https://store.steampowered.com/app/{app_id}",
'platform': 'Steam'
}
except Exception as e:
logger.error(f"Error fetching Steam game info for app {app_id}: {e}")
return {
'name': None,
'image_url': f"https://cdn.akamai.steamstatic.com/steam/apps/{app_id}/header.jpg",
'store_url': f"https://store.steampowered.com/app/{app_id}",
'platform': 'Steam'
}
def assign_winner_to_uuid(winner_uuid, winner_dc_id): def assign_winner_to_uuid(winner_uuid, winner_dc_id):
"""Verknüpft eine bereits existierende UUID mit einem tatsächlichen Gewinner""" """Verknüpft eine bereits existierende UUID mit einem tatsächlichen Gewinner"""
connection = None connection = None
@@ -1290,7 +1469,7 @@ def update_winner_in_db(guild_id, prize_uuid, winner_dc_id):
close_database_connection(connection) close_database_connection(connection)
class Giveaway: class Giveaway:
def __init__(self, ctx, platform, prize, num_winners, title, subtitle, duration, end_time): def __init__(self, ctx, platform, prize, num_winners, title, subtitle, duration, end_time, sponsor=None, game_url=None, game_info=None):
self.ctx = ctx self.ctx = ctx
self.guild_id = ctx.guild.id # Speichern der guild_id self.guild_id = ctx.guild.id # Speichern der guild_id
self.platform = platform self.platform = platform
@@ -1300,6 +1479,9 @@ class Giveaway:
self.subtitle = subtitle self.subtitle = subtitle
self.duration = duration self.duration = duration
self.end_time = end_time self.end_time = end_time
self.sponsor = sponsor # New sponsor field
self.game_url = game_url # Game store URL
self.game_info = game_info # Extracted game information
self.participants = [] self.participants = []
self.prize_uuid = uuid.uuid4() # Generiert eine eindeutige UUID für das Gewinnspiel 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.game_key = f"PREDEFINED_GAME_KEY" # Platzhalter für den tatsächlichen Game-Key
@@ -1323,6 +1505,9 @@ class Giveaway:
giveaway.num_winners = data.get("num_winners", 1) giveaway.num_winners = data.get("num_winners", 1)
giveaway.title = data.get("title", "Unknown Giveaway") giveaway.title = data.get("title", "Unknown Giveaway")
giveaway.subtitle = data.get("subtitle", "") giveaway.subtitle = data.get("subtitle", "")
giveaway.sponsor = data.get("sponsor", None) # Restore sponsor
giveaway.game_url = data.get("game_url", None) # Restore game URL
giveaway.game_info = data.get("game_info", None) # Restore game info
giveaway.duration = "restored" giveaway.duration = "restored"
giveaway.end_time = datetime.now() # Already expired giveaway.end_time = datetime.now() # Already expired
giveaway.participants = [] giveaway.participants = []
@@ -1344,6 +1529,9 @@ class Giveaway:
"num_winners": self.num_winners, "num_winners": self.num_winners,
"title": self.title, "title": self.title,
"subtitle": self.subtitle, "subtitle": self.subtitle,
"sponsor": self.sponsor, # Include sponsor in data
"game_url": self.game_url, # Include game URL
"game_info": self.game_info, # Include game info
"winner_uuids": [str(uuid) for uuid in self.winner_uuids], "winner_uuids": [str(uuid) for uuid in self.winner_uuids],
"prize_uuid": str(self.prize_uuid), "prize_uuid": str(self.prize_uuid),
"game_key": self.game_key, "game_key": self.game_key,
@@ -1433,43 +1621,105 @@ class Giveaway:
logger.error(f"Error completing giveaway process: {e}") logger.error(f"Error completing giveaway process: {e}")
@client.hybrid_command() @client.hybrid_command()
async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: str, subtitle: str, duration: str): async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: str, subtitle: str, duration: str, sponsor: str = None, game_url: str = None):
"""Creates a new giveaway, only available for admins.""" """Creates a new giveaway, only available for admins.
Parameters:
- platform: Gaming platform (Steam, Epic, etc.)
- prize: What's being given away
- num_winners: Number of winners to select
- title: Main giveaway title
- subtitle: Additional description
- duration: Duration (e.g. 1d, 30m, 2h)
- sponsor: Optional sponsor mention/name (e.g. @SimolZimol)
- game_url: Optional game store URL (Steam, Epic, etc.) for clickable link and auto-image
"""
guild_id = ctx.guild.id guild_id = ctx.guild.id
user_data = load_user_data_sync(ctx.author.id, guild_id) user_data = load_user_data_sync(ctx.author.id, guild_id)
if user_data["permission"] < 5: if user_data["permission"] < 5:
await ctx.send("You don't have permission to create a giveaway.") await ctx.send("You don't have permission to create a giveaway.")
return return
# Parse duration with more formats
if duration.endswith("m"): if duration.endswith("m"):
minutes = int(duration[:-1]) minutes = int(duration[:-1])
end_time = datetime.now() + timedelta(minutes=minutes) end_time = datetime.now() + timedelta(minutes=minutes)
elif duration.endswith("h"):
hours = int(duration[:-1])
end_time = datetime.now() + timedelta(hours=hours)
elif duration.endswith("d"): elif duration.endswith("d"):
days = int(duration[:-1]) days = int(duration[:-1])
end_time = datetime.now() + timedelta(days=days) end_time = datetime.now() + timedelta(days=days)
else: else:
await ctx.send("Invalid duration. Please use 'm' for minutes or 'd' for days.") await ctx.send("Invalid duration. Please use 'm' for minutes, 'h' for hours, or 'd' for days (e.g. 30m, 2h, 1d).")
return return
# Extract game information from URL if provided
game_info = None
if game_url:
game_info = await extract_game_info(game_url)
# Create new giveaway # Create new giveaway
giveaway = Giveaway(ctx, platform, prize, num_winners, title, subtitle, duration, end_time) giveaway = Giveaway(ctx, platform, prize, num_winners, title, subtitle, duration, end_time, sponsor, game_url, game_info)
giveaway_id = len(giveaways) + 1 giveaway_id = len(giveaways) + 1
giveaways[giveaway_id] = giveaway giveaways[giveaway_id] = giveaway
# Update the process data with the actual giveaway ID # Update the process data with the actual giveaway ID
giveaway.update_process_data(giveaway_id) giveaway.update_process_data(giveaway_id)
button = Button(label="Participate", style=discord.ButtonStyle.green, custom_id=f"giveaway_{giveaway_id}") # Create enhanced button
button = Button(label="🎉 Join Giveaway", style=discord.ButtonStyle.green, custom_id=f"giveaway_{giveaway_id}", emoji="🎁")
view = View() view = View()
view.add_item(button) view.add_item(button)
unix_end_time = int(time.mktime(end_time.timetuple())) unix_end_time = int(time.mktime(end_time.timetuple()))
# Enhanced embed design
embed = discord.Embed( embed = discord.Embed(
title=title, title=f"🎉 {title}",
description=f"{subtitle}\n\nPrize: {prize}\nPlatform: {platform}\nNumber of winners: {num_winners}\nEnds <t:{unix_end_time}:R>", description=f"{subtitle}",
color=0x00ff00 color=0xFFD700, # Gold color for premium look
timestamp=end_time
) )
embed.set_footer(text=f"Giveaway ends at {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
# Game information with clickable link if available
if game_info and game_info.get('name'):
if game_url:
prize_text = f"**[{game_info['name']}]({game_url})**"
else:
prize_text = f"**{game_info['name']}**"
# Add additional game details if available
if game_info.get('description'):
prize_text += f"\n*{game_info['description'][:100]}{'...' if len(game_info.get('description', '')) > 100 else ''}*"
else:
# Fallback to original prize text with URL if available
if game_url:
prize_text = f"**[{prize}]({game_url})**"
else:
prize_text = f"**{prize}**"
# Main prize information
embed.add_field(name="🎁 Prize", value=prize_text, inline=True)
embed.add_field(name="🎮 Platform", value=f"**{platform}**", inline=True)
embed.add_field(name="👥 Winners", value=f"**{num_winners}**", inline=True)
# Time information
embed.add_field(name="⏰ Ends", value=f"<t:{unix_end_time}:F>\n<t:{unix_end_time}:R>", inline=False)
# Sponsor information if provided
if sponsor:
embed.add_field(name="💝 Sponsored by", value=f"**{sponsor}**", inline=False)
embed.set_footer(text=f"Giveaway ID: {giveaway_id} • Sponsored by {sponsor}")
else:
embed.set_footer(text=f"Giveaway ID: {giveaway_id} • Good luck!")
# Set game image if available, otherwise use default
if game_info and game_info.get('image_url'):
embed.set_image(url=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")
await ctx.send(embed=embed, view=view) await ctx.send(embed=embed, view=view)
# Start the process manager if it's not already running # Start the process manager if it's not already running
@@ -1625,13 +1875,36 @@ async def on_interaction(interaction):
if giveaway: if giveaway:
if giveaway.is_finished(): if giveaway.is_finished():
await interaction.response.send_message("This giveaway has already ended.", ephemeral=True) # Enhanced ended message
ended_embed = discord.Embed(
title="⏰ Giveaway Ended",
description="This giveaway has already ended. Stay tuned for future giveaways!",
color=0xFF6B6B
)
await interaction.response.send_message(embed=ended_embed, ephemeral=True)
else: else:
added = giveaway.add_participant(interaction.user) added = giveaway.add_participant(interaction.user)
if added: if added:
await interaction.response.send_message("You have successfully entered the giveaway!", ephemeral=True) # Enhanced success message
success_embed = discord.Embed(
title="🎉 Successfully Entered!",
description=f"You're now participating in **{giveaway.title}**!",
color=0x00FF00
)
success_embed.add_field(name="🎁 Prize", value=giveaway.prize, inline=True)
success_embed.add_field(name="👥 Participants", value=f"{len(giveaway.participants)}", inline=True)
success_embed.set_footer(text="Good luck! 🍀")
await interaction.response.send_message(embed=success_embed, ephemeral=True)
else: else:
await interaction.response.send_message("You're already participating in this giveaway.", ephemeral=True) # Enhanced already participating message
already_embed = discord.Embed(
title=" Already Participating",
description=f"You're already entered in **{giveaway.title}**!",
color=0xFFB347
)
already_embed.add_field(name="👥 Current Participants", value=f"{len(giveaway.participants)}", inline=True)
already_embed.set_footer(text="Good luck! 🍀")
await interaction.response.send_message(embed=already_embed, ephemeral=True)
# Slash Commands und andere Interaktionen werden automatisch vom Framework verarbeitet # Slash Commands und andere Interaktionen werden automatisch vom Framework verarbeitet
def read_introduction(): def read_introduction():