69 lines
1.9 KiB
JavaScript
69 lines
1.9 KiB
JavaScript
import { SlashCommandBuilder, EmbedBuilder } from 'discord.js';
|
|
import { withConn } from '../db/pool.js';
|
|
|
|
export const data = new SlashCommandBuilder()
|
|
.setName('profile')
|
|
.setDescription('Show XP profile')
|
|
.addUserOption(o =>
|
|
o.setName('user').setDescription('User to view')
|
|
);
|
|
|
|
export async function execute(interaction) {
|
|
if (!interaction.guildId)
|
|
return interaction.reply({
|
|
content: 'Guild only command.',
|
|
ephemeral: true,
|
|
});
|
|
|
|
const target = interaction.options.getUser('user') || interaction.user;
|
|
|
|
const data = await withConn(async conn => {
|
|
const rows = await conn.query(
|
|
'SELECT xp FROM user_xp WHERE guild_id = ? AND user_id = ? LIMIT 1',
|
|
[BigInt(interaction.guildId), BigInt(target.id)]
|
|
);
|
|
|
|
const xp = Number(rows[0]?.xp ?? 0);
|
|
|
|
const rankRows = await conn.query(
|
|
'SELECT COUNT(*) AS ahead FROM user_xp WHERE guild_id = ? AND xp > ?',
|
|
[BigInt(interaction.guildId), xp]
|
|
);
|
|
|
|
const rank = Number(rankRows[0]?.ahead ?? 0) + 1;
|
|
|
|
return { xp, rank };
|
|
});
|
|
|
|
const XP_PER_LEVEL = 500; // match visual example
|
|
const level = Math.floor(data.xp / XP_PER_LEVEL);
|
|
const currentLevelXp = data.xp % XP_PER_LEVEL;
|
|
const progress = Math.min(
|
|
100,
|
|
Math.round((currentLevelXp / XP_PER_LEVEL) * 1000) / 10
|
|
);
|
|
|
|
const embed = new EmbedBuilder()
|
|
.setAuthor({
|
|
name: `${target.username}'s Profile`,
|
|
iconURL: target.displayAvatarURL(),
|
|
})
|
|
.setColor(0x5865f2)
|
|
.setDescription(`Progress to next level: **${progress}%**`)
|
|
.addFields(
|
|
{ name: '🏅 Level', value: `${level}`, inline: true },
|
|
{ name: '💎 XP', value: `${currentLevelXp} / ${XP_PER_LEVEL}`, inline: true },
|
|
{ name: '🏆 Rank', value: `#${data.rank}`, inline: true }
|
|
)
|
|
.setFooter({
|
|
text: `Server: ${interaction.guild?.name || 'Unknown'}`,
|
|
})
|
|
.setTimestamp();
|
|
|
|
await interaction.reply({
|
|
embeds: [embed],
|
|
allowedMentions: { parse: [] },
|
|
});
|
|
}
|
|
|