From d41d3d812d22ca8371b4cf5240b23f4262667f34 Mon Sep 17 00:00:00 2001 From: Sophia Atkinson Date: Tue, 6 May 2025 18:27:36 -0700 Subject: [PATCH] added support for 2 new sites, and patched jenkins you can now pull from Paper Hanger, and Bukkit to tell jenkins out i used lastSuccessfulBuild, meaning if you used something diffrent like lastStableBuild it would error out. --- README.md | 2 +- index.js | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2bd61f2..2c7b26c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Features -- Auto-detects download source (GitHub / Jenkins / Modrinth / Direct) +- Auto-detects download source (GitHub / Jenkins / Modrinth / Bukkit / Direct) - Skips already downloaded files - Password encryption for SFTP (AES-256-CBC) - Optional SFTP upload support diff --git a/index.js b/index.js index 034ab5e..a54992e 100644 --- a/index.js +++ b/index.js @@ -180,6 +180,62 @@ const handleDirect = async (url) => { await downloadJar(url, name); }; +// --- Handle PaperMC --- +const handlePaperMC = async (url) => { + const versionMatch = url.match(/papermc.io\/download\/(.*?)(?:\/|$)/); + if (!versionMatch) throw new Error("Invalid PaperMC URL format"); + const version = versionMatch[1]; + + const apiURL = `https://api.papermc.io/v2/projects/paper/versions/${version}/builds`; + const builds = await axios.get(apiURL).then((res) => res.data.builds); + const latestBuild = builds[0]; + + const downloadURL = latestBuild.downloads.application.url; + await downloadJar(downloadURL, `paper-${version}-${latestBuild.build}.jar`); +}; + +// --- Handle dev.bukkit.org --- +const handleBukkit = async (url) => { + if (!url.includes("dev.bukkit.org")) { + throw new Error("Not a dev.bukkit.org URL"); + } + + const html = await axios.get(url).then((res) => res.data); + const $ = cheerio.load(html); + + + let projectName = $("span.overflow-tip").text().trim() || "unknown-project"; + + projectName = projectName + .replace(/[<>:"/\\|?*\x00-\x1F()™©®]/g, "") + .replace(/[^\w.-]/g, "_"); + + + const downloadLink = $("a.button.alt.fa-icon-download[href*='/files/latest']") + .attr("href"); + + if (!downloadLink) { + throw new Error("No 'Download Latest File' link found on dev.bukkit.org page"); + } + + const fullDownloadLink = `https://dev.bukkit.org${downloadLink}`; + console.log(`🔗 Found download link: ${fullDownloadLink}`); + + let filename = `${projectName}.jar`; + + try { + const head = await axios.head(fullDownloadLink); + const disp = head.headers["content-disposition"]; + const match = disp?.match(/filename[^=]*=(?:UTF-8'')?["']?([^"';]+)/i); + if (match) filename = decodeURIComponent(match[1]); + } catch (err) { + console.log("Could not retrieve filename from headers, using project name."); + } + + await downloadJar(fullDownloadLink, filename); +}; + + // --- Upload to SFTP --- const uploadToSFTP = async () => { if (!sftpConfig.enabled) { @@ -231,7 +287,11 @@ const uploadToSFTP = async () => { await handleGitHub(url); } else if (url.includes("modrinth.com")) { await handleModrinth(url); - } else if (url.includes("/lastSuccessfulBuild/")) { + } else if (url.includes("papermc.io")) { + await handlePaperMC(url); + } else if (url.includes("dev.bukkit.org")) { + await handleBukkit(url); + } else if (url.includes("/job/")) { await handleJenkins(url); } else if (url.endsWith(".jar") || url.includes("download.geysermc.org")) { await handleDirect(url);