From ace016c0c58abbdafd74f116175a3675a370fce6 Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 12 Oct 2025 15:42:39 +0200 Subject: [finish]: finish --- src/app.js | 153 ++++++++++++++++++++++++------------------------------------- 1 file changed, 61 insertions(+), 92 deletions(-) (limited to 'src/app.js') diff --git a/src/app.js b/src/app.js index 2a67f0b..d25b3b6 100644 --- a/src/app.js +++ b/src/app.js @@ -2,19 +2,14 @@ const { Client, Events, GatewayIntentBits } = require("discord.js") const axios = require("axios") const fs = require("fs-extra") const path = require("path") -const config = require("../config.json") +const config = require("../config/config.json") +const api = require("../config/api.json") -const { - token, - channel_id, - minecraft_version, - modrinth_mods, -} = config +const { channel_id, minecraft_version, modrinth_mods } = config +const { token } = api const cacheFile = path.join(__dirname, "../cache/mod_versions.json") - const client = new Client({ intents: [GatewayIntentBits.Guilds] }) -const strictVersionMatch = true const LoadCache = async () => { @@ -22,8 +17,7 @@ const LoadCache = async () => { if (await fs.pathExists(cacheFile)) return JSON.parse(await fs.readFile(cacheFile, "utf8")) - } - catch (err) + } catch (err) { console.error("[Cache] Failed to read cache:", err) } @@ -36,135 +30,112 @@ const SaveCache = async (cache) => { await fs.ensureDir(path.dirname(cacheFile)) await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2)) - } - catch (err) + } catch (err) { console.error("[Cache] Failed to save cache:", err) } } -const GetLatestFabricVersion = async (slug) => +const GetCompatibleModVersion = async (slug, targetMinecraftVersion) => { try { const res = await axios.get(`https://api.modrinth.com/v2/project/${slug}/version`) - const versions = res.data.filter(v => v.loaders.includes("fabric")) - if (versions.length === 0) return null + const fabricVersions = res.data.filter(v => v.loaders.includes("fabric")) + if (fabricVersions.length === 0) + return null - return versions.sort( - (a, b) => new Date(b.date_published) - new Date(a.date_published) + const compatible = fabricVersions.find(v => v.game_versions.includes(targetMinecraftVersion)) + const latest = fabricVersions.sort((a, b) => + new Date(b.date_published) - new Date(a.date_published) )[0] - } - catch (err) + + return { latest, compatible: compatible || null } + } catch (err) { console.error(`[Modrinth] Error fetching ${slug}:`, err.message) return null } } -const IsVersionCompatible = (modVersionList, targetVersion) => -{ - if (strictVersionMatch) - return modVersionList.includes(targetVersion) - else - return modVersionList.some(v => targetVersion.startsWith(v)) -} - const CheckModUpdates = async () => { - console.log("[Check] Checking for mod updates...") + console.log("[Check] Checking for mod compatibility...") const cache = await LoadCache() const newCache = { ...cache } - const updates = [] - const upToDate = [] + const compatibleReleased = [] const waitingUpdate = [] + const newlyCompatible = [] for (const slug of modrinth_mods) { - const latest = await GetLatestFabricVersion(slug) - if (!latest) continue + const modData = await GetCompatibleModVersion(slug, minecraft_version) + if (!modData) continue - const compatible = IsVersionCompatible(latest.game_versions, minecraft_version) + const { latest, compatible } = modData const latestId = latest.id const cachedId = cache[slug] if (compatible) { - if (cachedId !== latestId) - { - newCache[slug] = latestId - updates.push({ - slug, - version: latest.version_number, - url: `https://modrinth.com/mod/${slug}/version/${latestId}`, - }) - } - else + compatibleReleased.push({ slug }) + newCache[slug] = latestId + + if (!cachedId || cachedId !== latestId) { - upToDate.push({ - slug, - version: latest.version_number, - url: `https://modrinth.com/mod/${slug}/version/${latestId}`, - }) - console.log(`[Check] ${slug} is up to date.`) + newlyCompatible.push({ slug }) + console.log(`[Update] ${slug} is now compatible with Minecraft ${minecraft_version}`) } - } - else + } else { - waitingUpdate.push({ - slug, - version: latest.version_number, - url: `https://modrinth.com/mod/${slug}/version/${latestId}`, - }) - console.log(`[Check] ${slug} waiting for update — not compatible with ${minecraft_version}`) + waitingUpdate.push({ slug }) + console.log(`[Check] ${slug} is waiting for a compatible version`) } } await SaveCache(newCache) - return { updates, upToDate, waitingUpdate } + return { compatibleReleased, waitingUpdate, newlyCompatible } } -const SendUpdateMessages = async (channel, updates, upToDate, waitingUpdate) => +const SendUpdateMessages = async (channel, compatibleReleased, waitingUpdate, newlyCompatible) => { - if (updates.length === 0) + if (!compatibleReleased.length && !waitingUpdate.length) { - console.log("[Update]: No new updates."); - return; + console.log("[Update]: No mods to report.") + return } - let message = "" - message += `**Mod Update Check — Minecraft ${minecraft_version}**\n\n` + let message = `**Mod Compatibility Check — Minecraft ${minecraft_version}**\n\n` - if (updates.length > 0) + if (newlyCompatible.length > 0) { - message += `**🟢 Updated Mods:**\n` - for (const { slug, url } of updates) - message += `✅ [${slug}](${url}) updated\n` + message += `**🎉 Mods Recently Updated:**\n` + for (const { slug } of newlyCompatible) + message += `✅ ${slug}\n` message += `\n` } - if (upToDate.lengt > 0) - { - message += `**⚪ Up-to-Date Mods:**\n` - for (const { slug, url } of upToDate) - message += `✅ [${slug}](${url})\n` + const stillCompatible = compatibleReleased.filter( + m => !newlyCompatible.find(n => n.slug === m.slug) + ) + if (stillCompatible.length > 0) + { + message += `**🟢 Mods Compatible:**\n` + for (const { slug } of stillCompatible) + message += `✅ ${slug}\n` message += `\n` } if (waitingUpdate.length > 0) { - message += `**⏳ Mods Waiting for Update:**\n` - for (const { slug, url } of waitingUpdate) - message += `❌ [${slug}](${url})\n` + message += `**⏳ Mods Waiting on Update:**\n` + for (const { slug } of waitingUpdate) + message += `❌ ${slug}\n` + message += `\n` } - - await channel.send( -{ - content: message, - allowedMentions: { parse: [] }, - flags: 4 - }) - console.log(`[Discord] Sent update summary (${updates.length} updated, ${upToDate.length} up-to-date, ${waitingUpdate.length} waiting).`) + + await channel.send({ content: message, allowedMentions: { parse: [] }, flags: 4 }) + console.log(`[Discord] Sent update summary (${newlyCompatible.length} updated, ${stillCompatible.length} compatible, ${waitingUpdate.length} waiting).`) } client.once(Events.ClientReady, async readyClient => @@ -172,20 +143,18 @@ client.once(Events.ClientReady, async readyClient => console.log(`[OK] Logged in as ${readyClient.user.tag}`) const channel = await client.channels.fetch(channel_id).catch(() => null) - if (!channel) - { + if (!channel) { console.error("❌ Could not find channel ID:", channel_id) return } - const { updates, upToDate, waitingUpdate } = await CheckModUpdates() - await SendUpdateMessages(channel, updates, upToDate, waitingUpdate) + const { compatibleReleased, waitingUpdate, newlyCompatible } = await CheckModUpdates() + await SendUpdateMessages(channel, compatibleReleased, waitingUpdate, newlyCompatible) - // ⏰ Check every hour (3600000 ms) setInterval(async () => { - const { updates, upToDate, waitingUpdate } = await CheckModUpdates() - await SendUpdateMessages(channel, updates, upToDate, waitingUpdate) + const { compatibleReleased, waitingUpdate, newlyCompatible } = await CheckModUpdates() + await SendUpdateMessages(channel, compatibleReleased, waitingUpdate, newlyCompatible) }, 60 * 60 * 1000) }) -- cgit v1.3