235 lines
8.5 KiB
JavaScript
235 lines
8.5 KiB
JavaScript
/**
|
|
* Gestion de l'XP vocal
|
|
* Gain d'XP toutes les 10 minutes en vocal (5-25 XP)
|
|
*/
|
|
|
|
const { Events } = require('discord.js');
|
|
const db = require('../functions/database/db.js');
|
|
const { addXP, getUserXP, getXPMultiplier } = require('../functions/xp/xp.js');
|
|
|
|
// Stocker les utilisateurs en vocal par serveur
|
|
const voiceUsers = new Map(); // Map<guildId_userId, { joinTime, interval }>
|
|
|
|
module.exports = {
|
|
name: Events.VoiceStateUpdate,
|
|
async execute(oldState, newState) {
|
|
const userId = newState.member?.id || oldState.member?.id;
|
|
const guildId = newState.guild?.id || oldState.guild?.id;
|
|
|
|
if (!userId || !guildId) return;
|
|
|
|
// Ignorer les bots
|
|
if (newState.member?.user.bot || oldState.member?.user.bot) return;
|
|
|
|
const key = `${guildId}_${userId}`;
|
|
|
|
// Utilisateur rejoint un canal vocal
|
|
if (!oldState.channelId && newState.channelId) {
|
|
// L'utilisateur a rejoint un canal vocal
|
|
const joinTime = Date.now();
|
|
|
|
// Mettre à jour lastVoiceJoin dans la DB
|
|
await db.query(
|
|
'UPDATE user_xp SET lastVoiceJoin = ? WHERE userId = ? AND guildId = ?',
|
|
[joinTime, userId, guildId]
|
|
).catch(() => {
|
|
// L'utilisateur n'existe pas encore, on le créera lors du premier gain d'XP
|
|
});
|
|
|
|
// Créer un interval pour gagner de l'XP toutes les 10 minutes
|
|
const interval = setInterval(async () => {
|
|
try {
|
|
// Récupérer le serveur et le membre
|
|
const guild = newState.guild || oldState.guild;
|
|
if (!guild) {
|
|
clearInterval(interval);
|
|
voiceUsers.delete(key);
|
|
return;
|
|
}
|
|
|
|
const member = await guild.members.fetch(userId).catch(() => null);
|
|
if (!member || !member.voice.channelId) {
|
|
// L'utilisateur n'est plus en vocal, arrêter l'interval
|
|
clearInterval(interval);
|
|
voiceUsers.delete(key);
|
|
return;
|
|
}
|
|
|
|
// Vérifier si l'utilisateur est seul (anti-farming ultra strict)
|
|
// Ne pas donner d'XP si l'utilisateur est seul dans le salon (peu importe s'il est muet ou non)
|
|
const voiceChannel = member.voice.channel;
|
|
if (voiceChannel) {
|
|
// Compter le nombre de membres dans le salon (sans les bots)
|
|
const membersInChannel = voiceChannel.members.filter(m => !m.user.bot).size;
|
|
const isAlone = membersInChannel === 1; // Seul dans le salon
|
|
|
|
// Si l'utilisateur est seul, ne pas donner d'XP (anti-farming ultra strict)
|
|
if (isAlone) {
|
|
// Ne pas donner d'XP mais continuer le timer (il pourra gagner de l'XP si quelqu'un le rejoint)
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Récupérer le multiplicateur (avec source='voice' pour le bonus vocal)
|
|
const multiplier = getXPMultiplier(member, 'voice');
|
|
|
|
// Gain d'XP vocal : 5-25 XP toutes les 10 minutes
|
|
const xpGained = Math.floor(Math.random() * 21) + 5; // 5-25 XP
|
|
|
|
// Ajouter l'XP
|
|
const result = await addXP(userId, guildId, xpGained, 'voice', multiplier);
|
|
|
|
if (result) {
|
|
// Mettre à jour totalVoiceTime (en minutes)
|
|
await db.query(
|
|
'UPDATE user_xp SET totalVoiceTime = totalVoiceTime + 10 WHERE userId = ? AND guildId = ?',
|
|
[userId, guildId]
|
|
);
|
|
|
|
// Si niveau supérieur, envoyer un message (optionnel, on peut le désactiver pour éviter le spam)
|
|
if (result.levelUp) {
|
|
const { EmbedBuilder } = require('discord.js');
|
|
const { colors } = require('../utils/constants');
|
|
const { getXPProgress } = require('../functions/xp/xp.js');
|
|
|
|
const progress = getXPProgress(result.newXP, result.newLevel);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('🎉 Level Up !')
|
|
.setDescription(`Félicitations ${member.toString()} ! Tu as atteint le niveau **${result.newLevel}** en vocal !`)
|
|
.setColor(colors.success)
|
|
.addFields(
|
|
{ name: '📊 XP', value: `${result.newXP} XP`, inline: true },
|
|
{ name: '⭐ Niveau', value: `${result.newLevel}`, inline: true },
|
|
{ name: '📈 Progression', value: `${progress.current}/${progress.needed} XP (${progress.percentage}%)`, inline: true }
|
|
)
|
|
.setThumbnail(member.user.displayAvatarURL({ dynamic: true }))
|
|
.setTimestamp();
|
|
|
|
// Envoyer dans le canal système (si disponible)
|
|
const systemChannel = guild.systemChannel;
|
|
if (systemChannel) {
|
|
await systemChannel.send({ embeds: [embed] }).catch(() => null);
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('Erreur lors du gain d\'XP vocal:', err);
|
|
}
|
|
}, 10 * 60 * 1000); // 10 minutes
|
|
|
|
voiceUsers.set(key, { joinTime, interval });
|
|
}
|
|
|
|
// Utilisateur quitte un canal vocal
|
|
if (oldState.channelId && !newState.channelId) {
|
|
// L'utilisateur a quitté le canal vocal
|
|
const userData = voiceUsers.get(key);
|
|
if (userData) {
|
|
clearInterval(userData.interval);
|
|
voiceUsers.delete(key);
|
|
|
|
// Calculer le temps passé en vocal et mettre à jour totalVoiceTime
|
|
const timeSpent = Math.floor((Date.now() - userData.joinTime) / 1000 / 60); // en minutes
|
|
if (timeSpent > 0) {
|
|
await db.query(
|
|
'UPDATE user_xp SET totalVoiceTime = totalVoiceTime + ? WHERE userId = ? AND guildId = ?',
|
|
[timeSpent, userId, guildId]
|
|
).catch(() => null);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Utilisateur change de canal vocal
|
|
if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
|
|
// L'utilisateur a changé de canal vocal
|
|
// On récupère les données existantes et on met à jour le joinTime
|
|
const userData = voiceUsers.get(key);
|
|
if (userData) {
|
|
// Mettre à jour le joinTime pour le nouveau canal
|
|
userData.joinTime = Date.now();
|
|
// L'interval continue, pas besoin de le redémarrer
|
|
} else {
|
|
// Si pour une raison quelconque les données n'existent pas, créer un nouvel interval
|
|
// (ce cas ne devrait normalement pas arriver)
|
|
const joinTime = Date.now();
|
|
await db.query(
|
|
'UPDATE user_xp SET lastVoiceJoin = ? WHERE userId = ? AND guildId = ?',
|
|
[joinTime, userId, guildId]
|
|
).catch(() => null);
|
|
|
|
const interval = setInterval(async () => {
|
|
try {
|
|
const guild = newState.guild || oldState.guild;
|
|
if (!guild) {
|
|
clearInterval(interval);
|
|
voiceUsers.delete(key);
|
|
return;
|
|
}
|
|
|
|
const member = await guild.members.fetch(userId).catch(() => null);
|
|
if (!member || !member.voice.channelId) {
|
|
clearInterval(interval);
|
|
voiceUsers.delete(key);
|
|
return;
|
|
}
|
|
|
|
// Vérifier si l'utilisateur est seul (anti-farming ultra strict)
|
|
const voiceChannel = member.voice.channel;
|
|
if (voiceChannel) {
|
|
const membersInChannel = voiceChannel.members.filter(m => !m.user.bot).size;
|
|
const isAlone = membersInChannel === 1;
|
|
|
|
// Si l'utilisateur est seul, ne pas donner d'XP
|
|
if (isAlone) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
const multiplier = getXPMultiplier(member, 'voice');
|
|
const xpGained = Math.floor(Math.random() * 21) + 5;
|
|
const result = await addXP(userId, guildId, xpGained, 'voice', multiplier);
|
|
|
|
if (result) {
|
|
await db.query(
|
|
'UPDATE user_xp SET totalVoiceTime = totalVoiceTime + 10 WHERE userId = ? AND guildId = ?',
|
|
[userId, guildId]
|
|
);
|
|
|
|
if (result.levelUp) {
|
|
const { EmbedBuilder } = require('discord.js');
|
|
const { colors } = require('../utils/constants');
|
|
const { getXPProgress } = require('../functions/xp/xp.js');
|
|
|
|
const progress = getXPProgress(result.newXP, result.newLevel);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('🎉 Level Up !')
|
|
.setDescription(`Félicitations ${member.toString()} ! Tu as atteint le niveau **${result.newLevel}** en vocal !`)
|
|
.setColor(colors.success)
|
|
.addFields(
|
|
{ name: '📊 XP', value: `${result.newXP} XP`, inline: true },
|
|
{ name: '⭐ Niveau', value: `${result.newLevel}`, inline: true },
|
|
{ name: '📈 Progression', value: `${progress.current}/${progress.needed} XP (${progress.percentage}%)`, inline: true }
|
|
)
|
|
.setThumbnail(member.user.displayAvatarURL({ dynamic: true }))
|
|
.setTimestamp();
|
|
|
|
const systemChannel = guild.systemChannel;
|
|
if (systemChannel) {
|
|
await systemChannel.send({ embeds: [embed] }).catch(() => null);
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('Erreur lors du gain d\'XP vocal:', err);
|
|
}
|
|
}, 10 * 60 * 1000);
|
|
|
|
voiceUsers.set(key, { joinTime, interval });
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|