nettoyage et standardisation
This commit is contained in:
parent
4533180ef0
commit
1b02dd8b22
16 changed files with 286 additions and 250 deletions
20
bot.py
20
bot.py
|
|
@ -1,18 +1,24 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import os
|
import os
|
||||||
import asyncio
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import DISCORD_TOKEN
|
from config import DISCORD_TOKEN
|
||||||
|
|
||||||
|
# Import des managers
|
||||||
from utils.DatabaseManager_class import DatabaseManager
|
from utils.DatabaseManager_class import DatabaseManager
|
||||||
from utils.ScreenshotManager_class import ScreenshotManager
|
from utils.ScreenshotManager_class import ScreenshotManager
|
||||||
|
|
||||||
|
# Définir les intents
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
|
|
||||||
bot = commands.Bot(command_prefix="!", intents=intents)
|
bot = commands.Bot(command_prefix="!", intents=intents)
|
||||||
|
|
||||||
|
# Initialisation unique des managers
|
||||||
db_manager = DatabaseManager()
|
db_manager = DatabaseManager()
|
||||||
screenshot_manager = ScreenshotManager()
|
screenshot_manager = ScreenshotManager()
|
||||||
|
|
||||||
|
# Liste des Cogs à charger
|
||||||
initial_cogs = [
|
initial_cogs = [
|
||||||
"cogs.guide",
|
"cogs.guide",
|
||||||
"cogs.pbhydra",
|
"cogs.pbhydra",
|
||||||
|
|
@ -23,7 +29,7 @@ initial_cogs = [
|
||||||
"cogs.mercy",
|
"cogs.mercy",
|
||||||
]
|
]
|
||||||
|
|
||||||
async def load_all_cogs():
|
async def load_cogs():
|
||||||
for cog in initial_cogs:
|
for cog in initial_cogs:
|
||||||
try:
|
try:
|
||||||
await bot.load_extension(cog)
|
await bot.load_extension(cog)
|
||||||
|
|
@ -35,10 +41,8 @@ async def load_all_cogs():
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"{bot.user.name} est connecté !")
|
print(f"{bot.user.name} est connecté !")
|
||||||
|
|
||||||
async def main():
|
# Charger les cogs avant le run
|
||||||
await load_all_cogs()
|
bot.loop.create_task(load_cogs())
|
||||||
await bot.start(DISCORD_TOKEN)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(main())
|
|
||||||
|
|
||||||
|
# Lancer le bot
|
||||||
|
bot.run(DISCORD_TOKEN)
|
||||||
|
|
|
||||||
|
|
@ -1,114 +1,118 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID
|
from config import AUTHORIZED_CHANNEL_ID
|
||||||
|
|
||||||
class Guide(commands.Cog):
|
class Guide(commands.Cog):
|
||||||
|
"""Affiche la liste des commandes disponibles"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@commands.command(name="guide")
|
@commands.command(name="guide")
|
||||||
async def guide(self, ctx):
|
async def guide(self, ctx):
|
||||||
"""Affiche la liste des commandes disponibles avec les nouvelles difficultés"""
|
"""Affiche toutes les commandes disponibles avec les difficultés"""
|
||||||
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
||||||
return
|
return
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title="🤖 RTF Bot - Commands Guide",
|
title="🧐 RTF Bot - Commands Guide",
|
||||||
description="Here are all available commands for tracking your Personal Bests!",
|
description="Here are all available commands for tracking your Personal Bests!",
|
||||||
color=0x00bfff
|
color=0x00bfff
|
||||||
)
|
)
|
||||||
|
|
||||||
# Info sur les formats de dégâts
|
# Info sur les formats de dégâts
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="💰 Damage Formats",
|
name="💠 Damage Formats",
|
||||||
value="**Accepted formats:** `1500000`, `1.5M`, `500K`, `2B`\n" +
|
value="**Accepted formats:** `1500000`, `1.5M`, `500K`, `2B`\n"
|
||||||
"**Suffixes:** K = thousands, M = millions, B = billions\n" +
|
"**Suffixes:** K = thousands, M = millions, B = billions\n"
|
||||||
"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare",
|
"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commandes PB Hydra
|
# Commandes PB Hydra
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="ðŸ Hydra Commands",
|
name="🐍 Hydra Commands",
|
||||||
value="**Difficulties:** Normal | Hard | Brutal | Nightmare (nm)\n" +
|
value="**Difficulties:** Normal | Hard | Brutal | Nightmare (nm)\n"
|
||||||
"`!pbhydra <difficulty> <damage>` - Submit PB + screenshot\n" +
|
"`!pbhydra <difficulty> <damage>` - Submit PB + screenshot\n"
|
||||||
"`!pbhydra <difficulty>` - Show your PB\n" +
|
"`!pbhydra <difficulty>` - Show your PB\n"
|
||||||
"`!pbhydra <difficulty> <user>` - Show user's PB",
|
"`!pbhydra <difficulty> <user>` - Show user's PB",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commandes PB Chimera
|
# Commandes PB Chimera
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="🦠Chimera Commands",
|
name="🦁 Chimera Commands",
|
||||||
value="**Difficulties:** Easy | Normal | Hard | Brutal | Nightmare (nm) | Ultra (unm)\n" +
|
value="**Difficulties:** Easy | Normal | Hard | Brutal | Nightmare (nm) | Ultra (unm)\n"
|
||||||
"`!pbchimera <difficulty> <damage>` - Submit PB + screenshot\n" +
|
"`!pbchimera <difficulty> <damage>` - Submit PB + screenshot\n"
|
||||||
"`!pbchimera <difficulty>` - Show your PB\n" +
|
"`!pbchimera <difficulty>` - Show your PB\n"
|
||||||
"`!pbchimera <difficulty> <user>` - Show user's PB",
|
"`!pbchimera <difficulty> <user>` - Show user's PB",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commandes PB CvC
|
# Commandes PB CvC
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="âš”ï¸ CvC Commands",
|
name="⚔️ CvC Commands",
|
||||||
value="`!pbcvc <damage>` - Submit PB + screenshot\n" +
|
value="`!pbcvc <damage>` - Submit PB + screenshot\n"
|
||||||
"`!pbcvc` - Show your PB\n" +
|
"`!pbcvc` - Show your PB\n"
|
||||||
"`!pbcvc <username>` - Show user's PB",
|
"`!pbcvc <username>` - Show user's PB",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Commandes Mercy
|
# Commandes Mercy
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="🎲 Mercy Commands",
|
name="🎲 Mercy Commands",
|
||||||
value="`!mercy show` - Show your current mercy pulls\n" +
|
value="`!mercy show` - Show your current mercy pulls\n"
|
||||||
"`!mercy add <nb> <type>` - Add pulls to a shard type\n" +
|
"`!mercy add <nb> <type>` - Add pulls to a shard type\n"
|
||||||
"`!mercy reset <type>` - Reset pulls for a shard type\n" +
|
"`!mercy reset <type>` - Reset pulls for a shard type\n"
|
||||||
"**Available types:** ancient, void, sacred, primal_legendary, primal_mythical, remnant",
|
"**Available types:** ancient, void, sacred, primal, remnant",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Classements globaux
|
# Classements globaux
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="🌠Global Leaderboards",
|
name="🌍 Global Leaderboards",
|
||||||
value="`!top10hydra <difficulty>` - Global Hydra rankings\n" +
|
value="`!top10hydra <difficulty>` - Global Hydra rankings\n"
|
||||||
"`!top10chimera <difficulty>` - Global Chimera rankings\n" +
|
"`!top10chimera <difficulty>` - Global Chimera rankings\n"
|
||||||
"`!top10cvc` - Global CvC rankings",
|
"`!top10cvc` - Global CvC rankings",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Classements par clan
|
# Classements par clan
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="ðŸ›ï¸ Clan Leaderboards",
|
name="🏆 Clan Leaderboards",
|
||||||
value="**RTF:** `!rtfhydra <diff>` `!rtfchimera <diff>` `!rtfcvc`\n" +
|
value="**RTF:** `!rtfhydra <diff>` `!rtfchimera <diff>` `!rtfcvc`\n"
|
||||||
"**RTFC:** `!rtfchydra <diff>` `!rtfcchimera <diff>` `!rtfccvc`\n" +
|
"**RTFC:** `!rtfchydra <diff>` `!rtfcchimera <diff>` `!rtfccvc`\n"
|
||||||
"**RTFR:** `!rtfrhydra <diff>` `!rtfrchimera <diff>` `!rtfrcvc`",
|
"**RTFR:** `!rtfrhydra <diff>` `!rtfrchimera <diff>` `!rtfrcvc`",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Stats et aide
|
# Stats et aide
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="📈 Stats & Info",
|
name="📈 Stats & Info",
|
||||||
value="`!mystats` - View all your PBs\n" +
|
value="`!mystats` - View all your PBs\n"
|
||||||
"`!mystats <username>` - View someone's PBs\n" +
|
"`!mystats <username>` - View someone's PBs\n"
|
||||||
"`!guide` - Show this help message",
|
"`!guide` - Show this help message",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name="💡 Examples",
|
name="⚡ Examples",
|
||||||
value="`!pbhydra brutal 1.5M` - Submit Brutal Hydra PB\n" +
|
value="`!pbhydra brutal 1.5M` - Submit Brutal Hydra PB\n"
|
||||||
"`!pbchimera unm 500K` - Submit Ultra Nightmare PB\n" +
|
"`!pbchimera unm 500K` - Submit Ultra Nightmare PB\n"
|
||||||
"`!pbcvc 2.3M` - Submit CvC PB\n" +
|
"`!pbcvc 2.3M` - Submit CvC PB\n"
|
||||||
"`!mercy add 50 ancient` - Add 50 pulls to Ancient shard\n" +
|
"`!mercy add 50 primal` - Add 50 pulls to Primal shard\n"
|
||||||
"`!mercy show` - Show your mercy pulls\n" +
|
"`!mercy show` - Show your mercy pulls\n"
|
||||||
"`!rtfhydra nm` - RTF clan Nightmare rankings\n" +
|
"`!rtfhydra nm` - RTF clan Nightmare rankings\n"
|
||||||
"**Always attach screenshot when submitting PBs!**",
|
"**Always attach screenshot when submitting PBs!**",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
embed.set_footer(text="🎮 Old screenshots are automatically deleted when you set new PBs!")
|
embed.set_footer(text="🎮 Old screenshots are automatically deleted when you set new PBs!")
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(Guide(bot))
|
await bot.add_cog(Guide(bot))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID
|
from config import AUTHORIZED_CHANNEL_ID
|
||||||
|
|
@ -7,6 +8,8 @@ from utils.helpers import calc_chance_and_guarantee
|
||||||
VALID_SHARDS = ["ancient", "void", "sacred", "primal", "remnant"]
|
VALID_SHARDS = ["ancient", "void", "sacred", "primal", "remnant"]
|
||||||
|
|
||||||
class Mercy(commands.Cog):
|
class Mercy(commands.Cog):
|
||||||
|
"""Cog pour gérer les pulls de Mercy"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.mercy_manager = MercyManager()
|
self.mercy_manager = MercyManager()
|
||||||
|
|
@ -18,61 +21,96 @@ class Mercy(commands.Cog):
|
||||||
|
|
||||||
user_id = str(ctx.author.id)
|
user_id = str(ctx.author.id)
|
||||||
|
|
||||||
|
# ----- SHOW -----
|
||||||
if action == "show":
|
if action == "show":
|
||||||
pulls_dict = self.mercy_manager.get_all_pulls(user_id)
|
pulls_dict = self.mercy_manager.get_all_pulls(user_id)
|
||||||
if not pulls_dict:
|
if not pulls_dict:
|
||||||
await ctx.send("⌠You don't have any mercy data yet.")
|
await ctx.send("ℹ️ You don't have any mercy data yet.")
|
||||||
return
|
return
|
||||||
|
|
||||||
embed = discord.Embed(title=f"🎲 Mercy Status for {ctx.author.display_name}", color=0x00bfff)
|
embed = discord.Embed(
|
||||||
|
title=f"🎲 Mercy Status for {ctx.author.display_name}",
|
||||||
|
color=0x00bfff
|
||||||
|
)
|
||||||
|
|
||||||
for shard_type, pulls in pulls_dict.items():
|
for shard_type, pulls in pulls_dict.items():
|
||||||
if shard_type == "primal":
|
if shard_type == "primal":
|
||||||
for sub_type in ["primal_legendary", "primal_mythical"]:
|
for sub_type in ["primal_legendary", "primal_mythical"]:
|
||||||
chance, guaranteed_at = self.calc_chance_and_guarantee(sub_type, pulls)
|
sub_pulls = pulls_dict.get(sub_type, 0)
|
||||||
guaranteed_text = f" (Guaranteed at {int(guaranteed_at)} pulls)" if guaranteed_at else ""
|
chance, guaranteed_at, remaining = calc_chance_and_guarantee(sub_type, sub_pulls)
|
||||||
|
guaranteed_text = f" (Guaranteed at {guaranteed_at} pulls, {remaining} remaining)" if guaranteed_at else ""
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name=sub_type.replace("_", " ").title(),
|
name=sub_type.replace("_", " ").title(),
|
||||||
value=f"Pulled: **{pulls} shards** → {chance:.1f}% chance{guaranteed_text}",
|
value=f"Pulled: **{sub_pulls}/{guaranteed_at} shards** → {chance:.1f}% chance{guaranteed_text}",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
chance, guaranteed_at = self.calc_chance_and_guarantee(shard_type, pulls)
|
chance, guaranteed_at, remaining = calc_chance_and_guarantee(shard_type, pulls)
|
||||||
guaranteed_text = f" (Guaranteed at {int(guaranteed_at)} pulls)" if guaranteed_at else ""
|
guaranteed_text = f" (Guaranteed at {guaranteed_at} pulls, {remaining} remaining)" if guaranteed_at else ""
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
name=shard_type.replace("_", " ").title(),
|
name=shard_type.replace("_", " ").title(),
|
||||||
value=f"Pulled: **{pulls} shards** → {chance:.1f}% chance{guaranteed_text}",
|
value=f"Pulled: **{pulls}/{guaranteed_at} shards** → {chance:.1f}% chance{guaranteed_text}",
|
||||||
inline=False
|
inline=False
|
||||||
)
|
)
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
# ----- ADD -----
|
||||||
elif action == "add" and arg1 and arg2:
|
elif action == "add" and arg1 and arg2:
|
||||||
try:
|
try:
|
||||||
pulls_to_add = int(arg1)
|
pulls_to_add = int(arg1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
await ctx.send("⌠Number of pulls must be an integer.")
|
await ctx.send("❌ Number of pulls must be an integer.")
|
||||||
return
|
return
|
||||||
|
|
||||||
shard_type = arg2.lower()
|
shard_type = arg2.lower()
|
||||||
if shard_type not in VALID_SHARDS:
|
if shard_type not in VALID_SHARDS:
|
||||||
await ctx.send(f"⌠Invalid shard type. Available: {', '.join(VALID_SHARDS)}")
|
await ctx.send(f"❌ Invalid shard type. Available: {', '.join(VALID_SHARDS)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
new_pulls = self.mercy_manager.add_pulls(user_id, shard_type, pulls_to_add)
|
if shard_type == "primal":
|
||||||
await ctx.send(f"✅ Added {pulls_to_add} pulls to **{shard_type}** mercy. Total: {new_pulls}")
|
messages = []
|
||||||
|
for sub_type in ["primal_legendary", "primal_mythical"]:
|
||||||
|
new_pulls = self.mercy_manager.add_pulls(user_id, sub_type, pulls_to_add)
|
||||||
|
chance, guaranteed_at, remaining = calc_chance_and_guarantee(sub_type, new_pulls)
|
||||||
|
messages.append(f"✅ Added {pulls_to_add} pulls to **{sub_type.replace('_', ' ').title()}**: {new_pulls}/{guaranteed_at} → {chance:.1f}% ({remaining} remaining)")
|
||||||
|
await ctx.send("\n".join(messages))
|
||||||
|
else:
|
||||||
|
new_pulls = self.mercy_manager.add_pulls(user_id, shard_type, pulls_to_add)
|
||||||
|
chance, guaranteed_at, remaining = calc_chance_and_guarantee(shard_type, new_pulls)
|
||||||
|
await ctx.send(f"✅ Added {pulls_to_add} pulls to **{shard_type}** mercy. Now: **{new_pulls}/{guaranteed_at}** pulls → {chance:.1f}% chance ({remaining} remaining)")
|
||||||
|
|
||||||
|
# ----- RESET -----
|
||||||
elif action == "reset" and arg1:
|
elif action == "reset" and arg1:
|
||||||
shard_type = arg1.lower()
|
shard_type = arg1.lower()
|
||||||
if shard_type not in VALID_SHARDS:
|
sub_type = arg2.lower() if arg2 else None
|
||||||
await ctx.send(f"⌠Invalid shard type. Available: {', '.join(VALID_SHARDS)}")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.mercy_manager.reset_pulls(user_id, shard_type)
|
if shard_type == "primal":
|
||||||
await ctx.send(f"🔄 Mercy for **{shard_type}** has been reset.")
|
if sub_type == "legendary":
|
||||||
|
self.mercy_manager.reset_pulls(user_id, "primal_legendary")
|
||||||
|
await ctx.send("🧾 Mercy for Primal Legendary has been reset.")
|
||||||
|
elif sub_type == "mythical":
|
||||||
|
self.mercy_manager.reset_pulls(user_id, "primal_mythical")
|
||||||
|
await ctx.send("🧾 Mercy for Primal Mythical has been reset.")
|
||||||
|
elif sub_type is None:
|
||||||
|
messages = []
|
||||||
|
for s in ["primal_legendary", "primal_mythical"]:
|
||||||
|
self.mercy_manager.reset_pulls(user_id, s)
|
||||||
|
messages.append(f"🧾 Mercy for {s.replace('_', ' ').title()} has been reset.")
|
||||||
|
await ctx.send("\n".join(messages))
|
||||||
|
else:
|
||||||
|
await ctx.send("❌ Invalid primal subtype. Use `legendary` or `mythical`.")
|
||||||
|
else:
|
||||||
|
if shard_type not in VALID_SHARDS:
|
||||||
|
await ctx.send(f"❌ Invalid shard type. Available: {', '.join(VALID_SHARDS)}")
|
||||||
|
return
|
||||||
|
self.mercy_manager.reset_pulls(user_id, shard_type)
|
||||||
|
await ctx.send(f"🧾 Mercy for **{shard_type}** has been reset.")
|
||||||
|
|
||||||
|
# ----- HELP -----
|
||||||
else:
|
else:
|
||||||
await ctx.send("⌠Usage: `!mercy add <nb> <type>`, `!mercy reset <type>`, `!mercy show`")
|
await ctx.send("ℹ️ Usage: `!mercy add <nb> <type>`, `!mercy reset <type> [subtype]`, `!mercy show`")
|
||||||
|
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(Mercy(bot))
|
await bot.add_cog(Mercy(bot))
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID, BOSS_CONFIG
|
from config import AUTHORIZED_CHANNEL_ID, BOSS_CONFIG
|
||||||
from utils.helpers import format_damage_display, format_date_only
|
from utils.helpers import format_damage_display, format_date_only
|
||||||
from utils.pb_handler import db_manager # ou set_db_manager si nécessaire
|
from utils.pb_handler import db_manager # Assurez-vous que db_manager est initialisé correctement
|
||||||
|
|
||||||
class MyStats(commands.Cog):
|
class MyStats(commands.Cog):
|
||||||
|
"""Cog pour afficher tous les PB d'un utilisateur"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@commands.command(name="mystats")
|
@commands.command(name="mystats")
|
||||||
async def mystats(self, ctx, target_user: str = None):
|
async def mystats(self, ctx, target_user: str = None):
|
||||||
"""Affiche tous les PB d'un utilisateur avec les nouvelles difficultés"""
|
"""Affiche tous les PB d'un utilisateur avec les nouvelles difficultés"""
|
||||||
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -19,15 +22,15 @@ class MyStats(commands.Cog):
|
||||||
user_data = db_manager.get_user_all_pbs(username)
|
user_data = db_manager.get_user_all_pbs(username)
|
||||||
|
|
||||||
if not user_data:
|
if not user_data:
|
||||||
await ctx.send(f"⌠No data found for **{username}**.")
|
await ctx.send(f"❌ No data found for **{username}**.")
|
||||||
return
|
return
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"📊 {username}'s Complete Stats",
|
title=f"📊 {username}'s Complete Stats",
|
||||||
color=0x00bfff
|
color=0x00bfff
|
||||||
)
|
)
|
||||||
|
|
||||||
# Hydra - toutes les difficultés
|
# Hydra - toutes les difficultés
|
||||||
hydra_stats = []
|
hydra_stats = []
|
||||||
for difficulty in BOSS_CONFIG['hydra']['difficulties']:
|
for difficulty in BOSS_CONFIG['hydra']['difficulties']:
|
||||||
pb_key = f'pb_hydra_{difficulty}'
|
pb_key = f'pb_hydra_{difficulty}'
|
||||||
|
|
@ -36,13 +39,13 @@ class MyStats(commands.Cog):
|
||||||
if pb_key in user_data and user_data[pb_key] > 0:
|
if pb_key in user_data and user_data[pb_key] > 0:
|
||||||
pb_value = user_data[pb_key]
|
pb_value = user_data[pb_key]
|
||||||
pb_date = user_data.get(date_key)
|
pb_date = user_data.get(date_key)
|
||||||
date_text = f" • {format_date_only(pb_date)}" if pb_date else ""
|
date_text = f" • {format_date_only(pb_date)}" if pb_date else ""
|
||||||
hydra_stats.append(f"**{difficulty.title()}:** {format_damage_display(pb_value)}{date_text}")
|
hydra_stats.append(f"**{difficulty.title()}:** {format_damage_display(pb_value)}{date_text}")
|
||||||
|
|
||||||
hydra_text = "\n".join(hydra_stats) if hydra_stats else "No records"
|
hydra_text = "\n".join(hydra_stats) if hydra_stats else "No records"
|
||||||
embed.add_field(name="ðŸ Hydra PBs", value=hydra_text, inline=False)
|
embed.add_field(name="🗡️ Hydra PBs", value=hydra_text, inline=False)
|
||||||
|
|
||||||
# Chimera - toutes les difficultés
|
# Chimera - toutes les difficultés
|
||||||
chimera_stats = []
|
chimera_stats = []
|
||||||
for difficulty in BOSS_CONFIG['chimera']['difficulties']:
|
for difficulty in BOSS_CONFIG['chimera']['difficulties']:
|
||||||
pb_key = f'pb_chimera_{difficulty}'
|
pb_key = f'pb_chimera_{difficulty}'
|
||||||
|
|
@ -51,12 +54,12 @@ class MyStats(commands.Cog):
|
||||||
if pb_key in user_data and user_data[pb_key] > 0:
|
if pb_key in user_data and user_data[pb_key] > 0:
|
||||||
pb_value = user_data[pb_key]
|
pb_value = user_data[pb_key]
|
||||||
pb_date = user_data.get(date_key)
|
pb_date = user_data.get(date_key)
|
||||||
date_text = f" • {format_date_only(pb_date)}" if pb_date else ""
|
date_text = f" • {format_date_only(pb_date)}" if pb_date else ""
|
||||||
display_name = "Ultra Nightmare" if difficulty == "ultra" else difficulty.title()
|
display_name = "Ultra Nightmare" if difficulty == "ultra" else difficulty.title()
|
||||||
chimera_stats.append(f"**{display_name}:** {format_damage_display(pb_value)}{date_text}")
|
chimera_stats.append(f"**{display_name}:** {format_damage_display(pb_value)}{date_text}")
|
||||||
|
|
||||||
chimera_text = "\n".join(chimera_stats) if chimera_stats else "No records"
|
chimera_text = "\n".join(chimera_stats) if chimera_stats else "No records"
|
||||||
embed.add_field(name="🦠Chimera PBs", value=chimera_text, inline=False)
|
embed.add_field(name="🛡️ Chimera PBs", value=chimera_text, inline=False)
|
||||||
|
|
||||||
# CvC
|
# CvC
|
||||||
cvc_pb = user_data.get('pb_cvc', 0)
|
cvc_pb = user_data.get('pb_cvc', 0)
|
||||||
|
|
@ -65,25 +68,19 @@ class MyStats(commands.Cog):
|
||||||
if cvc_pb > 0 and cvc_date:
|
if cvc_pb > 0 and cvc_date:
|
||||||
formatted_date = format_date_only(cvc_date)
|
formatted_date = format_date_only(cvc_date)
|
||||||
if formatted_date:
|
if formatted_date:
|
||||||
cvc_text += f" • {formatted_date}"
|
cvc_text += f" • {formatted_date}"
|
||||||
embed.add_field(name="âš”ï¸ CvC PB", value=cvc_text, inline=False)
|
embed.add_field(name="⚔️ CvC PB", value=cvc_text, inline=False)
|
||||||
|
|
||||||
# Total combiné
|
# Total combiné
|
||||||
total_damage = 0
|
total_damage = sum(user_data.get(f'pb_hydra_{d}', 0) for d in BOSS_CONFIG['hydra']['difficulties'])
|
||||||
for difficulty in BOSS_CONFIG['hydra']['difficulties']:
|
total_damage += sum(user_data.get(f'pb_chimera_{d}', 0) for d in BOSS_CONFIG['chimera']['difficulties'])
|
||||||
total_damage += user_data.get(f'pb_hydra_{difficulty}', 0)
|
|
||||||
for difficulty in BOSS_CONFIG['chimera']['difficulties']:
|
|
||||||
total_damage += user_data.get(f'pb_chimera_{difficulty}', 0)
|
|
||||||
total_damage += user_data.get('pb_cvc', 0)
|
total_damage += user_data.get('pb_cvc', 0)
|
||||||
|
embed.add_field(name="💯 Total Combined Damage", value=f"**{format_damage_display(total_damage)}**", inline=False)
|
||||||
embed.add_field(name="💯 Total Combined Damage", value=f"**{format_damage_display(total_damage)}**", inline=False)
|
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"⌠Error: {e}")
|
await ctx.send(f"❌ Error: {e}")
|
||||||
|
|
||||||
|
|
||||||
# Pour charger le Cog
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(MyStats(bot))
|
await bot.add_cog(MyStats(bot))
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID
|
|
||||||
from utils.pb_handler import handle_pb_command
|
from utils.pb_handler import handle_pb_command
|
||||||
|
|
||||||
class Pbchimera(commands.Cog):
|
class Pbchimera(commands.Cog):
|
||||||
|
"""Cog pour gérer les Personal Bests Chimera"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID
|
|
||||||
from utils.pb_handler import handle_pb_command
|
from utils.pb_handler import handle_pb_command
|
||||||
|
|
||||||
class Pbcvc(commands.Cog):
|
class Pbcvc(commands.Cog):
|
||||||
|
"""Cog pour gérer les Personal Bests CvC (sans difficultés)"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
@commands.command(name="pbcvc")
|
@commands.command(name="pbcvc")
|
||||||
async def pbcvc(self, ctx, target_user: str = None):
|
async def pbcvc(self, ctx, target_user: str = None):
|
||||||
"""Commande !pbcvc (sans difficultées)"""
|
"""Commande !pbcvc"""
|
||||||
await handle_pb_command(ctx, 'cvc', target_user)
|
await handle_pb_command(ctx, 'cvc', target_user)
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from config import AUTHORIZED_CHANNEL_ID
|
|
||||||
from utils.pb_handler import handle_pb_command
|
from utils.pb_handler import handle_pb_command
|
||||||
|
|
||||||
class Pbhydra(commands.Cog):
|
class Pbhydra(commands.Cog):
|
||||||
|
"""Cog pour gérer les Personal Bests Hydra"""
|
||||||
|
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from utils.leaderboard_handler import show_leaderboard
|
from utils.leaderboard_handler import show_leaderboard
|
||||||
|
|
@ -77,7 +78,11 @@ class Top10(commands.Cog):
|
||||||
await show_leaderboard(ctx, boss_type, difficulty, clan)
|
await show_leaderboard(ctx, boss_type, difficulty, clan)
|
||||||
elif boss_type != 'cvc': # CvC n’a pas de difficultés
|
elif boss_type != 'cvc': # CvC n’a pas de difficultés
|
||||||
difficulties = " | ".join(BOSS_CONFIG[boss_type]['difficulties'])
|
difficulties = " | ".join(BOSS_CONFIG[boss_type]['difficulties'])
|
||||||
await ctx.send(f"❌ Please specify difficulty: `!{ctx.command.name} <difficulty>`\n**Available:** {difficulties}\n**Shortcuts:** `nm` = Nightmare, `unm` = Ultra")
|
await ctx.send(
|
||||||
|
f"❌ Please specify difficulty: `!{ctx.command.name} <difficulty>`\n"
|
||||||
|
f"**Available:** {difficulties}\n"
|
||||||
|
f"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
await show_leaderboard(ctx, boss_type, clan=clan)
|
await show_leaderboard(ctx, boss_type, clan=clan)
|
||||||
|
|
||||||
|
|
|
||||||
20
config.py
20
config.py
|
|
@ -8,26 +8,26 @@ DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
|
||||||
AUTHORIZED_CHANNEL_ID = int(os.getenv("AUTHORIZED_CHANNEL_ID"))
|
AUTHORIZED_CHANNEL_ID = int(os.getenv("AUTHORIZED_CHANNEL_ID"))
|
||||||
|
|
||||||
# Chemins
|
# Chemins
|
||||||
SCREENSHOTS_BASE_PATH = "/share/Container/discord-bot/screenshots"
|
SCREENSHOTS_BASE_PATH = "/app/screenshots"
|
||||||
DATABASE_PATH = "/share/Container/discord-bot/bot_data.db"
|
DATABASE_PATH = "/app/data/bot_data.db"
|
||||||
|
|
||||||
# Configuration des clans
|
# Configuration des clans
|
||||||
CLAN_CONFIG = {
|
CLAN_CONFIG = {
|
||||||
'RTF': {'name': 'RTF', 'emoji': '⭐', 'color': 0x00ff00},
|
'RTF': {'name': 'RTF', 'emoji': 'â', 'color': 0x00ff00},
|
||||||
'RTFC': {'name': 'RTFC', 'emoji': '🔥', 'color': 0xff4500},
|
'RTFC': {'name': 'RTFC', 'emoji': '🔥', 'color': 0xff4500},
|
||||||
'RTFR': {'name': 'RTFR', 'emoji': '⚡', 'color': 0x1e90ff}
|
'RTFR': {'name': 'RTFR', 'emoji': 'âš¡', 'color': 0x1e90ff}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration des boss avec difficultés
|
# Configuration des boss avec difficultées
|
||||||
BOSS_CONFIG = {
|
BOSS_CONFIG = {
|
||||||
'hydra': {'name': 'Hydra', 'emoji': '🐍', 'color': 0xff6b35,
|
'hydra': {'name': 'Hydra', 'emoji': 'ðŸ', 'color': 0xff6b35,
|
||||||
'difficulties': ['normal', 'hard', 'brutal', 'nightmare']},
|
'difficulties': ['normal', 'hard', 'brutal', 'nightmare']},
|
||||||
'chimera': {'name': 'Chimera', 'emoji': '🦁', 'color': 0x9932cc,
|
'chimera': {'name': 'Chimera', 'emoji': 'ðŸ¦', 'color': 0x9932cc,
|
||||||
'difficulties': ['easy', 'normal', 'hard', 'brutal', 'nightmare', 'ultra']},
|
'difficulties': ['easy', 'normal', 'hard', 'brutal', 'nightmare', 'ultra']},
|
||||||
'cvc': {'name': 'Clan vs Clan', 'emoji': '⚔️', 'color': 0xff0000, 'difficulties': []}
|
'cvc': {'name': 'Clan vs Clan', 'emoji': 'âš”ï¸', 'color': 0xff0000, 'difficulties': []}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mappings pour diminutifs de difficultés
|
# Mappings pour diminutifs de difficultés
|
||||||
DIFFICULTY_SHORTCUTS = {
|
DIFFICULTY_SHORTCUTS = {
|
||||||
'nm': 'nightmare',
|
'nm': 'nightmare',
|
||||||
'unm': 'ultra'
|
'unm': 'ultra'
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ services:
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
# Montre le code source pour hot-reload
|
# Monte le code source pour hot-reload
|
||||||
- ./:/app
|
- ./:/app
|
||||||
# Montre les dossiers de stockage persistants
|
# Monte les dossiers de stockage persistants
|
||||||
- ./screenshots:/app/screenshots
|
- ./screenshots:/app/screenshots
|
||||||
- ./bot_data.db:/app/bot_data.db
|
- ./data:/app/data
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
from config import DATABASE_PATH
|
from config import DATABASE_PATH
|
||||||
import sqlite3, os
|
import sqlite3, os
|
||||||
|
|
||||||
class DatabaseManager:
|
class DatabaseManager:
|
||||||
def __init__(self, db_path=DATABASE_PATH):
|
def __init__(self, db_path=DATABASE_PATH):
|
||||||
self.db_path = db_path
|
self.db_path = db_path
|
||||||
|
|
@ -51,7 +53,7 @@ class DatabaseManager:
|
||||||
pb_chimera_ultra_screenshot TEXT,
|
pb_chimera_ultra_screenshot TEXT,
|
||||||
pb_chimera_ultra_date TIMESTAMP,
|
pb_chimera_ultra_date TIMESTAMP,
|
||||||
|
|
||||||
-- CvC (unchanged)
|
-- CvC (inchangé)
|
||||||
pb_cvc INTEGER DEFAULT 0,
|
pb_cvc INTEGER DEFAULT 0,
|
||||||
pb_cvc_screenshot TEXT,
|
pb_cvc_screenshot TEXT,
|
||||||
pb_cvc_date TIMESTAMP,
|
pb_cvc_date TIMESTAMP,
|
||||||
|
|
@ -170,11 +172,10 @@ class DatabaseManager:
|
||||||
# Récupérer toutes les colonnes de PB
|
# Récupérer toutes les colonnes de PB
|
||||||
cursor.execute('SELECT * FROM users WHERE discord_username = ?', (username.lower(),))
|
cursor.execute('SELECT * FROM users WHERE discord_username = ?', (username.lower(),))
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
|
columns = [desc[0] for desc in cursor.description]
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Convertir en dictionnaire pour faciliter l'accès
|
return dict(zip(columns, result))
|
||||||
columns = [desc[0] for desc in cursor.description]
|
|
||||||
return dict(zip(columns, result)) if result else None
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from config import DATABASE_PATH
|
from config import DATABASE_PATH
|
||||||
|
|
@ -18,6 +19,7 @@ class MercyManager:
|
||||||
self.init_table()
|
self.init_table()
|
||||||
|
|
||||||
def init_table(self):
|
def init_table(self):
|
||||||
|
"""Initialise la table des compteurs de mercy"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = sqlite3.connect(self.db_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
|
|
@ -33,6 +35,7 @@ class MercyManager:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def get_pulls(self, user_id, shard_type):
|
def get_pulls(self, user_id, shard_type):
|
||||||
|
"""Retourne le nombre de pulls actuels pour un utilisateur et un type de shard"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = sqlite3.connect(self.db_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
|
|
@ -44,24 +47,36 @@ class MercyManager:
|
||||||
return row[0] if row else 0
|
return row[0] if row else 0
|
||||||
|
|
||||||
def add_pulls(self, user_id, shard_type, pulls):
|
def add_pulls(self, user_id, shard_type, pulls):
|
||||||
current = self.get_pulls(user_id, shard_type)
|
"""Ajoute des pulls pour un utilisateur en gérant correctement l'INSERT/UPDATE"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = sqlite3.connect(self.db_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
if current:
|
|
||||||
|
# Vérifie si l'enregistrement existe
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT pulls FROM mercy_counters WHERE user_id = ? AND shard_type = ?",
|
||||||
|
(user_id, shard_type)
|
||||||
|
)
|
||||||
|
row = cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
new_pulls = row[0] + pulls
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"UPDATE mercy_counters SET pulls = ?, last_reset = ? WHERE user_id = ? AND shard_type = ?",
|
"UPDATE mercy_counters SET pulls = ?, last_reset = ? WHERE user_id = ? AND shard_type = ?",
|
||||||
(current + pulls, datetime.utcnow(), user_id, shard_type)
|
(new_pulls, datetime.utcnow(), user_id, shard_type)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
new_pulls = pulls
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"INSERT INTO mercy_counters (user_id, shard_type, pulls, last_reset) VALUES (?, ?, ?, ?)",
|
"INSERT INTO mercy_counters (user_id, shard_type, pulls, last_reset) VALUES (?, ?, ?, ?)",
|
||||||
(user_id, shard_type, pulls, datetime.utcnow())
|
(user_id, shard_type, new_pulls, datetime.utcnow())
|
||||||
)
|
)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return current + pulls
|
return new_pulls
|
||||||
|
|
||||||
def reset_pulls(self, user_id, shard_type):
|
def reset_pulls(self, user_id, shard_type):
|
||||||
|
"""Réinitialise les pulls d'un utilisateur pour un shard"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = sqlite3.connect(self.db_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
|
|
@ -72,6 +87,7 @@ class MercyManager:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def get_all_pulls(self, user_id):
|
def get_all_pulls(self, user_id):
|
||||||
|
"""Retourne tous les pulls d'un utilisateur pour tous les shards"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = sqlite3.connect(self.db_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
|
|
@ -83,6 +99,7 @@ class MercyManager:
|
||||||
return {shard_type: pulls for shard_type, pulls in rows}
|
return {shard_type: pulls for shard_type, pulls in rows}
|
||||||
|
|
||||||
def get_mercy_chance(self, shard_type, pulls):
|
def get_mercy_chance(self, shard_type, pulls):
|
||||||
|
"""Calcule la probabilité de mercy selon le nombre de pulls"""
|
||||||
rule = MERCY_RULES[shard_type]
|
rule = MERCY_RULES[shard_type]
|
||||||
if pulls <= rule["threshold"]:
|
if pulls <= rule["threshold"]:
|
||||||
return rule["base"]
|
return rule["base"]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import sqlite3, os
|
import sqlite3, os
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
@ -33,13 +34,14 @@ class ScreenshotManager:
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
async with session.get(attachment.url) as resp:
|
async with session.get(attachment.url) as resp:
|
||||||
if resp.status == 200:
|
if resp.status == 200:
|
||||||
|
# Ouverture en binaire, pas de problème d'encodage
|
||||||
with open(filepath, 'wb') as f:
|
with open(filepath, 'wb') as f:
|
||||||
f.write(await resp.read())
|
f.write(await resp.read())
|
||||||
return filename
|
return filename
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Erreur sauvegarde screenshot: {e}")
|
print(f"Erreur sauvegarde screenshot: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_screenshot_path(self, filename, boss_type, difficulty=None):
|
def get_screenshot_path(self, filename, boss_type, difficulty=None):
|
||||||
|
|
@ -60,4 +62,4 @@ class ScreenshotManager:
|
||||||
os.remove(old_path)
|
os.remove(old_path)
|
||||||
print(f"Ancien screenshot supprimé: {filename}")
|
print(f"Ancien screenshot supprimé: {filename}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Erreur suppression screenshot: {e}")
|
print(f"Erreur suppression screenshot: {str(e)}")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from config import AUTHORIZED_CHANNEL_ID, DIFFICULTY_SHORTCUTS
|
from config import AUTHORIZED_CHANNEL_ID, DIFFICULTY_SHORTCUTS
|
||||||
|
|
@ -17,7 +18,7 @@ def parse_damage_amount(damage_str):
|
||||||
number = float(number_str)
|
number = float(number_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
multipliers = {'K': 1000, 'M': 1_000_000, 'B': 1_000_000_000, '': 1}
|
multipliers = {'K': 1_000, 'M': 1_000_000, 'B': 1_000_000_000, '': 1}
|
||||||
return int(number * multipliers[suffix])
|
return int(number * multipliers[suffix])
|
||||||
|
|
||||||
def format_damage_display(damage):
|
def format_damage_display(damage):
|
||||||
|
|
@ -37,31 +38,22 @@ def normalize_difficulty(difficulty):
|
||||||
"""Normalise une difficulté en gérant les diminutifs"""
|
"""Normalise une difficulté en gérant les diminutifs"""
|
||||||
if not difficulty:
|
if not difficulty:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
difficulty_lower = difficulty.lower()
|
difficulty_lower = difficulty.lower()
|
||||||
|
|
||||||
# Vérifier les diminutifs d'abord
|
|
||||||
if difficulty_lower in DIFFICULTY_SHORTCUTS:
|
if difficulty_lower in DIFFICULTY_SHORTCUTS:
|
||||||
return DIFFICULTY_SHORTCUTS[difficulty_lower]
|
return DIFFICULTY_SHORTCUTS[difficulty_lower]
|
||||||
|
|
||||||
# Sinon retourner tel quel
|
|
||||||
return difficulty_lower
|
return difficulty_lower
|
||||||
|
|
||||||
# Fonctions utilitaires
|
|
||||||
def get_user_clan(username):
|
def get_user_clan(username):
|
||||||
"""Détermine le clan d'un utilisateur basé sur son pseudo - Version corrigée"""
|
"""Détermine le clan d'un utilisateur basé sur son pseudo"""
|
||||||
username_upper = username.upper()
|
username_upper = username.upper()
|
||||||
|
# Tags avec crochets et espace
|
||||||
# Chercher les tags avec crochets et espace
|
|
||||||
for clan_tag in ['[RTF] ', '[RTFC] ', '[RTFR] ']:
|
for clan_tag in ['[RTF] ', '[RTFC] ', '[RTFR] ']:
|
||||||
if username_upper.startswith(clan_tag):
|
if username_upper.startswith(clan_tag):
|
||||||
return clan_tag.replace('[', '').replace(']', '').strip()
|
return clan_tag.replace('[', '').replace(']', '').strip()
|
||||||
|
# Tags avec crochets sans espace
|
||||||
# Chercher les tags avec crochets sans espace
|
|
||||||
for clan_tag in ['[RTF]', '[RTFC]', '[RTFR]']:
|
for clan_tag in ['[RTF]', '[RTFC]', '[RTFR]']:
|
||||||
if username_upper.startswith(clan_tag):
|
if username_upper.startswith(clan_tag):
|
||||||
return clan_tag.replace('[', '').replace(']', '')
|
return clan_tag.replace('[', '').replace(']', '')
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def format_datetime(date_str):
|
def format_datetime(date_str):
|
||||||
|
|
@ -117,4 +109,3 @@ def calc_chance_and_guarantee(shard_type, pulls):
|
||||||
guaranteed_at = int(rule["start"] + (100 - rule["base"]) / rule["increment"])
|
guaranteed_at = int(rule["start"] + (100 - rule["base"]) / rule["increment"])
|
||||||
remaining = max(0, guaranteed_at - pulls)
|
remaining = max(0, guaranteed_at - pulls)
|
||||||
return chance, guaranteed_at, remaining
|
return chance, guaranteed_at, remaining
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import os
|
import os
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
@ -11,17 +12,17 @@ def set_db_manager(db):
|
||||||
db_manager = db
|
db_manager = db
|
||||||
|
|
||||||
async def show_leaderboard(ctx, boss_type, difficulty=None, clan=None):
|
async def show_leaderboard(ctx, boss_type, difficulty=None, clan=None):
|
||||||
"""Fonction générique pour afficher les classements"""
|
"""Fonction générique pour afficher les classements"""
|
||||||
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Normaliser la difficulté si spécifiée
|
# Normaliser la difficulté si spécifiée
|
||||||
if difficulty:
|
if difficulty:
|
||||||
difficulty = normalize_difficulty(difficulty)
|
difficulty = normalize_difficulty(difficulty)
|
||||||
if difficulty not in BOSS_CONFIG[boss_type]['difficulties']:
|
if difficulty not in BOSS_CONFIG[boss_type]['difficulties']:
|
||||||
difficulties = " | ".join(BOSS_CONFIG[boss_type]['difficulties'])
|
difficulties = " | ".join(BOSS_CONFIG[boss_type]['difficulties'])
|
||||||
await ctx.send(f"⌠Invalid difficulty. Available: {difficulties}")
|
await ctx.send(f"⚠️ Invalid difficulty. Available: {difficulties}")
|
||||||
return
|
return
|
||||||
|
|
||||||
boss_info = BOSS_CONFIG[boss_type]
|
boss_info = BOSS_CONFIG[boss_type]
|
||||||
|
|
@ -30,15 +31,15 @@ async def show_leaderboard(ctx, boss_type, difficulty=None, clan=None):
|
||||||
if not leaderboard:
|
if not leaderboard:
|
||||||
clan_text = f" for clan {clan}" if clan else ""
|
clan_text = f" for clan {clan}" if clan else ""
|
||||||
difficulty_text = f" {get_difficulty_display_name(difficulty)}" if difficulty else ""
|
difficulty_text = f" {get_difficulty_display_name(difficulty)}" if difficulty else ""
|
||||||
await ctx.send(f"⌠No{difficulty_text} {boss_info['name']} records found{clan_text} yet!")
|
await ctx.send(f"⚠️ No{difficulty_text} {boss_info['name']} records found{clan_text} yet!")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Titre avec clan et difficulté si spécifiés
|
# Titre avec clan et difficulté si spécifiés
|
||||||
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
||||||
title = f"🆠{difficulty_name} {boss_info['name']} Leaderboard - Top 10"
|
title = f"🏆 {difficulty_name} {boss_info['name']} Leaderboard - Top 10"
|
||||||
|
|
||||||
if clan:
|
if clan:
|
||||||
clan_info = CLAN_CONFIG.get(clan, {'name': clan, 'emoji': 'ðŸ›ï¸'})
|
clan_info = CLAN_CONFIG.get(clan, {'name': clan, 'emoji': '🏛️'})
|
||||||
title = f"{clan_info['emoji']} {clan_info['name']} - {difficulty_name} {boss_info['name']} Top 10"
|
title = f"{clan_info['emoji']} {clan_info['name']} - {difficulty_name} {boss_info['name']} Top 10"
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
|
|
@ -46,21 +47,21 @@ async def show_leaderboard(ctx, boss_type, difficulty=None, clan=None):
|
||||||
color=boss_info['color'] if not clan else CLAN_CONFIG.get(clan, {'color': boss_info['color']})['color']
|
color=boss_info['color'] if not clan else CLAN_CONFIG.get(clan, {'color': boss_info['color']})['color']
|
||||||
)
|
)
|
||||||
|
|
||||||
medals = ["🥇", "🥈", "🥉"] + ["ðŸ…"] * 7
|
medals = ["🥇", "🥈", "🥉"] + ["🏅"] * 7
|
||||||
|
|
||||||
for i, (username, damage, date) in enumerate(leaderboard):
|
for i, (username, damage, date) in enumerate(leaderboard):
|
||||||
date_text = ""
|
date_text = ""
|
||||||
if date:
|
if date:
|
||||||
formatted_date = format_date_only(date)
|
formatted_date = format_date_only(date)
|
||||||
if formatted_date:
|
if formatted_date:
|
||||||
date_text = f" • {formatted_date}"
|
date_text = f" • {formatted_date}"
|
||||||
|
|
||||||
# Afficher le clan dans le nom si pas de filtre par clan
|
# Afficher le clan dans le nom si pas de filtre par clan
|
||||||
display_name = username
|
display_name = username
|
||||||
if not clan:
|
if not clan:
|
||||||
user_clan = get_user_clan(username)
|
user_clan = get_user_clan(username)
|
||||||
if user_clan:
|
if user_clan:
|
||||||
clan_emoji = CLAN_CONFIG.get(user_clan, {'emoji': 'ðŸ›ï¸'})['emoji']
|
clan_emoji = CLAN_CONFIG.get(user_clan, {'emoji': '🏛️'})['emoji']
|
||||||
display_name = f"{clan_emoji} {username}"
|
display_name = f"{clan_emoji} {username}"
|
||||||
|
|
||||||
embed.add_field(
|
embed.add_field(
|
||||||
|
|
@ -72,4 +73,4 @@ async def show_leaderboard(ctx, boss_type, difficulty=None, clan=None):
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"⌠Error: {e}")
|
await ctx.send(f"⚠️ Error: {e}")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
import os
|
import os
|
||||||
import discord
|
import discord
|
||||||
from config import AUTHORIZED_CHANNEL_ID, BOSS_CONFIG
|
from config import AUTHORIZED_CHANNEL_ID, BOSS_CONFIG
|
||||||
|
|
@ -13,13 +14,13 @@ db_manager = None
|
||||||
screenshot_manager = None
|
screenshot_manager = None
|
||||||
|
|
||||||
def set_managers(db, ss):
|
def set_managers(db, ss):
|
||||||
"""Injection des managers (appelée une seule fois depuis bot.py)"""
|
"""Injection des managers (appelée une seule fois depuis bot.py)"""
|
||||||
global db_manager, screenshot_manager
|
global db_manager, screenshot_manager
|
||||||
db_manager = db
|
db_manager = db
|
||||||
screenshot_manager = ss
|
screenshot_manager = ss
|
||||||
|
|
||||||
async def handle_pb_command(ctx, boss_type, arg1=None, arg2=None):
|
async def handle_pb_command(ctx, boss_type, arg1=None, arg2=None):
|
||||||
"""Fonction générique pour gérer toutes les commandes PB avec difficultés"""
|
"""Fonction générique pour gérer toutes les commandes PB avec difficultés"""
|
||||||
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
if ctx.channel.id != AUTHORIZED_CHANNEL_ID:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -27,25 +28,23 @@ async def handle_pb_command(ctx, boss_type, arg1=None, arg2=None):
|
||||||
difficulties = boss_info['difficulties']
|
difficulties = boss_info['difficulties']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Pour CvC (pas de difficultés)
|
# Pour CvC (pas de difficultés)
|
||||||
if not difficulties:
|
if not difficulties:
|
||||||
# Utiliser l'ancienne logique pour CvC avec parsing des montants
|
|
||||||
if arg1:
|
if arg1:
|
||||||
damage = parse_damage_amount(arg1)
|
damage = parse_damage_amount(arg1)
|
||||||
if damage is not None:
|
if damage is not None:
|
||||||
await handle_pb_submission(ctx, boss_type, None, damage)
|
await handle_pb_submission(ctx, boss_type, None, damage)
|
||||||
else: # Username
|
else:
|
||||||
await show_user_pb(ctx, boss_type, None, arg1)
|
await show_user_pb(ctx, boss_type, None, arg1)
|
||||||
else: # Montrer son propre PB
|
else:
|
||||||
await show_user_pb(ctx, boss_type, None, ctx.author.display_name)
|
await show_user_pb(ctx, boss_type, None, ctx.author.display_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Pour Hydra et Chimera (avec difficultés)
|
# Pour Hydra et Chimera (avec difficultés)
|
||||||
if not arg1:
|
if not arg1:
|
||||||
# !pbhydra sans arguments - montrer aide
|
|
||||||
difficulty_list = " | ".join([d.title() for d in difficulties])
|
difficulty_list = " | ".join([d.title() for d in difficulties])
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"⌠Please specify difficulty and damage!\n"
|
f"⚠️ Please specify difficulty and damage!\n"
|
||||||
f"**Available difficulties:** {difficulty_list}\n"
|
f"**Available difficulties:** {difficulty_list}\n"
|
||||||
f"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare\n"
|
f"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare\n"
|
||||||
f"**Examples:**\n"
|
f"**Examples:**\n"
|
||||||
|
|
@ -56,63 +55,54 @@ async def handle_pb_command(ctx, boss_type, arg1=None, arg2=None):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Normaliser la difficulté (gérer les diminutifs)
|
|
||||||
normalized_difficulty = normalize_difficulty(arg1)
|
normalized_difficulty = normalize_difficulty(arg1)
|
||||||
|
|
||||||
# Vérifier si arg1 est une difficulté valide
|
|
||||||
if normalized_difficulty in difficulties:
|
if normalized_difficulty in difficulties:
|
||||||
difficulty = normalized_difficulty
|
difficulty = normalized_difficulty
|
||||||
|
|
||||||
if arg2:
|
if arg2:
|
||||||
damage = parse_damage_amount(arg2)
|
damage = parse_damage_amount(arg2)
|
||||||
if damage is not None:
|
if damage is not None:
|
||||||
# !pbhydra normal 1.5M - Soumission PB
|
|
||||||
await handle_pb_submission(ctx, boss_type, difficulty, damage)
|
await handle_pb_submission(ctx, boss_type, difficulty, damage)
|
||||||
else:
|
else:
|
||||||
# !pbhydra normal username - Voir PB d'un utilisateur
|
|
||||||
await show_user_pb(ctx, boss_type, difficulty, arg2)
|
await show_user_pb(ctx, boss_type, difficulty, arg2)
|
||||||
else:
|
else:
|
||||||
# !pbhydra normal - Voir son propre PB
|
|
||||||
await show_user_pb(ctx, boss_type, difficulty, ctx.author.display_name)
|
await show_user_pb(ctx, boss_type, difficulty, ctx.author.display_name)
|
||||||
else:
|
else:
|
||||||
# arg1 n'est pas une difficulté valide
|
|
||||||
difficulty_list = " | ".join([d.title() for d in difficulties])
|
difficulty_list = " | ".join([d.title() for d in difficulties])
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"⌠Invalid difficulty: `{arg1}`\n"
|
f"⚠️ Invalid difficulty: `{arg1}`\n"
|
||||||
f"**Available difficulties:** {difficulty_list}\n"
|
f"**Available difficulties:** {difficulty_list}\n"
|
||||||
f"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare"
|
f"**Shortcuts:** `nm` = Nightmare, `unm` = Ultra Nightmare"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"⌠Error: {e}")
|
await ctx.send(f"⚠️ Error: {str(e)}")
|
||||||
|
|
||||||
async def handle_pb_submission(ctx, boss_type, difficulty, damage):
|
async def handle_pb_submission(ctx, boss_type, difficulty, damage):
|
||||||
"""Gère la soumission d'un nouveau PB"""
|
"""Gère la soumission d'un nouveau PB"""
|
||||||
if not ctx.message.attachments:
|
if not ctx.message.attachments:
|
||||||
await ctx.send("⌠Please attach a screenshot to validate your PB!")
|
await ctx.send("⚠️ Please attach a screenshot to validate your PB!")
|
||||||
return
|
return
|
||||||
|
|
||||||
attachment = ctx.message.attachments[0]
|
attachment = ctx.message.attachments[0]
|
||||||
if not any(attachment.filename.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.gif', '.webp']):
|
if not any(attachment.filename.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.gif', '.webp']):
|
||||||
await ctx.send("⌠Please attach a valid image file!")
|
await ctx.send("⚠️ Please attach a valid image file!")
|
||||||
return
|
return
|
||||||
|
|
||||||
username = ctx.author.display_name
|
username = ctx.author.display_name
|
||||||
current_pb, _, _ = db_manager.get_user_pb(username, boss_type, difficulty)
|
current_pb, _, _ = db_manager.get_user_pb(username, boss_type, difficulty)
|
||||||
|
|
||||||
if damage > current_pb:
|
if damage > current_pb:
|
||||||
# Sauvegarder la nouvelle screenshot
|
|
||||||
screenshot_filename = await screenshot_manager.save_screenshot(
|
screenshot_filename = await screenshot_manager.save_screenshot(
|
||||||
attachment, username, damage, boss_type, difficulty
|
attachment, username, damage, boss_type, difficulty
|
||||||
)
|
)
|
||||||
|
|
||||||
if screenshot_filename:
|
if screenshot_filename:
|
||||||
# Mettre à jour la base et récupérer l'ancien screenshot
|
|
||||||
old_screenshot = db_manager.update_user_pb(
|
old_screenshot = db_manager.update_user_pb(
|
||||||
username, boss_type, damage, screenshot_filename, difficulty
|
username, boss_type, damage, screenshot_filename, difficulty
|
||||||
)
|
)
|
||||||
|
|
||||||
# Supprimer l'ancien screenshot
|
|
||||||
if old_screenshot:
|
if old_screenshot:
|
||||||
screenshot_manager.delete_old_screenshot(old_screenshot, boss_type, difficulty)
|
screenshot_manager.delete_old_screenshot(old_screenshot, boss_type, difficulty)
|
||||||
|
|
||||||
|
|
@ -121,70 +111,50 @@ async def handle_pb_submission(ctx, boss_type, difficulty, damage):
|
||||||
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"🎉 NEW {boss_info['name'].upper()} PB! 🎉",
|
title=f"🎉 NEW {boss_info['name'].upper()} PB! 🎉",
|
||||||
description=f"**{username}** just hit **{format_damage_display(damage)} damage** on {difficulty_name} {boss_info['name']}!",
|
description=f"**{username}** just hit **{format_damage_display(damage)} damage** on {difficulty_name} {boss_info['name']}!",
|
||||||
color=0x00ff00
|
color=0x00ff00
|
||||||
)
|
)
|
||||||
embed.add_field(name="📈 Improvement", value=f"+{format_damage_display(improvement)} damage", inline=True)
|
embed.add_field(name="📈 Improvement", value=f"+{format_damage_display(improvement)} damage", inline=True)
|
||||||
embed.set_image(url=attachment.url)
|
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
# Envoi du screenshot correctement pour Discord
|
||||||
|
screenshot_path = screenshot_manager.get_screenshot_path(screenshot_filename, boss_type, difficulty)
|
||||||
|
if screenshot_path and os.path.exists(screenshot_path):
|
||||||
|
file = discord.File(screenshot_path, filename=screenshot_filename)
|
||||||
|
embed.set_image(url=f"attachment://{screenshot_filename}")
|
||||||
|
await ctx.send(embed=embed, file=file)
|
||||||
|
else:
|
||||||
|
await ctx.send(embed=embed)
|
||||||
else:
|
else:
|
||||||
await ctx.send("⌠Failed to save screenshot. Please try again.")
|
await ctx.send("⚠️ Failed to save screenshot. Please try again.")
|
||||||
else:
|
else:
|
||||||
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
# Si le PB n'est pas battu, on montre le PB existant
|
||||||
embed = discord.Embed(
|
await show_user_pb(ctx, boss_type, difficulty, username)
|
||||||
title="💪 Nice attempt!",
|
|
||||||
description=f"Your damage: **{format_damage_display(damage)}**\nCurrent PB: **{format_damage_display(current_pb)}**",
|
|
||||||
color=0xffa500
|
|
||||||
)
|
|
||||||
embed.add_field(
|
|
||||||
name="Keep going!",
|
|
||||||
value=f"You need **{format_damage_display(current_pb - damage + 1)}** more damage for a new {difficulty_name} PB!",
|
|
||||||
inline=False
|
|
||||||
)
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
||||||
|
|
||||||
async def show_user_pb(ctx, boss_type, difficulty, username):
|
|
||||||
"""Affiche le PB d'un utilisateur"""
|
|
||||||
pb_data = db_manager.get_user_pb(username, boss_type, difficulty)
|
|
||||||
pb_damage, screenshot_filename, pb_date = pb_data
|
|
||||||
|
|
||||||
|
async def show_user_pb(ctx, boss_type, difficulty, target_user):
|
||||||
|
"""Affiche le PB actuel d'un utilisateur"""
|
||||||
|
current_pb, screenshot, date = db_manager.get_user_pb(target_user, boss_type, difficulty)
|
||||||
boss_info = BOSS_CONFIG[boss_type]
|
boss_info = BOSS_CONFIG[boss_type]
|
||||||
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
difficulty_name = get_difficulty_display_name(difficulty) if difficulty else ""
|
||||||
|
|
||||||
if pb_damage == 0:
|
if current_pb > 0:
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
title=f"{boss_info['emoji']} {username}'s {difficulty_name} {boss_info['name']} PB",
|
title=f"📊 {target_user}'s {difficulty_name} {boss_info['name']} PB",
|
||||||
description="**No record yet**",
|
description=f"**{format_damage_display(current_pb)} damage**",
|
||||||
color=0x666666
|
color=0x00bfff
|
||||||
)
|
|
||||||
embed.add_field(
|
|
||||||
name="💡 Get started!",
|
|
||||||
value=f"Use `!pb{boss_type} {difficulty} <damage>` with a screenshot to set your first record!\nAccepts K/M/B suffixes: `1.5M`, `500K`, etc.",
|
|
||||||
inline=False
|
|
||||||
)
|
)
|
||||||
|
if date:
|
||||||
|
embed.add_field(name="📅 Date", value=format_datetime(date), inline=True)
|
||||||
|
|
||||||
|
# Envoi du screenshot local correctement
|
||||||
|
if screenshot:
|
||||||
|
screenshot_path = screenshot_manager.get_screenshot_path(screenshot, boss_type, difficulty)
|
||||||
|
if screenshot_path and os.path.exists(screenshot_path):
|
||||||
|
file = discord.File(screenshot_path, filename=screenshot)
|
||||||
|
embed.set_image(url=f"attachment://{screenshot}")
|
||||||
|
await ctx.send(embed=embed, file=file)
|
||||||
|
return
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
return
|
else:
|
||||||
|
await ctx.send(f"⚠️ No PB found for **{target_user}** on {difficulty_name} {boss_info['name']}.")
|
||||||
embed = discord.Embed(
|
|
||||||
title=f"{boss_info['emoji']} {username}'s {difficulty_name} {boss_info['name']} PB",
|
|
||||||
description=f"**{format_damage_display(pb_damage)} damage**",
|
|
||||||
color=boss_info['color']
|
|
||||||
)
|
|
||||||
if pb_date:
|
|
||||||
formatted_date = format_datetime(pb_date)
|
|
||||||
if formatted_date:
|
|
||||||
embed.add_field(name="📅 Record Date", value=formatted_date, inline=False)
|
|
||||||
|
|
||||||
# Envoyer la screenshot si elle existe
|
|
||||||
if screenshot_filename:
|
|
||||||
screenshot_path = screenshot_manager.get_screenshot_path(screenshot_filename, boss_type, difficulty)
|
|
||||||
if screenshot_path and os.path.exists(screenshot_path):
|
|
||||||
file = discord.File(screenshot_path, filename=f"{username}_{boss_type}_{difficulty}_pb.png")
|
|
||||||
embed.set_image(url=f"attachment://{username}_{boss_type}_{difficulty}_pb.png")
|
|
||||||
await ctx.send(embed=embed, file=file)
|
|
||||||
return
|
|
||||||
|
|
||||||
await ctx.send(embed=embed)
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue