311 lines
12 KiB
JavaScript
311 lines
12 KiB
JavaScript
const { Events } = require('discord.js');
|
|
const db = require('../functions/database/db.js');
|
|
const { addXP, isChannelExcluded, getUserXP, getXPMultiplier } = require('../functions/xp/xp.js');
|
|
|
|
// Fonction pour détecter les bumps (Disboard, etc.)
|
|
async function detectBump(message) {
|
|
// Vérifier si le message vient d'un bot de bump (Disboard, etc.)
|
|
// Disboard a l'ID: 302050872383242240
|
|
// On peut aussi détecter par le nom du bot ou le contenu du message
|
|
const bumpBots = ['302050872383242240']; // Disboard bot ID
|
|
|
|
if (!message.author.bot) return null;
|
|
if (!bumpBots.includes(message.author.id)) return null;
|
|
|
|
// Détecter les messages de bump (Disboard envoie généralement un embed avec "Bump done!")
|
|
const content = message.content?.toLowerCase() || '';
|
|
const hasEmbed = message.embeds.length > 0;
|
|
|
|
// Vérifier si c'est un message de bump
|
|
// Disboard envoie généralement un embed avec "Bump done!" ou similaire
|
|
if (hasEmbed) {
|
|
const embed = message.embeds[0];
|
|
const embedDescription = embed.description?.toLowerCase() || '';
|
|
const embedTitle = embed.title?.toLowerCase() || '';
|
|
|
|
// Mots-clés pour détecter un bump
|
|
const bumpKeywords = ['bump done', 'bump réussi', 'bump réalisé', 'bump effectué', 'serv bump', 'server bump'];
|
|
|
|
const isBumpMessage = bumpKeywords.some(keyword =>
|
|
embedDescription.includes(keyword) ||
|
|
embedTitle.includes(keyword) ||
|
|
content.includes(keyword)
|
|
);
|
|
|
|
if (isBumpMessage) {
|
|
// Chercher l'utilisateur qui a fait le bump dans les mentions ou dans l'embed
|
|
// Disboard mentionne généralement l'utilisateur dans l'embed
|
|
let bumpedUserId = null;
|
|
|
|
// Essayer de trouver l'utilisateur dans les mentions
|
|
if (message.mentions.users.size > 0) {
|
|
bumpedUserId = message.mentions.users.first().id;
|
|
}
|
|
|
|
// Si pas de mention, chercher dans l'embed (format: "User bumped the server!")
|
|
if (!bumpedUserId && embedDescription) {
|
|
// Chercher un ID utilisateur dans l'embed (format: <@userId>)
|
|
const userIdMatch = embedDescription.match(/<@!?(\d+)>/);
|
|
if (userIdMatch) {
|
|
bumpedUserId = userIdMatch[1];
|
|
}
|
|
}
|
|
|
|
// Si toujours pas trouvé, chercher dans le footer ou les fields
|
|
if (!bumpedUserId && embed.footer) {
|
|
const footerMatch = embed.footer.text?.match(/<@!?(\d+)>/);
|
|
if (footerMatch) {
|
|
bumpedUserId = footerMatch[1];
|
|
}
|
|
}
|
|
|
|
return bumpedUserId;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// Fonction pour détecter les messages de bienvenue
|
|
function detectWelcomeMessage(message) {
|
|
// Ignorer les bots
|
|
if (message.author.bot) return false;
|
|
|
|
// Mots-clés pour détecter les messages de bienvenue
|
|
const welcomeKeywords = ['bienvenue', 'welcome', 'bvn', 'salut', 'hey', 'bonjour'];
|
|
const content = message.content.toLowerCase();
|
|
|
|
// Vérifier si le message contient un mot de bienvenue
|
|
const hasWelcomeKeyword = welcomeKeywords.some(keyword => content.includes(keyword));
|
|
|
|
// Vérifier si le message mentionne un utilisateur (généralement pour accueillir quelqu'un)
|
|
const hasMention = message.mentions.users.size > 0;
|
|
|
|
// Vérifier si le message est assez court (pour éviter les faux positifs)
|
|
const isShortMessage = message.content.length < 100;
|
|
|
|
return hasWelcomeKeyword && hasMention && isShortMessage;
|
|
}
|
|
|
|
module.exports = {
|
|
name: Events.MessageCreate,
|
|
async execute(message) {
|
|
// Ignorer les messages qui ne sont pas dans un canal de texte
|
|
if (!message.channel.isTextBased() || message.channel.isDMBased()) return;
|
|
|
|
try {
|
|
// Détecter les bumps (AVANT d'ignorer les bots, car Disboard est un bot)
|
|
const bumpedUserId = await detectBump(message);
|
|
if (bumpedUserId) {
|
|
try {
|
|
// Enregistrer le bump dans la DB
|
|
await db.query(
|
|
'INSERT INTO bumps (userId, guildId, bumpTime, reminderSent) VALUES (?, ?, ?, ?)',
|
|
[bumpedUserId, message.guild.id, Date.now(), false]
|
|
);
|
|
|
|
// Donner de l'XP pour le bump
|
|
const member = await message.guild.members.fetch(bumpedUserId).catch(() => null);
|
|
if (member) {
|
|
const multiplier = getXPMultiplier(member);
|
|
// Gain d'XP pour bump : 50-100 XP (plus que les messages normaux)
|
|
const xpGained = Math.floor(Math.random() * 51) + 50; // 50-100 XP
|
|
const result = await addXP(bumpedUserId, message.guild.id, xpGained, 'bump', multiplier);
|
|
|
|
if (result && 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}** !`)
|
|
.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();
|
|
|
|
await message.channel.send({ embeds: [embed] });
|
|
}
|
|
}
|
|
|
|
// Le reminder sera géré automatiquement par bumpReminder.js (vérifie toutes les minutes)
|
|
// Pas besoin de setTimeout ici, le système de reminder s'en occupe
|
|
|
|
} catch (err) {
|
|
console.error('Erreur lors de la détection du bump:', err);
|
|
}
|
|
|
|
// Ne pas continuer le traitement pour les messages de bump
|
|
return;
|
|
}
|
|
|
|
// Ignorer les messages du bot (après la détection des bumps)
|
|
if (message.author.bot) return;
|
|
// Vérifier si ce canal est un ticket (logique existante pour les tickets)
|
|
const [tickets] = await db.query(
|
|
'SELECT * FROM tickets WHERE channelId = ? AND status = ?',
|
|
[message.channel.id, 'Ouvert']
|
|
);
|
|
|
|
if (tickets.length > 0) {
|
|
// C'est un ticket, traiter la logique des tickets
|
|
const ticket = tickets[0];
|
|
|
|
// Enregistrer le message dans la DB
|
|
const attachments = message.attachments.size > 0
|
|
? message.attachments.map(a => a.url).join(', ')
|
|
: null;
|
|
|
|
// Troncature des champs pour respecter les limites SQL
|
|
const maxTag = 100;
|
|
const maxText = 65535;
|
|
const safeUserTag = (message.author.tag && message.author.tag.length > maxTag) ? message.author.tag.substring(0, maxTag) : message.author.tag;
|
|
const safeContent = (message.content && message.content.length > maxText) ? message.content.substring(0, maxText) : message.content;
|
|
const safeAttachments = (attachments && attachments.length > maxText) ? attachments.substring(0, maxText) : attachments;
|
|
await db.query(
|
|
`INSERT INTO ticket_messages (ticketId, messageId, userId, userTag, content, attachments, timestamp)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
ticket.ticketId,
|
|
message.id,
|
|
message.author.id,
|
|
safeUserTag,
|
|
safeContent || null,
|
|
safeAttachments,
|
|
message.createdTimestamp
|
|
]
|
|
);
|
|
|
|
|
|
// Ne pas donner d'XP dans les tickets
|
|
return;
|
|
}
|
|
|
|
// Système XP : Gagner de l'XP pour les messages (pas dans les tickets)
|
|
// Vérifier si le salon est exclus de l'XP
|
|
const excluded = await isChannelExcluded(message.channel.id, message.guild.id);
|
|
|
|
if (!excluded) {
|
|
// Récupérer les données de l'utilisateur
|
|
const userXP = await getUserXP(message.author.id, message.guild.id);
|
|
|
|
// Cooldown : 15 secondes entre chaque gain d'XP par message
|
|
const cooldown = 15 * 1000; // 15 secondes
|
|
const now = Date.now();
|
|
|
|
// Convertir lastMessageTime en nombre (peut être string depuis la DB)
|
|
let lastMessageTime = 0;
|
|
if (userXP.lastMessageTime) {
|
|
lastMessageTime = parseInt(userXP.lastMessageTime, 10);
|
|
// Si lastMessageTime est dans le futur (erreur de données) ou trop ancien (plus de 1 an), on le réinitialise
|
|
if (lastMessageTime > now || lastMessageTime < (now - 365 * 24 * 60 * 60 * 1000)) {
|
|
lastMessageTime = 0;
|
|
}
|
|
}
|
|
|
|
const timeSinceLastMessage = now - lastMessageTime;
|
|
|
|
// Si lastMessageTime est 0 (premier message) ou si le cooldown est passé
|
|
if (lastMessageTime === 0 || timeSinceLastMessage >= cooldown) {
|
|
// Récupérer le membre pour calculer le multiplicateur
|
|
const member = await message.guild.members.fetch(message.author.id).catch(() => null);
|
|
const multiplier = member ? getXPMultiplier(member) : 1.0;
|
|
|
|
// Gain d'XP : 15-25 XP aléatoire par message
|
|
const xpGained = Math.floor(Math.random() * 11) + 15; // 15-25 XP
|
|
|
|
// Ajouter l'XP
|
|
const result = await addXP(message.author.id, message.guild.id, xpGained, 'message', multiplier);
|
|
|
|
if (result && result.levelUp) {
|
|
// Niveau supérieur atteint !
|
|
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 ${message.author.toString()} ! Tu as atteint le niveau **${result.newLevel}** !`)
|
|
.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(message.author.displayAvatarURL({ dynamic: true }))
|
|
.setTimestamp();
|
|
|
|
await message.channel.send({ embeds: [embed] });
|
|
}
|
|
|
|
// Mettre à jour lastMessageTime et totalMessages (AVANT le gain d'XP pour éviter les problèmes)
|
|
await db.query(
|
|
'UPDATE user_xp SET lastMessageTime = ?, totalMessages = totalMessages + 1 WHERE userId = ? AND guildId = ?',
|
|
[now, message.author.id, message.guild.id]
|
|
);
|
|
} else {
|
|
// Cooldown actif, mettre à jour seulement totalMessages (sans XP)
|
|
await db.query(
|
|
'UPDATE user_xp SET totalMessages = totalMessages + 1 WHERE userId = ? AND guildId = ?',
|
|
[message.author.id, message.guild.id]
|
|
);
|
|
}
|
|
}
|
|
|
|
// Détecter les messages de bienvenue
|
|
if (detectWelcomeMessage(message)) {
|
|
try {
|
|
// Réagir avec un emoji de bienvenue
|
|
await message.react('👋').catch(() => null);
|
|
await message.react('🎉').catch(() => null);
|
|
|
|
// Donner de l'XP pour avoir dit bienvenue
|
|
const member = await message.guild.members.fetch(message.author.id).catch(() => null);
|
|
if (member) {
|
|
const multiplier = getXPMultiplier(member);
|
|
// Gain d'XP pour bienvenue : 20-40 XP
|
|
const xpGained = Math.floor(Math.random() * 21) + 20; // 20-40 XP
|
|
const result = await addXP(message.author.id, message.guild.id, xpGained, 'welcome', multiplier);
|
|
|
|
if (result && 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 ${message.author.toString()} ! Tu as atteint le niveau **${result.newLevel}** !`)
|
|
.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(message.author.displayAvatarURL({ dynamic: true }))
|
|
.setTimestamp();
|
|
|
|
await message.channel.send({ embeds: [embed] });
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error('Erreur lors de la détection du message de bienvenue:', err);
|
|
}
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error('Erreur lors de l\'enregistrement du message:', err);
|
|
}
|
|
},
|
|
};
|