Skip to content

Commit

Permalink
v3
Browse files Browse the repository at this point in the history
  • Loading branch information
Plexi09 committed Jan 3, 2025
1 parent 6fcadf8 commit 2006c05
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 158 deletions.
Binary file added __pycache__/data_manager.cpython-311.pyc
Binary file not shown.
Binary file added __pycache__/utils.cpython-311.pyc
Binary file not shown.
176 changes: 18 additions & 158 deletions bot.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,41 @@
import discord
from discord.ext import commands
from discord.ext import commands, tasks
from discord import app_commands
import json
import os
import re
import logging
import asyncio
from datetime import datetime
from dotenv import load_dotenv
from data_manager import DataManager
from utils import extract_number_and_sum, setup_logging

# Configuration du logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
logging.StreamHandler()
]
)
logger = logging.getLogger('DiscordBot')
setup_logging()

logger = logging.getLogger('Le69iste')

# Chargement des variables d'environnement
from dotenv import load_dotenv
load_dotenv()

DATA_FILE = 'data.json'

# Initialisation des intentions et du bot
intents = discord.Intents.default()
intents.messages = True
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)

def load_data():
try:
with open(DATA_FILE, 'r') as f:
content = f.read().strip()
if not content:
logger.warning("Fichier de données vide, création d'une nouvelle structure")
return {"config": {}, "stats": {}}
return json.loads(content)
except FileNotFoundError:
logger.warning(f"Fichier {DATA_FILE} non trouvé, création d'une nouvelle structure")
return {"config": {}, "stats": {}}
except json.JSONDecodeError:
logger.error(f"Erreur de décodage JSON dans {DATA_FILE}. Voulez vous créer une nouvelle structure ? Toutes les données du bot serons perdues (O/N)")
response = input()
if response.lower() == 'o' or response.lower() == 'oui' or response.lower() == 'y' or response.lower() == 'yes':
return {"config": {}, "stats": {}}
else:
logger.error("Arrêt du bot")
exit(1)

def save_data(data):
try:
with open(DATA_FILE, 'w') as f:
json.dump(data, f, indent=4)
logger.debug("Données sauvegardées avec succès")
except Exception as e:
logger.error(f"Erreur lors de la sauvegarde des données: {e}")

def get_guild_config(guild_id: str, data: dict) -> dict:
if guild_id not in data['config']:
data['config'][guild_id] = {
"send_public": True,
"send_message": True,
"enable_reactions": True
}
save_data(data)
return data['config'][guild_id]

def extract_number_and_sum(message):
numbers = list(map(int, re.findall(r'\b\d+\b', message)))
total = sum(numbers)
return numbers, total
# Initialisation du gestionnaire de données
data_manager = DataManager('data.json')

@tasks.loop(hours=1)
async def update_presence():
while True:
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=f"les nombres rigolos sur {len(bot.guilds)} serveurs."))
await asyncio.sleep(3600)
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=f"les nombres rigolos sur {len(bot.guilds)} serveurs."))

@bot.event
async def on_ready():
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=f"les nombres rigolos sur {len(bot.guilds)} serveurs."))
asyncio.create_task(update_presence())
update_presence.start()
logger.info(f'Bot {bot.user} connecté à Discord')
try:
synced = await bot.tree.sync()
logger.info(f'Synchronisé {len(synced)} commandes slash')
logger.info(f'{len(synced)} commandes slash synchronisées')
except Exception as e:
logger.error(f'Erreur lors de la synchronisation des commandes slash: {e}')

Expand All @@ -96,19 +46,13 @@ async def on_message(message):

numbers, total = extract_number_and_sum(message.content)
if total == 69:
data = load_data()
data = data_manager.load_data()
guild_id = str(message.guild.id)
user_id = str(message.author.id)
config = get_guild_config(guild_id, data)
config = data_manager.get_guild_config(guild_id)

# Mettre à jour les statistiques
if guild_id not in data['stats']:
data['stats'][guild_id] = {}
if user_id not in data['stats'][guild_id]:
data['stats'][guild_id][user_id] = {'count_69': 0}

data['stats'][guild_id][user_id]['count_69'] += 1
save_data(data)
data_manager.update_stats(guild_id, user_id, 'count_69')

logger.info(f"69 trouvé dans le message de {message.author.id} sur {message.guild.id}")

Expand Down Expand Up @@ -137,92 +81,8 @@ async def on_message(message):

await bot.process_commands(message)

@bot.tree.command(name="leaderboard_server", description="Affiche le classement des utilisateurs avec le plus de 69 sur ce serveur.")
async def leaderboard_server(interaction: discord.Interaction):
logger.info(f"Commande leaderboard_server utilisée sur {interaction.guild.id}")
data = load_data()
guild_id = str(interaction.guild.id)

if guild_id not in data['stats']:
logger.warning(f"Aucune donnée pour le serveur {guild_id}")
await interaction.response.send_message("Aucune donnée disponible pour ce serveur.")
return

leaderboard = sorted(data['stats'][guild_id].items(), key=lambda x: x[1]['count_69'], reverse=True)
embed = discord.Embed(title="Classement des utilisateurs avec le plus de 69 sur ce serveur", color=discord.Color.blue())

for user_id, stats in leaderboard[:10]:
user = await bot.fetch_user(int(user_id))
embed.add_field(name=user.display_name, value=f"{stats['count_69']} fois", inline=False)

await interaction.response.send_message(embed=embed)

@bot.tree.command(name="leaderboard_global", description="Affiche le classement global des utilisateurs avec le plus de 69.")
async def leaderboard_global(interaction: discord.Interaction):
logger.info(f"Commande leaderboard_global utilisée par {interaction.user}")
data = load_data()
global_stats = {}

