hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-11-23 04:44:40 +0100
committerhachem <im@hachem.wtf>2025-11-23 04:44:40 +0100
commitdb64493f5d66ea2912f099bf971ff6ffd9b6895c (patch)
treebf7152f29a754ef4208280ad5cbc7a23b4e0efd9
parent9f0d24d68628e43519b4aeec85fc1bc2cb6fe6ce (diff)
[add]: i learnt how to read
-rw-r--r--bot/app.js296
1 files changed, 169 insertions, 127 deletions
diff --git a/bot/app.js b/bot/app.js
index 8f1bfeb..d0d5084 100644
--- a/bot/app.js
+++ b/bot/app.js
@@ -1,161 +1,203 @@
- const { Client, Events, GatewayIntentBits } = require("discord.js")
- const axios = require("axios")
- const fs = require("fs-extra")
- const path = require("path")
- const config = require("../config/config.json")
- const api = require("../config/api.json")
+const
+{
+ Client,
+ Events,
+ GatewayIntentBits
+} = require("discord.js")
- const { channel_id, minecraft_version, modrinth_mods } = config
- const { token } = api
+const axios = require("axios")
+const fs = require("fs-extra")
+const path = require("path")
- const cacheFile = path.join(__dirname, "../cache/mod_versions.json")
- const client = new Client({ intents: [GatewayIntentBits.Guilds] })
+const config = require("../config/config.json")
+const api = require("../config/api.json")
- const LoadCache = async () =>
+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 LoadCache = async () =>
+{
+ try
{
- 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 {}
+ 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) =>
+const SaveCache = async cache =>
+{
+ try
{
- 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)
- }
+ 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 GetCompatibleModVersion = async (slug, targetMinecraftVersion) =>
+const GetModrinthData = async slug =>
+{
+ try
{
- try
- {
- const res = await axios.get(`https://api.modrinth.com/v2/project/${slug}/version`)
- const fabricVersions = res.data.filter(v => v.loaders.includes("fabric"))
- if (fabricVersions.length === 0)
- return null
+ const r = await axios.get(`https://api.modrinth.com/v2/project/${slug}/version`)
+ return r.data
+ }
+ catch (err)
+ {
+ console.error(`[Modrinth] Failed for ${slug}:`, err.message)
+ return null
+ }
+}
- 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]
+const CheckMods = async () =>
+{
+ const cache = await LoadCache()
+ const newCache = { ...cache }
- return { latest, compatible: compatible || null }
- } catch (err)
- {
- console.error(`[Modrinth] Error fetching ${slug}:`, err.message)
- return null
- }
- }
+ const updatedNotCompatible = []
+ const newlyCompatible = []
+ const compatibleUpdated = []
- const CheckModUpdates = async () =>
+ for (const slug of modrinth_mods)
{
- console.log("[Check] Checking for mod compatibility...")
- const cache = await LoadCache()
- const newCache = { ...cache }
- const compatibleReleased = []
- const waitingUpdate = []
- const newlyCompatible = []
+ const versions = await GetModrinthData(slug)
+ if (!versions)
+ continue
- for (const slug of modrinth_mods)
- {
- const modData = await GetCompatibleModVersion(slug, minecraft_version)
- if (!modData) continue
+ const fabric = versions.filter(v => v.loaders.includes("fabric"))
+ if (!fabric.length)
+ continue
+
+ const latest = fabric.sort((a, b) =>
+ new Date(b.date_published) - new Date(a.date_published)
+ )[0]
+
+ const latestId = latest.id
+ const compatible = latest.game_versions.includes(minecraft_version)
+ const cachedId = cache[slug]
- const { latest, compatible } = modData
- const latestId = latest.id
- const cachedId = cache[slug]
+ if (!cachedId)
+ newCache[slug] = latestId
- if (compatible)
- {
- compatibleReleased.push({ slug })
- newCache[slug] = latestId
+ if (latestId === cachedId)
+ continue
- if (!cachedId || cachedId !== latestId)
- {
- newlyCompatible.push({ slug })
- console.log(`[Update] ${slug} is now compatible with Minecraft ${minecraft_version}`)
- }
- } else
- {
- waitingUpdate.push({ slug })
- console.log(`[Check] ${slug} is waiting for a compatible version`)
- }
- }
+ const previouslyCompatible = fabric.some(v =>
+ v.id === cachedId && v.game_versions.includes(minecraft_version)
+ )
+
+ if (!compatible)
+ updatedNotCompatible.push(slug)
+ else if (compatible && !previouslyCompatible)
+ newlyCompatible.push(slug)
+ else if (compatible && previouslyCompatible)
+ compatibleUpdated.push(slug)
- await SaveCache(newCache)
- return { compatibleReleased, waitingUpdate, newlyCompatible }
+ newCache[slug] = latestId
}
- const SendUpdateMessages = async (channel, compatibleReleased, waitingUpdate, newlyCompatible) =>
+ await SaveCache(newCache)
+ return { updatedNotCompatible, newlyCompatible, compatibleUpdated }
+}
+
+const SendUpdate = async (channel, updatedNotCompatible, newlyCompatible, compatibleUpdated) =>
+{
+ if (!updatedNotCompatible.length && !newlyCompatible.length && !compatibleUpdated.length)
+ return
+
+ let msg = `**Modrinth Update Check — ${minecraft_version}**\n\n`
+
+ if (updatedNotCompatible.length)
{
- if (!newlyCompatible.length || !waitingUpdate.length)
- {
- console.log("[Update]: No mods to report.")
- return
- }
-
- let message = `**Mod Compatibility Check — Minecraft ${minecraft_version}**\n\n`
+ msg += `**❗ Updated but NOT compatible:**\n`
+ for (const s of updatedNotCompatible)
+ msg += `❗ ${s}\n`
+ msg += `\n`
+ }
- if (newlyCompatible.length > 0)
- {
- message += `**🎉 Mods Recently Updated:**\n`
- for (const { slug } of newlyCompatible)
- message += `✅ ${slug}\n`
- message += `\n`
- }
+ if (newlyCompatible.length)
+ {
+ msg += `**🎉 NOW Compatible:**\n`
+ for (const s of newlyCompatible)
+ msg += `🎉 ${s}\n`
+ msg += `\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 (compatibleUpdated.length)
+ {
+ msg += `**🟢 Updated (still compatible):**\n`
+ for (const s of compatibleUpdated)
+ msg += `🟢 ${s}\n`
+ msg += `\n`
+ }
- if (waitingUpdate.length > 0)
+ await channel.send
+ ({
+ content: msg,
+ allowedMentions:
{
- message += `**⏳ Mods Waiting on Update:**\n`
- for (const { slug } of waitingUpdate)
- message += `❌ ${slug}\n`
- message += `\n`
- }
+ parse: []
+ },
+ flags: 4
+ })
- await channel.send({ content: message, allowedMentions: { parse: [] }, flags: 4 })
- console.log(`[Discord] Sent update summary (${newlyCompatible.length} updated, ${stillCompatible.length} compatible, ${waitingUpdate.length} waiting).`)
- }
+ console.log("[Discord] Sent update.")
+}
+
+client.once(Events.ClientReady, async c =>
+{
+ console.log(`[OK] Logged in as ${c.user.tag}`)
- client.once(Events.ClientReady, async readyClient =>
+ const channel = await client.channels.fetch(channel_id).catch(() => null)
+ if (!channel)
{
- console.log(`[OK] Logged in as ${readyClient.user.tag}`)
+ console.error("Invalid channel_id:", channel_id)
+ return
+ }
- const channel = await client.channels.fetch(channel_id).catch(() => null)
- if (!channel) {
- console.error("❌ Could not find channel ID:", channel_id)
- return
- }
+ const
+ {
+ updatedNotCompatible,
+ newlyCompatible,
+ compatibleUpdated
+ } = await CheckMods()
- const { compatibleReleased, waitingUpdate, newlyCompatible } = await CheckModUpdates()
- await SendUpdateMessages(channel, compatibleReleased, waitingUpdate, newlyCompatible)
+ await SendUpdate(channel, updatedNotCompatible, newlyCompatible, compatibleUpdated)
- setInterval(async () =>
+ setInterval(async () =>
+ {
+ const
{
- const { compatibleReleased, waitingUpdate, newlyCompatible } = await CheckModUpdates()
- await SendUpdateMessages(channel, compatibleReleased, waitingUpdate, newlyCompatible)
- }, 60 * 60 * 1000)
- })
+ updatedNotCompatible,
+ newlyCompatible,
+ compatibleUpdated
+ } = await CheckMods()
+
+ await SendUpdate(channel, updatedNotCompatible, newlyCompatible, compatibleUpdated)
+ }, 60 * 60 * 1000)
+})
- client.login(token)
+client.login(token)