diff --git a/src/commands/leaderboard.ts b/src/commands/leaderboard.ts index bcb0b8b..428c28c 100644 --- a/src/commands/leaderboard.ts +++ b/src/commands/leaderboard.ts @@ -22,40 +22,9 @@ export default new app.Command({ const ladders = [ app.ratingLadder(guild._id), - app.pointLadder, app.activeLadder(guild._id), - new app.Ladder<{ rank: number; coins: number; user_id: string }>({ - title: "Coins", - fetchLineCount() { - return userTable.count('"coins" > 0') - }, - async fetchLines(options) { - return userTable.query - .select( - "coins", - app.database.raw('rank() over (order by coins desc) as "rank"'), - "id as user_id", - ) - .where("coins", ">", 0) - .limit(options.pageLineCount) - .offset(options.pageIndex * options.pageLineCount) - .then( - (rows) => - rows as unknown as { - rank: number - coins: number - user_id: string - }[], - ) - }, - formatLine(line, _, lines) { - return `${app.formatRank(line.rank)} \`${app.forceTextSize( - line.coins, - Math.max(...lines.map((l) => String(l.coins).length)), - true, - )}\` coins - ${app.userMention(line.user_id)}` - }, - }), + app.pointLadder, + app.coinLadder, ] return message.channel.send({ diff --git a/src/namespaces/active.ts b/src/namespaces/active.ts index fd26f99..83bacf9 100644 --- a/src/namespaces/active.ts +++ b/src/namespaces/active.ts @@ -211,7 +211,7 @@ export interface ActiveLadderLine { export const activeLadder = (guild_id: number) => new app.Ladder({ - title: "Activity", + title: "Guild's activity", fetchLines(options) { return message.query .select( diff --git a/src/namespaces/coins.ts b/src/namespaces/coins.ts index 80d3fc9..5ccaed2 100644 --- a/src/namespaces/coins.ts +++ b/src/namespaces/coins.ts @@ -1,11 +1,46 @@ +import * as app from "#app" + import userTable from "#tables/user.ts" import guildTable from "#tables/guild.ts" import pointTable from "#tables/point.ts" import noteTable from "#tables/rating.ts" import messageTable from "#tables/message.ts" import activeTable from "#tables/active.ts" + import { ResponseCache } from "#database" +export type CoinLadderLine = { + rank: number + coins: number + user_id: string +} + +export const coinLadder = new app.Ladder({ + title: "Wealthiest members", + fetchLineCount() { + return userTable.count('"coins" > 0') + }, + async fetchLines(options) { + return userTable.query + .select( + "coins", + app.database.raw('rank() over (order by coins desc) as "rank"'), + "id as user_id", + ) + .where("coins", ">", 0) + .limit(options.pageLineCount) + .offset(options.pageIndex * options.pageLineCount) + .then((rows) => rows as unknown as CoinLadderLine[]) + }, + formatLine(line, _, lines) { + return `${app.formatRank(line.rank)} \`${app.forceTextSize( + line.coins, + Math.max(...lines.map((l) => String(l.coins).length)), + true, + )}🪙\` - ${app.userMention(line.user_id)}` + }, +}) + export interface FullUser { _id: number id: string diff --git a/src/namespaces/point.ts b/src/namespaces/point.ts index 2940803..a400318 100644 --- a/src/namespaces/point.ts +++ b/src/namespaces/point.ts @@ -14,7 +14,7 @@ export interface PointLadderLine { } export const pointLadder = new app.Ladder({ - title: "Helpers", + title: "Global helper scoreboard", async fetchLines(options) { return point.query .select([ @@ -50,7 +50,7 @@ export const pointLadder = new app.Ladder({ }) export async function getPointRank(user: app.User): Promise<{ rank: string }> { - const result = await point.query + const subquery = point.query .select([ "user.id", app.database.raw( @@ -59,9 +59,15 @@ export async function getPointRank(user: app.User): Promise<{ rank: string }> { ]) .leftJoin("user", "point.to_id", "user._id") .groupBy("user.id") - .having("user.id", "=", user.id) + + const result = await app.database.database + .select("rank") + .from(subquery.as("ranked_users")) + .where("id", user.id) .first() + if (!result) return { rank: "N/A" } + return { rank: result.rank } } diff --git a/src/namespaces/rating.ts b/src/namespaces/rating.ts index 4ba24cb..f7a3d96 100644 --- a/src/namespaces/rating.ts +++ b/src/namespaces/rating.ts @@ -28,7 +28,7 @@ export function renderRatingLine(value: number, count: number) { export const ratingLadder = (guild_id?: number) => new app.Ladder({ - title: guild_id ? "Guild rating" : "Global rating", + title: guild_id ? "Guild's members rating" : "Global users rating", async fetchLines(options) { const query = table.query .count({ rating_count: "from_id" }) diff --git a/src/slash/buy.ts b/src/slash/buy.ts index a9d4191..1c0061e 100644 --- a/src/slash/buy.ts +++ b/src/slash/buy.ts @@ -45,7 +45,7 @@ export default new app.SlashCommand({ if (subcommand === "rename") { if (user.coins < prices.rename) { return interaction.reply({ - content: `You don't have enough coins to buy this. You need **${prices.rename}** coins. (You have **${user.coins}** coins)`, + content: `You don't have enough coins to buy this. You need **${prices.rename}** coins. (You have **${user.coins}** 🪙)`, ephemeral: true, }) } diff --git a/src/slash/profile.ts b/src/slash/profile.ts index f537c3e..4d4cf8a 100644 --- a/src/slash/profile.ts +++ b/src/slash/profile.ts @@ -23,6 +23,27 @@ export default new app.SlashCommand({ `author_id = ${user._id} AND guild_id = ${guild._id}`, ) + const member = await interaction.guild.members.fetch(interaction.user.id) + + const prestigeRoles = new Set() + + const highest = member.roles.cache + .sorted((a, b) => b.position - a.position) + .first() + + if (highest) prestigeRoles.add(highest.id) + + if (guild.active_role_id && user.active) + prestigeRoles.add(guild.active_role_id) + + if (guild.elders_role_pattern) { + const id = member.roles.cache + .sorted((a, b) => b.position - a.position) + .findKey((role) => role.name.includes(guild.elders_role_pattern!)) + + if (id) prestigeRoles.add(id) + } + return interaction.reply({ embeds: [ new app.EmbedBuilder() @@ -34,7 +55,8 @@ export default new app.SlashCommand({ : "") + `Total money: **${user.coins.toLocaleString()}** 🪙\n` + `Hourly money: **${Math.floor(app.getUserHourlyCoins(user)).toLocaleString()}** 🪙\n` + - `Messages sent: **${messagesSent.toLocaleString()}**`, + `Messages sent: **${messagesSent.toLocaleString()}**\n` + + `Rating sent: **${user.rateOthers}**`, ) .setFields( { @@ -45,9 +67,9 @@ export default new app.SlashCommand({ { name: "Prestige", value: - user.active && guild.active_role_id - ? app.roleMention(guild.active_role_id) - : "`nope`", + prestigeRoles.size === 0 + ? "`nope`" + : [...prestigeRoles].map(app.roleMention).join("\n"), inline: true, }, ),