Update from Git Manager GUI
This commit is contained in:
130
commands/compare.js
Normal file
130
commands/compare.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import { EmbedBuilder, SlashCommandBuilder } from "discord.js";
|
||||
import fs from "fs";
|
||||
import { t, getLang } from "../util/i18n.js";
|
||||
import { generateResourceIconURL } from "../util/helpers.js";
|
||||
import { Spiget } from "spiget";
|
||||
|
||||
const spiget = new Spiget("Viper-Network");
|
||||
|
||||
export default {
|
||||
name: "compare",
|
||||
description: "Vergleicht zwei Plugins nebeneinander",
|
||||
aliases: ["cmp"],
|
||||
guild: ["all"],
|
||||
nsfw: false,
|
||||
user_permissions: [],
|
||||
bot_permissions: [],
|
||||
args_required: 2,
|
||||
args_usage: "[id1] [id2] Beispiel: vn!compare 72678 34315",
|
||||
cooldown: 10,
|
||||
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("compare")
|
||||
.setDescription("Compares two plugins side by side")
|
||||
.addStringOption((opt) =>
|
||||
opt.setName("id1").setDescription("Erste Ressourcen-ID").setRequired(true)
|
||||
)
|
||||
.addStringOption((opt) =>
|
||||
opt.setName("id2").setDescription("Zweite Ressourcen-ID").setRequired(true)
|
||||
),
|
||||
|
||||
async execute(client, ctx, args) {
|
||||
const lang = loadLang(ctx.guild.id);
|
||||
const id1 = ctx.isSlash ? ctx.interaction.options.getString("id1") : args[0];
|
||||
const id2 = ctx.isSlash ? ctx.interaction.options.getString("id2") : args[1];
|
||||
|
||||
// Fetch both resources in parallel
|
||||
let [dataA, dataB] = await Promise.all([
|
||||
fetchResource(id1),
|
||||
fetchResource(id2),
|
||||
]);
|
||||
|
||||
if (!dataA) return ctx.reply(t(lang, "error.invalidID", { id: id1 }));
|
||||
if (!dataB) return ctx.reply(t(lang, "error.invalidID", { id: id2 }));
|
||||
|
||||
// Fetch latest versions
|
||||
const [verA, verB] = await Promise.all([
|
||||
fetchVersion(id1),
|
||||
fetchVersion(id2),
|
||||
]);
|
||||
|
||||
dataA.latestVersion = verA;
|
||||
dataB.latestVersion = verB;
|
||||
|
||||
// Helper: format a stat with winner indicator
|
||||
const win = (valA, valB, higherIsBetter = true) => {
|
||||
if (valA === valB) return ["–", "–"];
|
||||
const aWins = higherIsBetter ? valA > valB : valA < valB;
|
||||
return aWins ? ["🏆", ""] : ["", "🏆"];
|
||||
};
|
||||
|
||||
const [dlWinA, dlWinB] = win(dataA.downloads, dataB.downloads);
|
||||
const [rtWinA, rtWinB] = win(dataA.rating?.average ?? 0, dataB.rating?.average ?? 0);
|
||||
|
||||
const dateA = dataA.updateDate ? new Date(dataA.updateDate * 1000).toLocaleDateString("de-DE") : "?";
|
||||
const dateB = dataB.updateDate ? new Date(dataB.updateDate * 1000).toLocaleDateString("de-DE") : "?";
|
||||
const [dtWinA, dtWinB] = win(dataA.updateDate ?? 0, dataB.updateDate ?? 0);
|
||||
|
||||
const dlA = (dataA.downloads ?? 0).toLocaleString("de-DE");
|
||||
const dlB = (dataB.downloads ?? 0).toLocaleString("de-DE");
|
||||
const rtA = dataA.rating?.average?.toFixed(1) ?? "–";
|
||||
const rtB = dataB.rating?.average?.toFixed(1) ?? "–";
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(ctx.guild.members.me.displayHexColor)
|
||||
.setTitle(t(lang, "compare.title"))
|
||||
.addFields([
|
||||
// Header row
|
||||
{ name: "📦 Plugin", value: `**${dataA.name}**`, inline: true },
|
||||
{ name: "\u200b", value: "**vs**", inline: true },
|
||||
{ name: "\u200b", value: `**${dataB.name}**`, inline: true },
|
||||
// Downloads
|
||||
{ name: t(lang, "compare.downloads"), value: `${dlWinA} ${dlA}`, inline: true },
|
||||
{ name: "\u200b", value: "⬇️", inline: true },
|
||||
{ name: "\u200b", value: `${dlWinB} ${dlB}`, inline: true },
|
||||
// Rating
|
||||
{ name: t(lang, "compare.rating"), value: `${rtWinA} ⭐ ${rtA}`, inline: true },
|
||||
{ name: "\u200b", value: "⭐", inline: true },
|
||||
{ name: "\u200b", value: `${rtWinB} ⭐ ${rtB}`, inline: true },
|
||||
// Version
|
||||
{ name: t(lang, "compare.version"), value: `v${verA ?? "?"}`, inline: true },
|
||||
{ name: "\u200b", value: "📦", inline: true },
|
||||
{ name: "\u200b", value: `v${verB ?? "?"}`, inline: true },
|
||||
// Last update
|
||||
{ name: t(lang, "compare.updated"), value: `${dtWinA} ${dateA}`, inline: true },
|
||||
{ name: "\u200b", value: "🕐", inline: true },
|
||||
{ name: "\u200b", value: `${dtWinB} ${dateB}`, inline: true },
|
||||
// Links
|
||||
{ name: "🔗 Link", value: `[SpigotMC](https://spigotmc.org/resources/.${id1}/)`, inline: true },
|
||||
{ name: "\u200b", value: "\u200b", inline: true },
|
||||
{ name: "\u200b", value: `[SpigotMC](https://spigotmc.org/resources/.${id2}/)`, inline: true },
|
||||
])
|
||||
.setFooter({ text: `IDs: ${id1} vs ${id2}` })
|
||||
.setTimestamp();
|
||||
|
||||
return ctx.reply({ embeds: [embed] });
|
||||
},
|
||||
};
|
||||
|
||||
async function fetchResource(id) {
|
||||
try {
|
||||
const res = await fetch(`https://api.spiget.org/v2/resources/${id}`);
|
||||
if (!res.ok) return null;
|
||||
return await res.json();
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
async function fetchVersion(id) {
|
||||
try {
|
||||
const res = await fetch(`https://api.spigotmc.org/legacy/update.php?resource=${id}`);
|
||||
if (!res.ok) return null;
|
||||
return (await res.text()).trim();
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
function loadLang(guildID) {
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(`./serverdata/${guildID}.json`, "utf8"));
|
||||
return getLang(data);
|
||||
} catch { return "de"; }
|
||||
}
|
||||
Reference in New Issue
Block a user