Update Bot (j'ai plus le repo sur GitHub)
Qui c'est la conne qui a delete le repo sur GitHub? C'EST MOIIIII
This commit is contained in:
143
events/voiceStateUpdate.js
Normal file
143
events/voiceStateUpdate.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* Gestion de l'XP vocal
|
||||
* Gain d'XP toutes les 10 minutes en vocal (5-25 XP)
|
||||
* - Timer ne démarre QUE si au moins 2 personnes dans le salon
|
||||
* - Timer s'arrête si l'utilisateur est mute/deafen
|
||||
* - totalVoiceTime est incrémenté chaque minute
|
||||
*/
|
||||
|
||||
const { Events, EmbedBuilder } = require('discord.js');
|
||||
const db = require('../functions/database/db.js');
|
||||
const { addXP, getXPMultiplier, getXPProgress } = require('../functions/xp/xp.js');
|
||||
const { colors } = require('../utils/constants');
|
||||
|
||||
// Map<guildId_userId, { xpInterval, timeInterval }>
|
||||
const voiceUsers = new Map();
|
||||
|
||||
function canGainXP(member) {
|
||||
if (!member || !member.voice.channelId) return false;
|
||||
const voiceChannel = member.voice.channel;
|
||||
if (!voiceChannel) return false;
|
||||
|
||||
// Compter les humains
|
||||
const membersInChannel = voiceChannel.members.filter(m => !m.user.bot).size;
|
||||
|
||||
// Conditions : Pas tout seul, pas mute, pas deaf
|
||||
const isAlone = membersInChannel < 2;
|
||||
const isMuted = member.voice.serverMute || member.voice.selfMute;
|
||||
const isDeafened = member.voice.serverDeaf || member.voice.selfDeaf;
|
||||
|
||||
return !isAlone && !isMuted && !isDeafened;
|
||||
}
|
||||
|
||||
async function startTimers(key, member, guildId, userId) {
|
||||
// Si déjà des timers, on ne fait rien
|
||||
if (voiceUsers.has(key)) return;
|
||||
|
||||
// 1. Timer XP (10 min)
|
||||
const xpInterval = setInterval(async () => {
|
||||
try {
|
||||
// Re-vérification dynamique
|
||||
const currentMember = await member.guild.members.fetch(userId).catch(() => null);
|
||||
if (!currentMember || !canGainXP(currentMember)) return;
|
||||
|
||||
const multiplier = getXPMultiplier(currentMember, 'voice');
|
||||
const xpGained = Math.floor(Math.random() * 21) + 5; // 5-25 XP
|
||||
const result = await addXP(userId, guildId, xpGained, 'voice', multiplier);
|
||||
|
||||
if (result && result.levelUp) {
|
||||
const progress = getXPProgress(result.newXP, result.newLevel);
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🎉 Level Up !')
|
||||
.setDescription(`Félicitations ${currentMember.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(currentMember.user.displayAvatarURL({ dynamic: true }))
|
||||
.setTimestamp();
|
||||
|
||||
const systemChannel = member.guild.systemChannel;
|
||||
if (systemChannel) await systemChannel.send({ embeds: [embed] }).catch(() => null);
|
||||
}
|
||||
} catch (err) { console.error('Erreur Timer XP:', err); }
|
||||
}, 10 * 60 * 1000);
|
||||
|
||||
// 2. Timer Temps (1 min)
|
||||
const timeInterval = setInterval(async () => {
|
||||
try {
|
||||
const currentMember = await member.guild.members.fetch(userId).catch(() => null);
|
||||
if (currentMember && canGainXP(currentMember)) {
|
||||
await db.query('UPDATE user_xp SET totalVoiceTime = totalVoiceTime + 1 WHERE userId = ? AND guildId = ?', [userId, guildId]);
|
||||
}
|
||||
} catch (err) { console.error('Erreur Timer Temps:', err); }
|
||||
}, 60 * 1000);
|
||||
|
||||
voiceUsers.set(key, { xpInterval, timeInterval });
|
||||
|
||||
// Mise à jour lastVoiceJoin
|
||||
await db.query('UPDATE user_xp SET lastVoiceJoin = ? WHERE userId = ? AND guildId = ?', [Date.now(), userId, guildId]).catch(() => {});
|
||||
}
|
||||
|
||||
function stopTimers(key) {
|
||||
const userData = voiceUsers.get(key);
|
||||
if (userData) {
|
||||
clearInterval(userData.xpInterval);
|
||||
clearInterval(userData.timeInterval);
|
||||
voiceUsers.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateState(member) {
|
||||
if (!member || member.user.bot) return;
|
||||
|
||||
const guildId = member.guild.id;
|
||||
const userId = member.id;
|
||||
const key = `${guildId}_${userId}`;
|
||||
|
||||
if (canGainXP(member)) {
|
||||
await startTimers(key, member, guildId, userId);
|
||||
} else {
|
||||
stopTimers(key);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkChannel(channel) {
|
||||
if (!channel) return;
|
||||
// Vérifier tous les membres du salon car l'arrivée/départ de quelqu'un change le statut "isAlone"
|
||||
for (const [id, member] of channel.members) {
|
||||
await updateState(member);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
name: Events.VoiceStateUpdate,
|
||||
async execute(oldState, newState) {
|
||||
try {
|
||||
// Cas 1: Join
|
||||
if (!oldState.channelId && newState.channelId) {
|
||||
await checkChannel(newState.channel);
|
||||
}
|
||||
// Cas 2: Leave
|
||||
else if (oldState.channelId && !newState.channelId) {
|
||||
const member = oldState.member;
|
||||
const key = `${member.guild.id}_${member.id}`;
|
||||
stopTimers(key); // Arrêt immédiat pour celui qui part
|
||||
await checkChannel(oldState.channel); // Vérif pour ceux qui restent
|
||||
}
|
||||
// Cas 3: Move
|
||||
else if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
|
||||
await checkChannel(oldState.channel);
|
||||
await checkChannel(newState.channel);
|
||||
}
|
||||
// Cas 4: Mute/Deaf update (Même channel)
|
||||
else if (oldState.channelId === newState.channelId) {
|
||||
await updateState(newState.member);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Erreur VoiceStateUpdate:', err);
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user