for guild_stats in data['stats'].values():
for user_id, stats in guild_stats.items():
if user_id not in global_stats:
global_stats[user_id] = 0
global_stats[user_id] += stats['count_69']

leaderboard = sorted(global_stats.items(), key=lambda x: x[1], reverse=True)
embed = discord.Embed(title="Classement global des utilisateurs avec le plus de 69", color=discord.Color.gold())

for user_id, count in leaderboard[:10]:
user = await bot.fetch_user(int(user_id))
embed.add_field(name=user.display_name, value=f"{count} fois", inline=False)

await interaction.response.send_message(embed=embed)

@bot.tree.command(name="config", description="Affiche ou configure les paramètres du bot.")
async def config(interaction: discord.Interaction):
logger.info(f"Commande config utilisée sur {interaction.guild.id}")
data = load_data()
guild_id = str(interaction.guild.id)
config = get_guild_config(guild_id, data)

embed = discord.Embed(title="Configuration du Bot", color=discord.Color.blue())
embed.add_field(name="Envoi des messages", value="Public" if config['send_public'] else "Privé", inline=True)
embed.add_field(name="Envoi des messages activé", value="Oui" if config['send_message'] else "Non", inline=True)
embed.add_field(name="Réactions activées", value="Oui" if config['enable_reactions'] else "Non", inline=True)
await interaction.response.send_message(embed=embed)

@bot.tree.command(name="set_send_public", description="Configure si les messages doivent être envoyés en public ou en privé.")
@app_commands.describe(send_public="Définir si les messages sont envoyés en public (True) ou en privé (False).")
async def set_send_public(interaction: discord.Interaction, send_public: bool):
logger.info(f"Modification de send_public à {send_public} sur {interaction.guild.id}")
data = load_data()
guild_id = str(interaction.guild.id)
config = get_guild_config(guild_id, data)
config['send_public'] = send_public
save_data(data)
await interaction.response.send_message(f"Envoi des messages {'public' if send_public else 'privé'} configuré.")

@bot.tree.command(name="set_send_message", description="Active ou désactive l'envoi des messages.")
@app_commands.describe(send_message="Définir si l'envoi des messages est activé (True) ou désactivé (False).")
async def set_send_message(interaction: discord.Interaction, send_message: bool):
logger.info(f"Modification de send_message à {send_message} sur {interaction.guild.id}")
data = load_data()
guild_id = str(interaction.guild.id)
config = get_guild_config(guild_id, data)
config['send_message'] = send_message
save_data(data)
await interaction.response.send_message(f"Envoi des messages {'activé' if send_message else 'désactivé'}.")

@bot.tree.command(name="set_enable_reactions", description="Active ou désactive les réactions.")
@app_commands.describe(enable_reactions="Activer ou désactiver les réactions (True ou False).")
async def set_enable_reactions(interaction: discord.Interaction, enable_reactions: bool):
logger.info(f"Modification de enable_reactions à {enable_reactions} sur {interaction.guild.id}")
data = load_data()
guild_id = str(interaction.guild.id)
config = get_guild_config(guild_id, data)
config['enable_reactions'] = enable_reactions
save_data(data)
await interaction.response.send_message(f"Réactions {'activées' if enable_reactions else 'désactivées'}.")
# Ajout des commandes slash ici...
# Exemple : leaderboard_server, leaderboard_global, config, set_send_public, set_send_message, set_enable_reactions

@bot.event
async def on_command_error(ctx, error):
Expand Down
61 changes: 61 additions & 0 deletions data_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import json
import logging
import asyncio

logger = logging.getLogger('DiscordBot')

class DataManager:
def __init__(self, data_file):
self.data_file = data_file
self.lock = asyncio.Lock()

async def load_data(self):
async with self.lock:
try:
with open(self.data_file, 'r') as f:
content = f.read().strip()
if not content:
logger.warning("Fichier de données vide, création d'une nouvelle structure")
return {"config": {}, "stats": {}}
return json.loads(content)
except FileNotFoundError:
logger.warning(f"Fichier {self.data_file} non trouvé, création d'une nouvelle structure")
return {"config": {}, "stats": {}}
except json.JSONDecodeError:
logger.error(f"Erreur de décodage JSON dans {self.data_file}. Voulez vous créer une nouvelle structure ? Toutes les données du bot seront perdues (O/N)")
response = input()
if response.lower() in ['o', 'oui', 'y', 'yes']:
return {"config": {}, "stats": {}}
else:
logger.error("Arrêt du bot")
exit(1)

async def save_data(self, data):
async with self.lock:
try:
with open(self.data_file, 'w') as f:
json.dump(data, f, indent=4)
logger.debug("Données sauvegardées avec succès")
except Exception as e:
logger.error(f"Erreur lors de la sauvegarde des données: {e}")

async def get_guild_config(self, guild_id: str) -> dict:
data = await self.load_data()
if guild_id not in data['config']:
data['config'][guild_id] = {
"send_public": True,
"send_message": True,
"enable_reactions": True
}
await self.save_data(data)
return data['config'][guild_id]

async def update_stats(self, guild_id: str, user_id: str, stat: str):
data = await self.load_data()
if guild_id not in data['stats']:
data['stats'][guild_id] = {}
if user_id not in data['stats'][guild_id]:
data['stats'][guild_id][user_id] = {'count_69': 0}

data['stats'][guild_id][user_id][stat] += 1
await self.save_data(data)
17 changes: 17 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import logging
import re

def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
logging.StreamHandler()
]
)

def extract_number_and_sum(message: str):
numbers = list(map(int, re.findall(r'\b\d+\b', message)))
total = sum(numbers)
return numbers, total

0 comments on commit 2006c05

Please sign in to comment.