diff --git a/index.js b/index.js index f9076e4..93e650e 100644 --- a/index.js +++ b/index.js @@ -1,121 +1,140 @@ -require("dotenv").config() -const uptimekuma = require("uptimekuma-api") -const kuma = new uptimekuma(process.env.KUMA_BASE_URL); -const subs = require("./subs.json") -const Discord = require("discord.js") -const Client = new Discord.Client({ - intents: [ - "Guilds", - "GuildMessages" - ] -}) +require("dotenv").config(); +const { Client, GatewayIntentBits, EmbedBuilder } = require("discord.js"); +const UptimeKuma = require("uptimekuma-api"); +const cron = require("node-cron"); +const subs = require("./subs.json"); -const cron = require("node-cron") +const KUMA_BASE_URL = process.env.KUMA_BASE_URL; +const DISCORD_TOKEN = process.env.TOKEN; +const CRON_SCHEDULE = "*/5 * * * *"; -function getStatus(input) { - return new Promise((resolve, reject) => { - kuma.status(input).then((status) => { - let total = 0; - let offline = 0; - let embed = { - title: status.info.title, - thumbnail: { - url: status.info.icon - }, - fields: [] - } - // for (cat of status.status) { - // let fieldText = ""; - // for (monitor of cat.monitors) { - // if (!monitor.heartbeats[0].status) offline++; - // total++; - // fieldText += `${monitor.heartbeats[0].status ? "<:online:1307359583785713744>" : "<:offline:1307359600592424971>"} ${monitor.name}\n` - // } - // embed.fields.push({ - // name: cat.name, - // value: fieldText - // }) - // } - // let statusDesc = "<:online:1307359583785713744> All Systems Operational" - // if (offline > 0 && offline !== total) { - // statusDesc = "<:degraded:1307359619491954778> Degraded Service" - // } else if(offline === total) { - // statusDesc = "<:Offline:1307359600592424971> Full Outage" - // } - // embed.description = `${status.info.description}\n\n${statusDesc}` - for (cat of status.status) { - let fieldText = ""; - let fieldParts = []; - - for (monitor of cat.monitors) { - const isOnline = Boolean(monitor.heartbeats[0].status); // Use Boolean() for clarity - console.log(`Monitor: ${monitor.name}, Status: ${isOnline}`); - const monitorText = `${isOnline ? "<:online:1307359583785713744>" : "<:offline:1307359600592424971>"} ${monitor.name}\n`; +const STATUS_EMOJIS = { + online: "<:online:1307359583785713744>", + offline: "<:offline:1307359600592424971>", + degraded: "<:degraded:1307359619491954778>", +}; - // If the monitor is offline, increment the offline count - if (!isOnline) offline++; - total++; +const STATUS_INFO = { + operational: { + text: "All Systems Operational", + color: 0x43b581, // Green + emoji: STATUS_EMOJIS.online, + }, + degraded: { + text: "Degraded Service", + color: 0xfaa61a, // Orange + emoji: STATUS_EMOJIS.degraded, + }, + outage: { + text: "Full Outage", + color: 0xf04747, // Red + emoji: STATUS_EMOJIS.offline, + }, +}; - // Check if adding this monitor's text will exceed 1024 characters - if (fieldText.length + monitorText.length > 1024) { - // Push the current field text and start a new field - fieldParts.push(fieldText.trim()); - fieldText = monitorText; // Start new field with this monitor's text - } else { - // Otherwise, just add the monitor's text to the current field - fieldText += monitorText; - } - } - - // Push any remaining text in fieldText after processing all monitors - if (fieldText.trim()) { - fieldParts.push(fieldText.trim()); - } - - // Now, add each part as a separate field - for (let i = 0; i < fieldParts.length; i++) { - embed.fields.push({ - name: i === 0 ? cat.name : `More ${cat.name}`, - value: fieldParts[i] - }); - } - } - - let statusDesc = "<:online:1307359583785713744> All Systems Operational"; - embed.color = 0x43b581 - if (offline > 0 && offline !== total) { - statusDesc = "<:degraded:1307359619491954778> Degraded Service"; - embed.color = 0xfaa61a - } else if(offline === total) { - statusDesc = "<:Offline:1307359600592424971> Full Outage"; - embed.color = 0xf04747 - } - - embed.description = `${status.info.description !== null ? `${status.info.description}\n\n` : ""}${statusDesc}`; - - resolve(embed) - }) - }) -} - -Client.on('ready', async () => { - console.log(`Logged in as ${Client.user.displayName}`); - for (const channelId in subs) { - const channel = await Client.channels.fetch(channelId) - messages = await channel.messages.fetch({ limit: 10 }) - var message = messages.find(msg => msg.author.id === Client.user.id); - if (!message) message = await channel.send({embeds:[{description:"Loading..."}]}); - getStatus(subs[channelId]).then((status) => { - status.timestamp = new Date() - message.edit({embeds:[status]}) - }) - cron.schedule("*/5 * * * *", () => { - getStatus(subs[channelId]).then((status) => { - status.timestamp = new Date() - message.edit({embeds:[status]}) - }) - }) - } +const kuma = new UptimeKuma(KUMA_BASE_URL); +const client = new Client({ + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages], }); -Client.login(process.env.TOKEN) \ No newline at end of file +async function createStatusEmbed(statusPageSlug) { + try { + const statusData = await kuma.status(statusPageSlug); + const embed = new EmbedBuilder() + .setTitle(statusData.info.title) + .setThumbnail(statusData.info.icon); + + let totalMonitors = 0; + let offlineMonitors = 0; + + for (const category of statusData.status) { + let fieldText = ""; + for (const monitor of category.monitors) { + totalMonitors++; + const isOnline = monitor.heartbeats[0]?.status === 1; + if (!isOnline) { + offlineMonitors++; + } + const emoji = isOnline ? STATUS_EMOJIS.online : STATUS_EMOJIS.offline; + fieldText += `${emoji} ${monitor.name}\n`; + } + + // Discord embed fields have a 1024 character limit. + // This splits the text into multiple fields if necessary. + const fieldChunks = fieldText.match(/[\s\S]{1,1024}/g) || []; + fieldChunks.forEach((chunk, index) => { + embed.addFields({ + name: index === 0 ? category.name : `${category.name} (cont.)`, + value: chunk, + }); + }); + } + + const status = determineOverallStatus(offlineMonitors, totalMonitors); + const description = statusData.info.description + ? `${statusData.info.description}\n\n${status.emoji} ${status.text}` + : `${status.emoji} ${status.text}`; + + embed + .setDescription(description) + .setColor(status.color) + .setTimestamp(new Date()); + + return embed; + } catch (error) { + console.error(`Error fetching status for "${statusPageSlug}":`, error); + return new EmbedBuilder() + .setColor(STATUS_INFO.outage.color) + .setDescription("An error occurred while fetching status data."); + } +} + +function determineOverallStatus(offlineCount, totalCount) { + if (offlineCount === 0) { + return STATUS_INFO.operational; + } + if (offlineCount === totalCount) { + return STATUS_INFO.outage; + } + return STATUS_INFO.degraded; +} + +async function findOrCreateStatusMessage(channel) { + const messages = await channel.messages.fetch({ limit: 25 }); + let message = messages.find((msg) => msg.author.id === client.user.id); + + if (!message) { + const loadingEmbed = new EmbedBuilder().setDescription("Initializing status panel..."); + message = await channel.send({ embeds: [loadingEmbed] }); + } + return message; +} + +async function updateAllStatusMessages() { + console.log("Updating all status messages..."); + for (const [channelId, slug] of Object.entries(subs)) { + try { + const channel = await client.channels.fetch(channelId); + if (!channel || !channel.isTextBased()) { + console.warn(`Channel ${channelId} not found or is not a text channel.`); + continue; + } + + const message = await findOrCreateStatusMessage(channel); + const embed = await createStatusEmbed(slug); + await message.edit({ embeds: [embed] }); + } catch (error) { + console.error(`Failed to update status for channel ${channelId}:`, error); + } + } + console.log("Finished updating status messages."); +} + +client.once("ready", async () => { + console.log(`Logged in as ${client.user.tag}`); + await updateAllStatusMessages(); // Initial update on startup + cron.schedule(CRON_SCHEDULE, updateAllStatusMessages); + console.log(`Scheduled status updates with cron schedule: ${CRON_SCHEDULE}`); +}); + +client.login(DISCORD_TOKEN); \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..03ff61d --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,536 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + discord.js: + specifier: ^14.16.3 + version: 14.21.0 + dotenv: + specifier: ^16.4.5 + version: 16.6.1 + node-cron: + specifier: ^3.0.3 + version: 3.0.3 + uptimekuma-api: + specifier: github:ChrisChrome/uptimekuma-api + version: https://codeload.github.com/ChrisChrome/uptimekuma-api/tar.gz/501d6114a9daf7b073771a20556c2a3fcf67e696 + +packages: + + '@discordjs/builders@1.11.2': + resolution: {integrity: sha512-F1WTABdd8/R9D1icJzajC4IuLyyS8f3rTOz66JsSI3pKvpCAtsMBweu8cyNYsIyvcrKAVn9EPK+Psoymq+XC0A==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@1.5.3': + resolution: {integrity: sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==} + engines: {node: '>=16.11.0'} + + '@discordjs/collection@2.1.1': + resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==} + engines: {node: '>=18'} + + '@discordjs/formatters@0.6.1': + resolution: {integrity: sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg==} + engines: {node: '>=16.11.0'} + + '@discordjs/rest@2.5.1': + resolution: {integrity: sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw==} + engines: {node: '>=18'} + + '@discordjs/util@1.1.1': + resolution: {integrity: sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==} + engines: {node: '>=18'} + + '@discordjs/ws@1.2.3': + resolution: {integrity: sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==} + engines: {node: '>=16.11.0'} + + '@sapphire/async-queue@1.5.5': + resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@sapphire/shapeshift@4.0.0': + resolution: {integrity: sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==} + engines: {node: '>=v16'} + + '@sapphire/snowflake@3.5.3': + resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + + '@types/node@24.0.13': + resolution: {integrity: sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@vladfrangu/async_event_emitter@2.4.6': + resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==} + engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.6.0: + resolution: {integrity: sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + discord-api-types@0.38.16: + resolution: {integrity: sha512-Cz42dC5WqJD17Yk0bRy7YLTJmh3NKo4FGpxZuA8MHqT0RPxKSrll5YhlODZ2z5DiEV/gpHMeTSrTFTWpSXjT1Q==} + + discord.js@14.21.0: + resolution: {integrity: sha512-U5w41cEmcnSfwKYlLv5RJjB8Joa+QJyRwIJz5i/eg+v2Qvv6EYpCRhN9I2Rlf0900LuqSDg8edakUATrDZQncQ==} + engines: {node: '>=18'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + engine.io-client@6.6.3: + resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} + + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.3: + resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} + engines: {node: '>= 6'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + magic-bytes.js@1.12.1: + resolution: {integrity: sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + node-cron@3.0.3: + resolution: {integrity: sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==} + engines: {node: '>=6.0.0'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + socket.io-client@4.8.1: + resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} + engines: {node: '>=10.0.0'} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + ts-mixer@6.0.4: + resolution: {integrity: sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + + undici@6.21.3: + resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} + engines: {node: '>=18.17'} + + uptimekuma-api@https://codeload.github.com/ChrisChrome/uptimekuma-api/tar.gz/501d6114a9daf7b073771a20556c2a3fcf67e696: + resolution: {tarball: https://codeload.github.com/ChrisChrome/uptimekuma-api/tar.gz/501d6114a9daf7b073771a20556c2a3fcf67e696} + version: 1.1.0 + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.3: + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xmlhttprequest-ssl@2.1.2: + resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} + engines: {node: '>=0.4.0'} + +snapshots: + + '@discordjs/builders@1.11.2': + dependencies: + '@discordjs/formatters': 0.6.1 + '@discordjs/util': 1.1.1 + '@sapphire/shapeshift': 4.0.0 + discord-api-types: 0.38.16 + fast-deep-equal: 3.1.3 + ts-mixer: 6.0.4 + tslib: 2.8.1 + + '@discordjs/collection@1.5.3': {} + + '@discordjs/collection@2.1.1': {} + + '@discordjs/formatters@0.6.1': + dependencies: + discord-api-types: 0.38.16 + + '@discordjs/rest@2.5.1': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/util': 1.1.1 + '@sapphire/async-queue': 1.5.5 + '@sapphire/snowflake': 3.5.3 + '@vladfrangu/async_event_emitter': 2.4.6 + discord-api-types: 0.38.16 + magic-bytes.js: 1.12.1 + tslib: 2.8.1 + undici: 6.21.3 + + '@discordjs/util@1.1.1': {} + + '@discordjs/ws@1.2.3': + dependencies: + '@discordjs/collection': 2.1.1 + '@discordjs/rest': 2.5.1 + '@discordjs/util': 1.1.1 + '@sapphire/async-queue': 1.5.5 + '@types/ws': 8.18.1 + '@vladfrangu/async_event_emitter': 2.4.6 + discord-api-types: 0.38.16 + tslib: 2.8.1 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@sapphire/async-queue@1.5.5': {} + + '@sapphire/shapeshift@4.0.0': + dependencies: + fast-deep-equal: 3.1.3 + lodash: 4.17.21 + + '@sapphire/snowflake@3.5.3': {} + + '@socket.io/component-emitter@3.1.2': {} + + '@types/node@24.0.13': + dependencies: + undici-types: 7.8.0 + + '@types/ws@8.18.1': + dependencies: + '@types/node': 24.0.13 + + '@vladfrangu/async_event_emitter@2.4.6': {} + + asynckit@0.4.0: {} + + axios@1.6.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.3 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + delayed-stream@1.0.0: {} + + discord-api-types@0.38.16: {} + + discord.js@14.21.0: + dependencies: + '@discordjs/builders': 1.11.2 + '@discordjs/collection': 1.5.3 + '@discordjs/formatters': 0.6.1 + '@discordjs/rest': 2.5.1 + '@discordjs/util': 1.1.1 + '@discordjs/ws': 1.2.3 + '@sapphire/snowflake': 3.5.3 + discord-api-types: 0.38.16 + fast-deep-equal: 3.1.3 + lodash.snakecase: 4.1.1 + magic-bytes.js: 1.12.1 + tslib: 2.8.1 + undici: 6.21.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + engine.io-client@6.6.3: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + xmlhttprequest-ssl: 2.1.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + engine.io-parser@5.2.3: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + fast-deep-equal@3.1.3: {} + + follow-redirects@1.15.9: {} + + form-data@4.0.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + lodash.snakecase@4.1.1: {} + + lodash@4.17.21: {} + + magic-bytes.js@1.12.1: {} + + math-intrinsics@1.1.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + ms@2.1.3: {} + + node-cron@3.0.3: + dependencies: + uuid: 8.3.2 + + proxy-from-env@1.1.0: {} + + socket.io-client@4.8.1: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + engine.io-client: 6.6.3 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + ts-mixer@6.0.4: {} + + tslib@2.8.1: {} + + undici-types@7.8.0: {} + + undici@6.21.3: {} + + uptimekuma-api@https://codeload.github.com/ChrisChrome/uptimekuma-api/tar.gz/501d6114a9daf7b073771a20556c2a3fcf67e696: + dependencies: + axios: 1.6.0 + socket.io-client: 4.8.1 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + uuid@8.3.2: {} + + ws@8.17.1: {} + + ws@8.18.3: {} + + xmlhttprequest-ssl@2.1.2: {}