import { createCommand } from "@shared/lib/utils"; import { SlashCommandBuilder } from "discord.js"; import { DrizzleClient } from "@shared/db/DrizzleClient"; import { users, items, inventory } from "@db/schema"; import { desc, sql, eq } from "drizzle-orm"; import { createWarningEmbed } from "@lib/embeds"; import { getLeaderboardEmbed } from "@/modules/leveling/leveling.view"; export const leaderboard = createCommand({ data: new SlashCommandBuilder() .setName("leaderboard") .setDescription("View the top players") .addStringOption(option => option.setName("type") .setDescription("Sort by XP, Balance, or Net Worth") .setRequired(true) .addChoices( { name: "Level / XP", value: "xp" }, { name: "Balance", value: "balance" }, { name: "Net Worth", value: "networth" } ) ), execute: async (interaction) => { await interaction.deferReply(); const type = interaction.options.getString("type", true); let leaders; if (type === 'networth') { leaders = await DrizzleClient.select({ username: users.username, level: users.level, xp: users.xp, balance: users.balance, netWorth: sql`${users.balance} + COALESCE(SUM(${items.price} * ${inventory.quantity}), 0)`.as('net_worth') }) .from(users) .leftJoin(inventory, eq(users.id, inventory.userId)) .leftJoin(items, eq(inventory.itemId, items.id)) .groupBy(users.id) .orderBy(desc(sql`net_worth`)) .limit(10); } else { const isXp = type === "xp"; leaders = await DrizzleClient.query.users.findMany({ orderBy: isXp ? desc(users.xp) : desc(users.balance), limit: 10 }); } if (leaders.length === 0) { await interaction.editReply({ embeds: [createWarningEmbed("No users found.", "Leaderboard")] }); return; } const embed = getLeaderboardEmbed(leaders, type as 'xp' | 'balance' | 'networth'); await interaction.editReply({ embeds: [embed] }); } });