modified: bot.py
This commit is contained in:
311
bot.py
311
bot.py
@@ -14,6 +14,8 @@ import base64
|
||||
import mysql.connector
|
||||
import mysql.connector.pooling
|
||||
import json
|
||||
import re
|
||||
import aiohttp
|
||||
import logging
|
||||
import time
|
||||
import random
|
||||
@@ -836,22 +838,123 @@ async def handle_expired_giveaway(process_uuid, data):
|
||||
# Execute giveaway ending logic
|
||||
winners = giveaway.pick_winners()
|
||||
if winners:
|
||||
winner_mentions = ", ".join([winner.mention for winner in winners])
|
||||
await giveaway.ctx.send(f"🎉 Congratulations to the winners of the giveaway '{giveaway.title}'! The winners are: {winner_mentions}")
|
||||
# Create enhanced winner announcement
|
||||
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):
|
||||
try:
|
||||
if i < len(giveaway.winner_uuids):
|
||||
winner_uuid = giveaway.winner_uuids[i]
|
||||
assign_winner_to_uuid(winner_uuid, winner.id)
|
||||
|
||||
await winner.send(f"🎁 Congratulations! You won the giveaway '{giveaway.title}'!\n"
|
||||
f"Please claim your prize using the following link: {GIVEAWAY_WEBSITE_URL}{giveaway.guild_id}/{winner_uuid}")
|
||||
# Enhanced winner DM
|
||||
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:
|
||||
logger.error(f"Error processing winner {winner.name}: {e}")
|
||||
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
|
||||
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:
|
||||
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):
|
||||
"""Verknüpft eine bereits existierende UUID mit einem tatsächlichen Gewinner"""
|
||||
connection = None
|
||||
@@ -1290,7 +1469,7 @@ def update_winner_in_db(guild_id, prize_uuid, winner_dc_id):
|
||||
close_database_connection(connection)
|
||||
|
||||
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.guild_id = ctx.guild.id # Speichern der guild_id
|
||||
self.platform = platform
|
||||
@@ -1300,6 +1479,9 @@ class Giveaway:
|
||||
self.subtitle = subtitle
|
||||
self.duration = duration
|
||||
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.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
|
||||
@@ -1323,6 +1505,9 @@ class Giveaway:
|
||||
giveaway.num_winners = data.get("num_winners", 1)
|
||||
giveaway.title = data.get("title", "Unknown Giveaway")
|
||||
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.end_time = datetime.now() # Already expired
|
||||
giveaway.participants = []
|
||||
@@ -1344,6 +1529,9 @@ class Giveaway:
|
||||
"num_winners": self.num_winners,
|
||||
"title": self.title,
|
||||
"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],
|
||||
"prize_uuid": str(self.prize_uuid),
|
||||
"game_key": self.game_key,
|
||||
@@ -1433,43 +1621,105 @@ class Giveaway:
|
||||
logger.error(f"Error completing giveaway process: {e}")
|
||||
|
||||
@client.hybrid_command()
|
||||
async def startgiveaway(ctx, platform: str, prize: str, num_winners: int, title: str, subtitle: str, duration: str):
|
||||
"""Creates a new giveaway, only available for admins."""
|
||||
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.
|
||||
|
||||
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
|
||||
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 create a giveaway.")
|
||||
return
|
||||
|
||||
# Parse duration with more formats
|
||||
if duration.endswith("m"):
|
||||
minutes = int(duration[:-1])
|
||||
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"):
|
||||
days = int(duration[:-1])
|
||||
end_time = datetime.now() + timedelta(days=days)
|
||||
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
|
||||
|
||||
# Extract game information from URL if provided
|
||||
game_info = None
|
||||
if game_url:
|
||||
game_info = await extract_game_info(game_url)
|
||||
|
||||
# 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
|
||||
giveaways[giveaway_id] = giveaway
|
||||
|
||||
# Update the process data with the actual 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.add_item(button)
|
||||
unix_end_time = int(time.mktime(end_time.timetuple()))
|
||||
|
||||
# Enhanced embed design
|
||||
embed = discord.Embed(
|
||||
title=title,
|
||||
description=f"{subtitle}\n\nPrize: {prize}\nPlatform: {platform}\nNumber of winners: {num_winners}\nEnds <t:{unix_end_time}:R>",
|
||||
color=0x00ff00
|
||||
title=f"🎉 {title}",
|
||||
description=f"✨ {subtitle}",
|
||||
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)
|
||||
|
||||
# Start the process manager if it's not already running
|
||||
@@ -1625,13 +1875,36 @@ async def on_interaction(interaction):
|
||||
|
||||
if giveaway:
|
||||
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:
|
||||
added = giveaway.add_participant(interaction.user)
|
||||
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:
|
||||
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
|
||||
|
||||
def read_introduction():
|
||||
|
||||
Reference in New Issue
Block a user