Files
AuroraBot-discord/bot/commands/leveling/leaderboard.ts
2026-01-08 16:09:26 +01:00

62 lines
2.3 KiB
TypeScript

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<bigint>`${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] });
}
});