Introduce several new slash commands including ban, kick, timeout, and userinfo. Enhance existing commands like config and rank with new features and configurations. Add new listeners for welcome and goodbye messages. Implement XP tracking for user leveling and integrate it with role rewards. Update documentation to reflect these changes. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 1be8d824-5029-4875-bed8-0bd1d810892d Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/SQxsvtx Replit-Helium-Checkpoint-Created: true
86 lines
3.1 KiB
JavaScript
86 lines
3.1 KiB
JavaScript
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('rank')
|
|
.setDescription('View your unified level and XP across all platforms')
|
|
.addUserOption(option =>
|
|
option.setName('user')
|
|
.setDescription('User to check (defaults to yourself)')
|
|
.setRequired(false)
|
|
),
|
|
|
|
async execute(interaction, supabase, client) {
|
|
if (!supabase) {
|
|
return interaction.reply({ content: 'Database not configured.', ephemeral: true });
|
|
}
|
|
|
|
const target = interaction.options.getUser('user') || interaction.user;
|
|
await interaction.deferReply();
|
|
|
|
try {
|
|
const { data: link } = await supabase
|
|
.from('discord_links')
|
|
.select('user_id, primary_arm')
|
|
.eq('discord_id', target.id)
|
|
.single();
|
|
|
|
if (!link) {
|
|
return interaction.editReply({
|
|
embeds: [
|
|
new EmbedBuilder()
|
|
.setColor(0xff6b6b)
|
|
.setDescription(`${target.id === interaction.user.id ? 'You are' : `${target.tag} is`} not linked to AeThex. Use \`/verify\` to link your account.`)
|
|
]
|
|
});
|
|
}
|
|
|
|
const { data: profile } = await supabase
|
|
.from('user_profiles')
|
|
.select('username, avatar_url, xp, bio')
|
|
.eq('id', link.user_id)
|
|
.single();
|
|
|
|
const xp = profile?.xp || 0;
|
|
const level = Math.floor(Math.sqrt(xp / 100));
|
|
const currentLevelXp = level * level * 100;
|
|
const nextLevelXp = (level + 1) * (level + 1) * 100;
|
|
const progress = xp - currentLevelXp;
|
|
const needed = nextLevelXp - currentLevelXp;
|
|
const progressPercent = Math.floor((progress / needed) * 100);
|
|
|
|
const progressBar = createProgressBar(progressPercent);
|
|
|
|
const { count: rankPosition } = await supabase
|
|
.from('user_profiles')
|
|
.select('*', { count: 'exact', head: true })
|
|
.gt('xp', xp);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setColor(0x7c3aed)
|
|
.setTitle(`${profile?.username || target.tag}'s Rank`)
|
|
.setThumbnail(profile?.avatar_url || target.displayAvatarURL())
|
|
.addFields(
|
|
{ name: 'Level', value: `**${level}**`, inline: true },
|
|
{ name: 'Total XP', value: `**${xp.toLocaleString()}**`, inline: true },
|
|
{ name: 'Rank', value: `#${(rankPosition || 0) + 1}`, inline: true },
|
|
{ name: 'Progress to Next Level', value: `${progressBar}\n${progress.toLocaleString()} / ${needed.toLocaleString()} XP (${progressPercent}%)` },
|
|
{ name: 'Primary Realm', value: link.primary_arm || 'None set', inline: true }
|
|
)
|
|
.setFooter({ text: 'XP earned across Discord & AeThex platforms' })
|
|
.setTimestamp();
|
|
|
|
await interaction.editReply({ embeds: [embed] });
|
|
|
|
} catch (error) {
|
|
console.error('Rank error:', error);
|
|
await interaction.editReply({ content: 'Failed to fetch rank data.' });
|
|
}
|
|
},
|
|
};
|
|
|
|
function createProgressBar(percent) {
|
|
const filled = Math.floor(percent / 10);
|
|
const empty = 10 - filled;
|
|
return '█'.repeat(filled) + '░'.repeat(empty);
|
|
}
|