AeThex-Bot-Master/aethex-bot/utils/standaloneXp.js
sirpiglr c2a34f398e Add server mode configuration and dynamic status updates
Introduces a new server mode configuration system (Federation/Standalone) with associated command changes, dynamic status rotation for the bot, and adds new commands and features.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: b08e6ba5-7498-4b9f-b1c9-7dc11b362ddd
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/R9PkDi8
Replit-Helium-Checkpoint-Created: true
2025-12-09 23:26:33 +00:00

230 lines
5.7 KiB
JavaScript

const { EmbedBuilder } = require('discord.js');
const { getEmbedColor } = require('./modeHelper');
async function getStandaloneXp(supabase, discordId, guildId) {
if (!supabase) return null;
try {
const { data } = await supabase
.from('guild_user_xp')
.select('*')
.eq('discord_id', discordId)
.eq('guild_id', guildId)
.maybeSingle();
return data || null;
} catch (e) {
return null;
}
}
async function updateStandaloneXp(supabase, discordId, guildId, xpGain, username) {
if (!supabase) return null;
try {
const { data: existing } = await supabase
.from('guild_user_xp')
.select('*')
.eq('discord_id', discordId)
.eq('guild_id', guildId)
.maybeSingle();
if (existing) {
const newXp = (existing.xp || 0) + xpGain;
const totalEarned = (existing.total_xp_earned || 0) + xpGain;
const { data } = await supabase
.from('guild_user_xp')
.update({
xp: newXp,
total_xp_earned: totalEarned,
updated_at: new Date().toISOString(),
})
.eq('id', existing.id)
.select()
.single();
return data;
} else {
const { data } = await supabase
.from('guild_user_xp')
.insert({
discord_id: discordId,
guild_id: guildId,
username: username,
xp: xpGain,
total_xp_earned: xpGain,
prestige_level: 0,
daily_streak: 0,
})
.select()
.single();
return data;
}
} catch (e) {
console.error('Standalone XP update error:', e.message);
return null;
}
}
async function getStandaloneLeaderboard(supabase, guildId, limit = 10) {
if (!supabase) return [];
try {
const { data } = await supabase
.from('guild_user_xp')
.select('discord_id, username, xp, prestige_level')
.eq('guild_id', guildId)
.order('xp', { ascending: false })
.limit(limit);
return data || [];
} catch (e) {
return [];
}
}
async function claimStandaloneDaily(supabase, discordId, guildId, username) {
if (!supabase) return { success: false, message: 'Database not available' };
try {
const { data: existing } = await supabase
.from('guild_user_xp')
.select('*')
.eq('discord_id', discordId)
.eq('guild_id', guildId)
.maybeSingle();
const now = new Date();
const today = now.toISOString().split('T')[0];
if (existing) {
const lastClaim = existing.last_daily_claim ? existing.last_daily_claim.split('T')[0] : null;
if (lastClaim === today) {
return { success: false, message: 'You already claimed your daily reward today!' };
}
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() - 1);
const yesterdayStr = yesterday.toISOString().split('T')[0];
let newStreak = 1;
if (lastClaim === yesterdayStr) {
newStreak = (existing.daily_streak || 0) + 1;
}
const baseXp = 50;
const streakBonus = Math.min(newStreak * 5, 100);
const totalXp = baseXp + streakBonus;
const newXp = (existing.xp || 0) + totalXp;
const totalEarned = (existing.total_xp_earned || 0) + totalXp;
await supabase
.from('guild_user_xp')
.update({
xp: newXp,
total_xp_earned: totalEarned,
daily_streak: newStreak,
last_daily_claim: now.toISOString(),
updated_at: now.toISOString(),
})
.eq('id', existing.id);
return {
success: true,
xpGained: totalXp,
streak: newStreak,
totalXp: newXp,
};
} else {
const baseXp = 50;
await supabase
.from('guild_user_xp')
.insert({
discord_id: discordId,
guild_id: guildId,
username: username,
xp: baseXp,
total_xp_earned: baseXp,
prestige_level: 0,
daily_streak: 1,
last_daily_claim: now.toISOString(),
});
return {
success: true,
xpGained: baseXp,
streak: 1,
totalXp: baseXp,
};
}
} catch (e) {
console.error('Standalone daily claim error:', e.message);
return { success: false, message: 'An error occurred' };
}
}
async function prestigeStandalone(supabase, discordId, guildId) {
if (!supabase) return { success: false, message: 'Database not available' };
try {
const { data: existing } = await supabase
.from('guild_user_xp')
.select('*')
.eq('discord_id', discordId)
.eq('guild_id', guildId)
.maybeSingle();
if (!existing) {
return { success: false, message: 'No XP data found' };
}
const level = calculateLevel(existing.xp || 0, 'normal');
if (level < 50) {
return { success: false, message: `You need Level 50 to prestige! (Current: Level ${level})` };
}
const newPrestige = (existing.prestige_level || 0) + 1;
await supabase
.from('guild_user_xp')
.update({
xp: 0,
prestige_level: newPrestige,
updated_at: new Date().toISOString(),
})
.eq('id', existing.id);
return {
success: true,
newPrestige: newPrestige,
bonus: newPrestige * 5,
};
} catch (e) {
console.error('Standalone prestige error:', e.message);
return { success: false, message: 'An error occurred' };
}
}
function calculateLevel(xp, curve = 'normal') {
const bases = {
easy: 50,
normal: 100,
hard: 200,
};
const base = bases[curve] || 100;
return Math.floor(Math.sqrt(xp / base));
}
module.exports = {
getStandaloneXp,
updateStandaloneXp,
getStandaloneLeaderboard,
claimStandaloneDaily,
prestigeStandalone,
calculateLevel,
};