This commit is contained in:
2026-03-15 12:22:42 +01:00
parent cd99275933
commit 311ba5e7f3
558 changed files with 55182 additions and 22981 deletions

View File

@@ -1,96 +1,97 @@
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
const { getUserXP, getXPProgress, getXPForNextLevel, getUserRank } = require('../../functions/xp/xp.js');
const { colors } = require('../../utils/constants');
const { colors, emojis } = require('../../utils/constants');
module.exports = {
category: 'xp',
data: new SlashCommandBuilder()
.setName('level')
.setDescription('Affiche ton niveau et ton XP')
.addUserOption(option =>
option.setName('user')
.setDescription('L\'utilisateur dont tu veux voir le niveau')
.setRequired(false)),
async execute(interaction) {
await interaction.deferReply();
const target = interaction.options.getUser('user') || interaction.user;
const userXP = await getUserXP(target.id, interaction.guild.id);
if (!userXP) {
return interaction.editReply({
content: '❌ Erreur lors de la récupération des données XP.'
});
}
const progress = getXPProgress(userXP.xp, userXP.level);
const xpForNextLevel = getXPForNextLevel(userXP.level);
const rank = await getUserRank(target.id, interaction.guild.id);
// Créer une barre de progression visuelle
const barLength = 20;
let filled = 0;
let empty = barLength;
// Calculer la barre de progression seulement si progress.needed > 0
if (progress.needed > 0 && progress.current >= 0) {
const percentage = Math.min(100, Math.max(0, (progress.current / progress.needed) * 100));
filled = Math.max(0, Math.min(barLength, Math.floor((percentage / 100) * barLength)));
empty = Math.max(0, barLength - filled);
}
const progressBar = '█'.repeat(filled) + '░'.repeat(empty);
const { emojis } = require('../../utils/constants');
const embed = new EmbedBuilder()
.setAuthor({
name: `${target.displayName}`,
iconURL: target.displayAvatarURL({ dynamic: true })
})
.setTitle(`${emojis.level} Niveau ${userXP.level}`)
.setColor(colors.xp)
.setThumbnail(target.displayAvatarURL({ dynamic: true, size: 256 }))
.setDescription(`**${emojis.rank} Rang #${rank}** sur ${interaction.guild.name}`)
.addFields(
{
name: `${emojis.xp} XP Total`,
value: `\`${userXP.xp.toLocaleString()} XP\``,
inline: true
},
{
name: '📈 Progression',
value: `\`${progress.current}/${progress.needed} XP\` (${progress.percentage}%)`,
inline: true
},
{
name: '🎯 Prochain Niveau',
value: `\`${xpForNextLevel} XP\` requis`,
inline: true
},
{
name: '📊 Barre de Progression',
value: `\`\`\`${progressBar}\`\`\``,
inline: false
},
{
name: '💬 Messages',
value: `\`${(userXP.totalMessages || 0).toLocaleString()}\``,
inline: true
},
{
name: '🎤 Temps Vocal',
value: `\`${Math.floor((userXP.totalVoiceTime || 0) / 60)}h\``,
inline: true
}
)
.setFooter({
text: `${interaction.guild.name} • Niveau ${userXP.level}`,
iconURL: interaction.guild.iconURL({ dynamic: true }) || undefined
})
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
},
};
category: 'xp',
data: new SlashCommandBuilder()
.setName('level')
.setDescription('Affiche ton niveau et ton XP')
.addUserOption(option =>
option.setName('user')
.setDescription('L\'utilisateur dont tu veux voir le niveau')
.setRequired(false)),
async execute(interaction) {
await interaction.deferReply();
const target = interaction.options.getUser('user') || interaction.user;
const userXP = await getUserXP(target.id, interaction.guild.id);
if (!userXP) {
return interaction.editReply({
content: '❌ Erreur lors de la récupération des données XP.'
});
}
const progress = getXPProgress(userXP.xp, userXP.level);
const xpForNextLevel = getXPForNextLevel(userXP.level);
const rank = await getUserRank(target.id, interaction.guild.id);
const barLength = 20;
let filled = 0;
let empty = barLength;
if (progress.needed > 0 && progress.current >= 0) {
const percentage = Math.min(100, Math.max(0, (progress.current / progress.needed) * 100));
filled = Math.max(0, Math.min(barLength, Math.floor((percentage / 100) * barLength)));
empty = Math.max(0, barLength - filled);
}
const progressBar = '█'.repeat(filled) + '░'.repeat(empty);
// Formatage du temps vocal
const totalMinutes = userXP.totalVoiceTime || 0;
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
const voiceTimeStr = `${hours}h ${minutes}m`;
const embed = new EmbedBuilder()
.setAuthor({
name: target.displayName,
iconURL: target.displayAvatarURL({ dynamic: true })
})
.setTitle(`${emojis.level} Niveau ${userXP.level}`)
.setColor(colors.xp)
.setThumbnail(target.displayAvatarURL({ dynamic: true, size: 256 }))
.setDescription(`**${emojis.rank} Rang #${rank}** sur ${interaction.guild.name}`)
.addFields(
{
name: `${emojis.xp} XP Total`,
value: `\`${userXP.xp.toLocaleString()} XP\``,
inline: true
},
{
name: '📈 Progression',
value: `\`${progress.current}/${progress.needed} XP\` (${progress.percentage}%)`,
inline: true
},
{
name: '🎯 Prochain Niveau',
value: `\`${xpForNextLevel} XP\` requis`,
inline: true
},
{
name: '📊 Barre de Progression',
value: `\`\`\`${progressBar}\`\`\``,
inline: false
},
{
name: '💬 Messages',
value: `\`${(userXP.totalMessages || 0).toLocaleString()}\``,
inline: true
},
{
name: '🎤 Temps Vocal',
value: `\`${voiceTimeStr}\``,
inline: true
}
)
.setFooter({
text: `${interaction.guild.name} • Niveau ${userXP.level}`,
iconURL: interaction.guild.iconURL({ dynamic: true }) || undefined
})
.setTimestamp();
await interaction.editReply({ embeds: [embed] });
},
};