import { SlashCommandSubcommandBuilder } from "discord.js" import { devMessage, embedColor } from "~/config/options" import { IGuildData, SubCommand } from "~/typings" import { numberFormatter } from "~/utils/Functions/intlFormaters" import { getGuild, getIGN, getPlayer, getUUID } from "~/utils/Hypixel" import { redis } from "~/utils/Illegitimate" export const topSub = new SlashCommandSubcommandBuilder() .setName("top") .setDescription("Get the top guild members based on gexp") .addStringOption(option => option .setName("query") .setDescription("The query to search for. [Default: player]") .setRequired(true) ) .addStringOption(option => option .setName("type") .setDescription("The type of query.") .addChoices( { name: "Guild Member", value: "ign" }, { name: "Guild Name", value: "name" }, { name: "Guild Id", value: "id" } ) ) .addNumberOption(option => option .setName("amount") .setDescription("The amount of guild members to show. [Default: 10]") ) const cmd: SubCommand = async ({ interaction }) => { await interaction.deferReply() const query = interaction.options.getString("query")! const type = interaction.options.getString("type") || "ign" let amount = interaction.options.getNumber("amount") || 10 let guild: IGuildData | null if (type === "ign") { await interaction.editReply({ embeds: [{ description: "Fetching your uuid...", color: embedColor }] }) const uuid = await getUUID(query) if (!uuid) { interaction.editReply({ embeds: [{ description: " That player does not exist.", color: embedColor }] }) return } await interaction.editReply({ embeds: [{ description: "Fetching your player data...", color: embedColor }] }) const player = await getPlayer(uuid) if (!player) { interaction.editReply({ embeds: [{ description: " That player hasn't played Hypixel before.", color: embedColor }] }) return } await interaction.editReply({ embeds: [{ description: "Fetching your guild data...", color: embedColor }] }) guild = await getGuild(uuid, "player") if (!guild) { interaction.editReply({ embeds: [{ description: "That player is not in a guild!", color: embedColor }] }) return } } else if (type === "name") { await interaction.editReply({ embeds: [{ description: "Fetching your guild data...", color: embedColor }] }) guild = await getGuild(query, "name") if (!guild) { interaction.editReply({ embeds: [{ description: "That guild doesn't exist!", color: embedColor }] }) return } } else if (type === "id") { await interaction.editReply({ embeds: [{ description: "Fetching your guild data...", color: embedColor }] }) guild = await getGuild(query, "id") if (!guild) { interaction.editReply({ embeds: [{ description: "That guild doesn't exist!", color: embedColor }] }) return } } const guildName = guild!.name const guildMembers = guild!.members const guildId = guild!._id const cachedData = await redis.get("guildTop+" + guildId) const gexpTodayUnformatted = guildMembers.map(member => { return member.expHistory[Object.keys(member.expHistory)[0]] }).reduce((a, b) => a + b, 0) const gexpToday = numberFormatter(gexpTodayUnformatted) const averageGuildMemberGEXPUnformatted = Math.floor(gexpTodayUnformatted / guildMembers.length) const averageGuildMemberGEXP = numberFormatter(averageGuildMemberGEXPUnformatted) const allMembersDailyGEXP = guildMembers.map(member => { return { uuid: member.uuid, gexp: member.expHistory[Object.keys(member.expHistory)[0]] } }) if (amount > guildMembers.length) { amount = guildMembers.length } if (amount < 1) { amount = 1 } type GuildTopData = { ign: string, uuid: string }[] type NewList = { name: string, value: string, inline: boolean }[] let cacheStatus: boolean let guildData: GuildTopData = [] const fieldsValueRaw: string[] = [] const allMembersSorted = allMembersDailyGEXP.sort((a, b) => b.gexp - a.gexp) const allMembersSortedUUIDArray = allMembersSorted.map(member => member.uuid) if (!cachedData) { cacheStatus = false await interaction.editReply({ embeds: [{ description: "Fetching the top " + amount + " members of " + guildName + "...", color: embedColor }] }) for (let i = 0; i < allMembersSortedUUIDArray.length; i++) { const uuid = allMembersSortedUUIDArray[i] const ign = await getIGN(uuid) guildData.push({ ign: ign!, uuid: uuid }) } await redis.set("guildTop+" + guildId, JSON.stringify(guildData), "EX", 60 * 30) } else { cacheStatus = true await interaction.editReply({ embeds: [{ description: "Fetching the top " + amount + " members of " + guildName + "using cache...", color: embedColor }] }) guildData = JSON.parse(cachedData) } const topMembers = allMembersSorted.slice(0, amount) const sliceSize = amount / 4 for (let i = 0; i < amount; i++) { const gexp = numberFormatter(topMembers[i].gexp) const ign = guildData.find(member => member.uuid === topMembers[i].uuid)?.ign const position = i + 1 fieldsValueRaw.push("**#" + position + " " + ign + ":** `" + gexp + "`") } const list = Array.from({ length: sliceSize }, (_, i) => fieldsValueRaw.slice(i * sliceSize, (i + 1) * sliceSize)) const newList: NewList = [] list.forEach((item, index) => { if (item.length === 0) return newList[index] = { name: "", value: item.join("\n"), inline: false } }) const cacheStatusText = cacheStatus ? " | [Cache]" : "" await interaction.editReply({ embeds: [{ title: "Top members of " + guildName, description: "**Total daily GEXP:** `" + gexpToday + "`\n" + "**Average guild memeber GEXP:** `" + averageGuildMemberGEXP + "`", color: embedColor, fields: newList, footer: { text: interaction.guild!.name + " | " + devMessage + cacheStatusText, icon_url: interaction.guild!.iconURL() || undefined } }] }) } export default cmd