diff --git a/app/bot.js b/app/bot.js index 7791ce6..dc35da8 100644 --- a/app/bot.js +++ b/app/bot.js @@ -4,10 +4,11 @@ loadSlashCommands(); const db = require("./db"); const { Client, GatewayIntentBits, ActivityType, Events } = require("discord.js"); +const e = require('express'); const client = new Client({ intents: Object.values(GatewayIntentBits) }); -client.once("clientReady", () => { +client.once(Events.ClientReady, () => { console.log(`Bot connecté en tant que ${client.user.tag}`); client.user.setActivity("LazyBot à votre service !", { type: ActivityType.Custom }); }); @@ -115,6 +116,139 @@ client.on(Events.VoiceStateUpdate, (oldState, newState) => { ); }); + +client.on(Events.MessageCreate, message => { + if (message.author.bot) return; + + const guildId = message.guild.id; + + db.get( + `SELECT + enabled, + level_announcements_enabled, + level_announcements_channel_id, + level_announcements_message, + xp_courbe_type, + multiplier_courbe_for_level, + level_annoncement_every_level, + level_max, + role_with_without_type, + role_with_without_xp, + salon_with_without_type, + salon_with_without_xp, + gain_xp_on_message, + gain_xp_message_lower_bound, + gain_xp_message_upper_bound, + cooldown_xp_message_seconds + FROM levels_config WHERE guild_id = ?`, + [guildId], + (err, row) => { + if (err || !row || !row.enabled || !row.gain_xp_on_message) return; + if (row.role_with_without_type === "with") { + const userRoles = message.member.roles.cache; + const requiredRoles = JSON.parse(row.role_with_without_xp || "[]"); + if (!requiredRoles.some(roleId => userRoles.has(roleId))) { + return; // User has an excluded role + } + } else if (row.role_with_without_type === "without") { + const userRoles = message.member.roles.cache; + const excludedRoles = JSON.parse(row.role_with_without_xp || "[]"); + if (excludedRoles.some(roleId => userRoles.has(roleId))) { + return; // User does not have any of the required roles + } + } else if (row.salon_with_without_type === "with") { + const channelId = message.channel.id; + const requiredChannels = JSON.parse(row.salon_with_without_xp || "[]"); + if (!requiredChannels.includes(channelId)) { + return; // Message not in a required channel + } + } else if (row.salon_with_without_type === "without") { + const channelId = message.channel.id; + const excludedChannels = JSON.parse(row.salon_with_without_xp || "[]"); + if (excludedChannels.includes(channelId)) { + return; // Message in an excluded channel + } + } + // Logic to award XP for message goes here + const now = Date.now(); + db.get( + `SELECT xp, level, last_xp_message_timestamp FROM user_levels WHERE guild_id = ? AND user_id = ?`, + [guildId, message.author.id], + (err, userRow) => { + if (err) return; + + const lastTimestamp = userRow ? userRow.last_xp_message_timestamp || 0 : 0; + if (now - lastTimestamp < row.cooldown_xp_message_seconds * 1000) { + return; // Still in cooldown + } + + const minXp = row.gain_xp_message_lower_bound; + const maxXp = row.gain_xp_message_upper_bound; + const xpToAdd = Math.floor(Math.random() * (maxXp - minXp + 1)) + minXp; + + let newXp; + let newLevel; + + if (userRow) { + newXp = userRow.xp + xpToAdd; + newLevel = userRow.level; + } else { + newXp = xpToAdd; + newLevel = 1; + } + + // Level up logic based on xp_courbe_type and multiplier goes here + const firstLevelXp = 100; // Example base XP for first level ---------------------------------------- + const multiplier = row.multiplier_courbe_for_level; + let fonction_courbe; + + if (row.xp_courbe_type === "constante") { + fonction_courbe = (level) => firstLevelXp * multiplier; + } else if (row.xp_courbe_type === "linear") { + fonction_courbe = (level) => firstLevelXp * (level) * multiplier; + } else if (row.xp_courbe_type === "quadratic") { + fonction_courbe = (level) => firstLevelXp * (level) * (level) * multiplier; + } else if (row.xp_courbe_type === "exponential") { + fonction_courbe = (level) => firstLevelXp * Math.pow(2, (level - 1)) * multiplier; + } + + let xpForNextLevel = fonction_courbe(newLevel); + while (newXp >= xpForNextLevel && (row.level_max === 0 || newLevel < row.level_max)) { + newXp -= xpForNextLevel; + newLevel += 1; + xpForNextLevel = fonction_courbe(newLevel); + + // Announce level up if enabled and meets the criteria + if (row.level_announcements_enabled && (newLevel % row.level_annoncement_every_level === 0)) { + const channel = message.guild.channels.cache.get(row.level_announcements_channel_id); + console.log("Channel for level announcement:", channel); + if (channel) { + let announcementMsg = row.level_announcements_message; + announcementMsg = announcementMsg + .replace("{user}", message.author.username) + .replace("{mention}", `<@${message.author.id}>`) + .replace("{level}", newLevel) + .replace("{level-xp}", xpForNextLevel); + channel.send(announcementMsg); + } + } + } + + db.run( + `INSERT INTO user_levels (guild_id, user_id, xp, level, last_xp_message_timestamp) + VALUES (?, ?, ?, ?, ?) + ON CONFLICT(guild_id, user_id) DO UPDATE SET + xp = excluded.xp, + level = excluded.level, + last_xp_message_timestamp = excluded.last_xp_message_timestamp`, + [guildId, message.author.id, newXp, newLevel, now] + ); + } + ); + } + ); +}); + client.login(process.env.BOT_TOKEN); module.exports = client; diff --git a/app/db.js b/app/db.js index f3323e4..ae3816d 100644 --- a/app/db.js +++ b/app/db.js @@ -37,6 +37,38 @@ db.exec(` exclude_channel_ids TEXT, enabled INTEGER NOT NULL ); + + CREATE TABLE IF NOT EXISTS levels_config ( + guild_id TEXT PRIMARY KEY, + enabled INTEGER NOT NULL, + level_announcements_enabled INTEGER NOT NULL, + level_announcements_channel_id TEXT, + level_announcements_message TEXT NOT NULL, + xp_courbe_type TEXT NOT NULL, + multiplier_courbe_for_level INTEGER NOT NULL, + level_annoncement_every_level INTEGER NOT NULL, + level_max INTEGER NOT NULL, + role_with_without_type TEXT NOT NULL, + role_with_without_xp TEXT NOT NULL, + salon_with_without_type TEXT NOT NULL, + salon_with_without_xp TEXT NOT NULL, + gain_xp_on_message INTEGER NOT NULL, + gain_xp_message_lower_bound INTEGER NOT NULL, + gain_xp_message_upper_bound INTEGER NOT NULL, + cooldown_xp_message_seconds INTEGER NOT NULL, + gain_xp_on_voice INTEGER NOT NULL, + gain_voice_xp_lower_bound INTEGER NOT NULL, + gain_voice_xp_upper_bound INTEGER NOT NULL + ); + + CREATE TABLE IF NOT EXISTS user_levels ( + guild_id TEXT NOT NULL, + user_id TEXT NOT NULL, + xp INTEGER NOT NULL, + level INTEGER NOT NULL, + last_xp_message_timestamp INTEGER, + PRIMARY KEY (guild_id, user_id) + ); `); module.exports = db; diff --git a/app/public/guild.html b/app/public/guild.html index 7e16abe..c1a9088 100644 --- a/app/public/guild.html +++ b/app/public/guild.html @@ -131,213 +131,145 @@
+ + + - + + + + + +