Add XP multipliers and booster bonuses to all XP tracking methods

Implement XP multiplier role support and automatic server booster bonuses across message, reaction, and voice XP tracking. Updates `reactionXp.js`, `voiceXp.js`, and `xpTracker.js` to apply these enhancements.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 7b3ac5f3-db6e-42bf-9123-4a2fcade4ca3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/ZjyNKqu
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sirpiglr 2025-12-08 21:15:13 +00:00
parent 49f6c9fe13
commit feb54ff272
3 changed files with 39 additions and 5 deletions

View file

@ -47,13 +47,16 @@ module.exports = {
const receiverOnCooldown = now - lastReceiverXp < cooldownMs || now - lastMessageXp < cooldownMs;
try {
const giverMember = await reaction.message.guild.members.fetch(user.id).catch(() => null);
const receiverMember = await reaction.message.guild.members.fetch(messageAuthor.id).catch(() => null);
if (!giverOnCooldown && giverXp > 0) {
await grantXp(supabase, user.id, giverXp, client);
await grantXp(supabase, user.id, giverXp, client, giverMember, config);
reactionCooldowns.set(cooldownKeyGiver, now);
}
if (!receiverOnCooldown && receiverXp > 0) {
await grantXp(supabase, messageAuthor.id, receiverXp, client);
await grantXp(supabase, messageAuthor.id, receiverXp, client, receiverMember, config);
reactionCooldowns.set(cooldownKeyReceiver, now);
reactionCooldowns.set(cooldownKeyMessage, now);
}
@ -63,7 +66,7 @@ module.exports = {
}
};
async function grantXp(supabase, discordUserId, xpAmount, client) {
async function grantXp(supabase, discordUserId, xpAmount, client, member, config) {
const { data: link, error: linkError } = await supabase
.from('discord_links')
.select('user_id')
@ -80,8 +83,27 @@ async function grantXp(supabase, discordUserId, xpAmount, client) {
if (profileError || !profile) return;
let finalXp = xpAmount;
if (member && config) {
const multiplierRoles = config.multiplier_roles || [];
let highestMultiplier = 1;
for (const mr of multiplierRoles) {
if (member.roles?.cache?.has(mr.role_id)) {
highestMultiplier = Math.max(highestMultiplier, mr.multiplier);
}
}
if (member.premiumSince) {
highestMultiplier = Math.max(highestMultiplier, 1.5);
}
finalXp = Math.floor(xpAmount * highestMultiplier);
}
const currentXp = profile.xp || 0;
const newXp = currentXp + xpAmount;
const newXp = currentXp + finalXp;
const { error: updateError } = await supabase
.from('user_profiles')
@ -91,7 +113,7 @@ async function grantXp(supabase, discordUserId, xpAmount, client) {
if (updateError) return;
if (client.trackXP) {
client.trackXP(xpAmount);
client.trackXP(finalXp);
}
}

View file

@ -164,6 +164,12 @@ async function grantVoiceXp(supabase, client, guildId, userId, config, member, m
highestMultiplier = Math.max(highestMultiplier, mr.multiplier);
}
}
// Server boosters get 1.5x XP bonus automatically
if (member?.premiumSince) {
highestMultiplier = Math.max(highestMultiplier, 1.5);
}
xpGain = Math.floor(xpGain * highestMultiplier);
const currentXp = profile.xp || 0;

View file

@ -63,6 +63,12 @@ module.exports = {
highestMultiplier = Math.max(highestMultiplier, mr.multiplier);
}
}
// Server boosters get 1.5x XP bonus automatically
if (message.member?.premiumSince) {
highestMultiplier = Math.max(highestMultiplier, 1.5);
}
xpGain = Math.floor(xpGain * highestMultiplier);
const currentXp = profile.xp || 0;