hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-11-23 05:01:11 +0100
committerhachem <im@hachem.wtf>2025-11-23 05:01:11 +0100
commit9010ed1f600413465468b824036cff471d3972c1 (patch)
treee96a3705d9a5f554eea46dc01d17509fa080476b
parentdb64493f5d66ea2912f099bf971ff6ffd9b6895c (diff)
[add]: i spent way too much time on this stupid bot omg
-rw-r--r--bot/app.js280
-rw-r--r--config/config.json2
2 files changed, 143 insertions, 139 deletions
diff --git a/bot/app.js b/bot/app.js
index d0d5084..3fc9134 100644
--- a/bot/app.js
+++ b/bot/app.js
@@ -1,8 +1,8 @@
const
{
- Client,
- Events,
- GatewayIntentBits
+ Client,
+ Events,
+ GatewayIntentBits
} = require("discord.js")
const axios = require("axios")
@@ -14,190 +14,194 @@ const api = require("../config/api.json")
const
{
- channel_id,
- minecraft_version,
- modrinth_mods
+ channel_id,
+ check_interval_minutes,
+ minecraft_version,
+ fabric_loader_version,
+ loader_meta_version,
+ modrinth_mods
} = config
-const
-{
- token
-} = api
+const { token } = api
const cacheFile = path.join(__dirname, "../cache/mod_versions.json")
-
const client = new Client
({
- intents: [GatewayIntentBits.Guilds]
+ intents:
+ [
+ GatewayIntentBits.Guilds,
+ GatewayIntentBits.GuildMessages
+ ]
})
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 {}
+ try
+ {
+ if (await fs.pathExists(cacheFile))
+ return JSON.parse(await fs.readFile(cacheFile, "utf8"))
+ }
+ catch (err)
+ {
+ console.error("[Cache] Failed to load:", 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)
- }
+ try
+ {
+ await fs.ensureDir(path.dirname(cacheFile))
+ await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2))
+ }
+ catch (err)
+ {
+ console.error("[Cache] Failed to save:", err)
+ }
}
-const GetModrinthData = async slug =>
+const GetModVersions = async slug =>
{
- try
- {
- 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
- }
+ try
+ {
+ const response = await axios.get(`https://api.modrinth.com/v2/project/${slug}/version`)
+ return response.data
+ }
+ catch (err)
+ {
+ console.error(`[Modrinth] Failed for ${slug}:`, err.message)
+ return null
+ }
}
const CheckMods = async () =>
{
- const cache = await LoadCache()
- const newCache = { ...cache }
+ const cache = await LoadCache()
+ const newCache = { ...cache }
- const updatedNotCompatible = []
- const newlyCompatible = []
- const compatibleUpdated = []
+ const noCompatible = []
+ const newlyCompatible = []
+ const stillCompatibleUpdate = []
- for (const slug of modrinth_mods)
- {
- const versions = await GetModrinthData(slug)
- if (!versions)
- continue
-
- const fabric = versions.filter(v => v.loaders.includes("fabric"))
- if (!fabric.length)
- continue
+ for (const slug of modrinth_mods)
+ {
+ const versions = await GetModVersions(slug)
+ if (!versions)
+ continue
- const latest = fabric.sort((a, b) =>
- new Date(b.date_published) - new Date(a.date_published)
- )[0]
+ const latest = versions.sort((a, b) => new Date(b.date_published) - new Date(a.date_published))[0]
+ const compatible = versions.find(v => v.game_versions.includes(minecraft_version)) || null
- const latestId = latest.id
- const compatible = latest.game_versions.includes(minecraft_version)
- const cachedId = cache[slug]
+ const cached = cache[slug] ||
+ {
+ compatible: null,
+ latest: null
+ }
- if (!cachedId)
- newCache[slug] = latestId
+ newCache[slug] =
+ {
+ compatible: compatible ? compatible.id : null,
+ latest: latest.id
+ }
- if (latestId === cachedId)
- continue
+ if (!compatible)
+ {
+ noCompatible.push(slug)
+ continue
+ }
- const previouslyCompatible = fabric.some(v =>
- v.id === cachedId && v.game_versions.includes(minecraft_version)
- )
+ if (!cached.compatible && compatible)
+ {
+ newlyCompatible.push(slug)
+ continue
+ }
- if (!compatible)
- updatedNotCompatible.push(slug)
- else if (compatible && !previouslyCompatible)
- newlyCompatible.push(slug)
- else if (compatible && previouslyCompatible)
- compatibleUpdated.push(slug)
+ if (latest.id !== cached.latest)
+ stillCompatibleUpdate.push(slug)
+ }
- newCache[slug] = latestId
- }
+ await SaveCache(newCache)
- await SaveCache(newCache)
- return { updatedNotCompatible, newlyCompatible, compatibleUpdated }
+ return { noCompatible, newlyCompatible, stillCompatibleUpdate }
}
-const SendUpdate = async (channel, updatedNotCompatible, newlyCompatible, compatibleUpdated) =>
+const SendUpdate = async (channel, noCompatible, newlyCompatible, stillCompatibleUpdate) =>
{
- if (!updatedNotCompatible.length && !newlyCompatible.length && !compatibleUpdated.length)
- return
+ if (!noCompatible.length && !newlyCompatible.length && !stillCompatibleUpdate.length)
+ return
- let msg = `**Modrinth Update Check — ${minecraft_version}**\n\n`
+ let msg = `**Modrinth Compatibility — ${minecraft_version}**\n\n`
- if (updatedNotCompatible.length)
- {
- msg += `**❗ Updated but NOT compatible:**\n`
- for (const s of updatedNotCompatible)
- msg += `❗ ${s}\n`
- msg += `\n`
- }
-
- if (newlyCompatible.length)
- {
- msg += `**🎉 NOW Compatible:**\n`
- for (const s of newlyCompatible)
- msg += `🎉 ${s}\n`
- msg += `\n`
- }
+ if (noCompatible.length)
+ {
+ msg += `**❌ No compatible version available:**\n`
+ for (const slug of noCompatible)
+ msg += `❌ ${slug}\n`
+ msg += `\n`
+ }
- if (compatibleUpdated.length)
- {
- msg += `**🟢 Updated (still compatible):**\n`
- for (const s of compatibleUpdated)
- msg += `🟢 ${s}\n`
- msg += `\n`
- }
+ if (newlyCompatible.length)
+ {
+ msg += `**🎉 Now Compatible:**\n`
+ for (const slug of newlyCompatible)
+ msg += `🎉 ${slug}\n`
+ msg += `\n`
+ }
- await channel.send
- ({
- content: msg,
- allowedMentions:
+ if (stillCompatibleUpdate.length)
{
- parse: []
- },
- flags: 4
- })
+ msg += `**🟢 Updated (still compatible):**\n`
+ for (const slug of stillCompatibleUpdate)
+ msg += `🟢 ${slug}\n`
+ msg += `\n`
+ }
- console.log("[Discord] Sent update.")
+ await channel.send
+ ({
+ content: msg,
+ allowedMentions: { parse: [] }
+ })
+
+ console.log("[Discord] Update message sent.")
}
client.once(Events.ClientReady, async c =>
{
- console.log(`[OK] Logged in as ${c.user.tag}`)
-
- const channel = await client.channels.fetch(channel_id).catch(() => null)
- if (!channel)
- {
- console.error("Invalid channel_id:", channel_id)
- return
- }
-
- const
- {
- updatedNotCompatible,
- newlyCompatible,
- compatibleUpdated
- } = await CheckMods()
+ console.log(`[OK] Logged in as ${c.user.tag}`)
- await SendUpdate(channel, updatedNotCompatible, newlyCompatible, compatibleUpdated)
+ let channel = null
+ try
+ {
+ channel = await client.channels.fetch(channel_id)
+ console.log("Fetched channel:", channel.name, "type:", channel.type)
+ }
+ catch
+ {
+ console.error("❌ Failed to fetch channel:", channel_id)
+ return
+ }
- setInterval(async () =>
- {
const
{
- updatedNotCompatible,
- newlyCompatible,
- compatibleUpdated
+ noCompatible,
+ newlyCompatible,
+ stillCompatibleUpdate
} = await CheckMods()
- await SendUpdate(channel, updatedNotCompatible, newlyCompatible, compatibleUpdated)
- }, 60 * 60 * 1000)
+ await SendUpdate(channel, noCompatible, newlyCompatible, stillCompatibleUpdate)
+
+ setInterval(async () =>
+ {
+ const
+ {
+ noCompatible,
+ newlyCompatible,
+ stillCompatibleUpdate
+ } = await CheckMods()
+
+ await SendUpdate(channel, noCompatible, newlyCompatible, stillCompatibleUpdate)
+ }, check_interval_minutes * 60 * 1000)
})
-client.login(token)
+client.login(token) \ No newline at end of file
diff --git a/config/config.json b/config/config.json
index 3cde6d7..6db2f86 100644
--- a/config/config.json
+++ b/config/config.json
@@ -1,5 +1,5 @@
{
- "channel_id": "1426917156032876635",
+ "channel_id": "[channel]",
"check_interval_minutes": 60,
"minecraft_version": "1.21.10",
"fabric_loader_version": "0.17.3",