hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/src/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/app.js b/src/app.js
index e69de29..2a67f0b 100644
--- a/src/app.js
+++ b/src/app.js
@@ -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)