diff options
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 192 |
1 files changed, 192 insertions, 0 deletions
@@ -0,0 +1,192 @@ +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 { + token, + channel_id, + minecraft_version, + modrinth_mods, +} = config + +const cacheFile = path.join(__dirname, "../cache/mod_versions.json") + +const client = new Client({ intents: [GatewayIntentBits.Guilds] }) +const strictVersionMatch = true + +const LoadCache = async () => +{ + try + { + if (await fs.pathExists(cacheFile)) + return JSON.parse(await fs.readFile(cacheFile, "utf8")) + } + catch (err) + { + console.error("[Cache] Failed to read cache:", err) + } + return {} +} + +const SaveCache = async (cache) => +{ + try + { + await fs.ensureDir(path.dirname(cacheFile)) + await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2)) + } + catch (err) + { + console.error("[Cache] Failed to save cache:", err) + } +} + +const GetLatestFabricVersion = async (slug) => +{ + 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 + + return versions.sort( + (a, b) => new Date(b.date_published) - new Date(a.date_published) + )[0] + } + 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...") + const cache = await LoadCache() + const newCache = { ...cache } + const updates = [] + const upToDate = [] + const waitingUpdate = [] + + for (const slug of modrinth_mods) + { + const latest = await GetLatestFabricVersion(slug) + if (!latest) continue + + const compatible = IsVersionCompatible(latest.game_versions, minecraft_version) + 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 + { + upToDate.push({ + slug, + version: latest.version_number, + url: `https://modrinth.com/mod/${slug}/version/${latestId}`, + }) + console.log(`[Check] ${slug} is up to date.`) + } + } + 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}`) + } + } + + await SaveCache(newCache) + return { updates, upToDate, waitingUpdate } +} + +const SendUpdateMessages = async (channel, updates, upToDate, waitingUpdate) => +{ + if (updates.length === 0) + { + console.log("[Update]: No new updates."); + return; + } + + let message = "" + message += `**Mod Update Check — Minecraft ${minecraft_version}**\n\n` + + if (updates.length > 0) + { + message += `**🟢 Updated Mods:**\n` + for (const { slug, url } of updates) + message += `✅ [${slug}](${url}) updated\n` + message += `\n` + } + + if (upToDate.lengt > 0) + { + message += `**⚪ Up-to-Date Mods:**\n` + for (const { slug, url } of upToDate) + message += `✅ [${slug}](${url})\n` + message += `\n` + } + + if (waitingUpdate.length > 0) + { + message += `**⏳ Mods Waiting for Update:**\n` + for (const { slug, url } of waitingUpdate) + message += `❌ [${slug}](${url})\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).`) +} + +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) + { + console.error("❌ Could not find channel ID:", channel_id) + return + } + + const { updates, upToDate, waitingUpdate } = await CheckModUpdates() + await SendUpdateMessages(channel, updates, upToDate, waitingUpdate) + + // ⏰ Check every hour (3600000 ms) + setInterval(async () => + { + const { updates, upToDate, waitingUpdate } = await CheckModUpdates() + await SendUpdateMessages(channel, updates, upToDate, waitingUpdate) + }, 60 * 60 * 1000) +}) + +client.login(token) |
