Files
SpigotWatch/commands/top.js
2026-02-25 18:51:08 +01:00

100 lines
3.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { EmbedBuilder, SlashCommandBuilder } from "discord.js";
import fs from "fs/promises";
import { t, getLang } from "../util/i18n.js";
export default {
name: "top",
description: "Zeigt die meistgeladenen/bestbewerteten beobachteten Plugins",
aliases: [],
guild: ["all"],
nsfw: false,
user_permissions: [],
bot_permissions: [],
args_required: 0,
args_usage: "[-r] -r = nach Bewertung sortieren",
cooldown: 10,
data: new SlashCommandBuilder()
.setName("top")
.setDescription("Shows the top watched plugins by downloads or rating")
.addStringOption((opt) =>
opt
.setName("sortierung")
.setDescription("Sortierung")
.setRequired(false)
.addChoices(
{ name: "⬇️ Downloads", value: "downloads" },
{ name: "⭐ Bewertung", value: "rating" }
)
),
async execute(client, ctx, args) {
const guildID = ctx.guild.id;
const filePath = `./serverdata/${guildID}.json`;
let saveData;
try {
const raw = await fs.readFile(filePath, "utf8");
saveData = JSON.parse(raw);
} catch {
return ctx.reply("Dieser Server hat keine beobachteten Ressourcen.");
}
const lang = getLang(saveData);
const sortBy = ctx.isSlash
? (ctx.interaction.options.getString("sortierung") ?? "downloads")
: (args.includes("-r") ? "rating" : "downloads");
const watched = saveData.watchedResources;
if (!watched || watched.length === 0) {
return ctx.reply(t(lang, "top.noData"));
}
// Fetch stats for all watched resources
const results = [];
for (const w of watched) {
try {
const res = await fetch(`https://api.spiget.org/v2/resources/${w.resourceID}`);
if (!res.ok) continue;
const data = await res.json();
results.push({
id: w.resourceID,
name: data.name ?? w.resourceName ?? w.resourceID,
downloads: data.downloads ?? 0,
rating: data.rating?.average ?? 0,
version: w.lastCheckedVersion ?? "?",
channelID: w.channelID,
});
await new Promise((r) => setTimeout(r, 300));
} catch { /* Plugin überspringen */ }
}
if (results.length === 0) {
return ctx.reply(t(lang, "error.apiDown"));
}
// Sort
results.sort((a, b) =>
sortBy === "rating" ? b.rating - a.rating : b.downloads - a.downloads
);
const sortLabel = t(lang, sortBy === "rating" ? "top.rating" : "top.downloads");
const medal = ["🥇", "🥈", "🥉"];
const list = results.map((r, i) => {
const icon = medal[i] ?? `${i + 1}.`;
const dl = r.downloads.toLocaleString("de-DE");
const stars = r.rating > 0 ? `${r.rating.toFixed(1)}` : "⭐ ";
return `${icon} **${r.name}** (v${r.version})\n⬇️ ${dl} ${stars} 🆔 \`${r.id}\``;
}).join("\n\n");
const embed = new EmbedBuilder()
.setColor(ctx.guild.members.me.displayHexColor)
.setTitle(t(lang, "top.title", { sort: sortLabel }))
.setDescription(list)
.setFooter({ text: `${results.length} Plugins • ${client.config.prefix}plugin [id] für Details` })
.setTimestamp();
return ctx.reply({ embeds: [embed] });
},
};