diff --git a/assets/offline.jpg b/assets/offline.jpg new file mode 100644 index 0000000..a755c12 Binary files /dev/null and b/assets/offline.jpg differ diff --git a/commands/channels/channels.js b/commands/channels/channels.js new file mode 100644 index 0000000..61f23b0 --- /dev/null +++ b/commands/channels/channels.js @@ -0,0 +1,260 @@ +const { configDotenv } = require('dotenv'); +const { MongoClient } = require('mongodb'); +const TwitchApi = require("node-twitch").default +const tClient = new TwitchApi({ + client_id: process.env.TTV_ID, + client_secret: process.env.TTV_SECRET +}); +configDotenv +const mClient = new MongoClient(process.env.MONGO_URL); +const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); + +async function SubscribeChannel(interaction) { + const channelName = encodeURI(await interaction.options.getString('channel')).toLowerCase() + const userID = interaction.user.id + try { + let streamData = await tClient.getStreams({ channel: channelName }) + //console.log(await tClient.searchChannels({query: `${channelName}`})) // returns too many results and not exact match first + } catch (error) { + return interaction.reply({ + content: `**[ERROR]:** Could not validate channel name for *${channelName}*!\r\n${error}`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } + + const db = mClient.db('notifyme') + const channelsColl = db.collection('channels') + + const find = await channelsColl.find({ channel: channelName }).toArray() + + if (find[0]) { + if (find[0].users.includes(userID)) { + return interaction.reply({ + content: `**[WARNING]:** You are already subscribed to *${channelName}*!`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } + } + + try { + const res = await channelsColl.findOneAndUpdate({ + channel: channelName + }, { + $set: { + channel: channelName, + }, + $push: { + users: userID + } + }, { + upsert: true, + returnDocument: 'after' + }) + } catch (error) { + return interaction.reply({ + content: `**[ERROR]:** There was an issue updating the database!\r\n${error}`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } + //console.log(res) // debug + return interaction.reply({ + content: `**[SUCCESS]:** You are now subscribed to *${channelName}*!`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) +} + +async function UnsubscribeChannel(interaction) { + const channelName = encodeURI(await interaction.options.getString('channel')).toLowerCase() + const userID = interaction.user.id + + const db = mClient.db('notifyme') + const channelsColl = db.collection('channels') + + const find = await channelsColl.find({ channel: channelName }).toArray() + + if (find[0]) { + if (!find[0].users.includes(userID)) { + return interaction.reply({ + content: `**[WARNING]:** You were not subscribed to *${channelName}*!`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } + } + + try { + const res = await channelsColl.findOneAndUpdate({ + channel: channelName + }, { + $set: { + channel: channelName, + }, + $pull: { + users: userID + } + }, { + upsert: true, + returnDocument: 'after' + }) + } catch (error) { + return interaction.reply({ + content: `**[ERROR]:** There was an issue with the database!\r\n${error}`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } + //console.log(res) // debug + return interaction.reply({ + content: `**[SUCCESS]:** You are no longer subscribed to *${channelName}*!`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) +} + +async function ListChannel(interaction) { + const userID = interaction.user.id + + const db = mClient.db('notifyme') + const channelsColl = db.collection('channels') + + const find = await channelsColl.find({ users: userID }).toArray() + var channelList = [] + find.forEach((document) => { + channelList.push(document.channel) + }) + const embed = new EmbedBuilder() + .setTitle('Lists of Subscribed Channels:') + .setDescription(channelList.join("\n")) + + return interaction.reply({ + embeds: [embed], + ephemeral: true + }) +} + +async function InfoChannel(interaction) { + const channelName = encodeURI(await interaction.options.getString('channel')).toLowerCase() + try { + let streamData = await tClient.getStreams({ channel: channelName }) + if (streamData?.data[0]) { + let liveData = { + streamer: streamData.data[0].user_name, + game: streamData.data[0].game_name, + title: streamData.data[0].title, + thumbnail: streamData.data[0].thumbnail_url.replace('-{width}x{height}', ''), + tags: streamData.data[0].tags + } + const embed = new EmbedBuilder() + .setTitle(`${liveData.streamer} is live!`) + .setDescription(`They're playing ${liveData.game}`) + .addFields( + { name: '\u200B', value: `${liveData.title}` }) + .setImage(liveData.thumbnail) + .setURL(`https://twitch.tv/${channelName}`) + let footer = "" + liveData.tags.forEach((tag) => { + footer += `${footer?',':''} #${tag}` + }) + embed.setFooter({ + text: footer + }) + + return interaction.reply({ + embeds: [embed], + ephemeral: true + }) + } else { + const embed = new EmbedBuilder() + .setTitle(`${channelName} is currently offline!`) + .setImage('https://media.discordapp.net/attachments/1061304429724319794/1319800268770250883/no-signal-tv-descendant-network-rainbow-bars-abstract-background-vector.jpg?ex=67674748&is=6765f5c8&hm=d539944a67fccec461b0183a9f0300e19ac485deda7b23090165088567f2c84f&=&format=webp') + .setURL(`https://twitch.tv/${channelName}`) + return interaction.reply({ + embeds: [embed], + ephemeral: true + }) + } + //streamData = streamData. + //console.log(await tClient.searchChannels({query: `${channelName}`})) // returns too many results and not exact match first + } catch (error) { + console.error(error) + return interaction.reply({ + content: `**[ERROR]:** Could not validate channel name for *${channelName}*!\r\n${error}`, + ephemeral: true + }).then(setTimeout(() => { + interaction.deleteReply() + }, 5000)) + } +} + +module.exports = { + data: new SlashCommandBuilder() + .setName('channel') + .setDescription('channel related commands') + .addSubcommand(s => + s + .setName('subscribe') + .setDescription('subscribe to notifications when this channel goes live') + .addStringOption(o => + o + .setName('channel') + .setDescription('channel name') + .setRequired(true) + ) + ) + .addSubcommand(s => + s + .setName('unsubscribe') + .setDescription('unsubscribe to notifications when this channel goes live') + .addStringOption(o => + o + .setName('channel') + .setDescription('channel name') + .setRequired(true) + ) + ) + .addSubcommand(s => + s + .setName('list') + .setDescription('list your subscribed channels') + ) + .addSubcommand(s => + s + .setName('info') + .setDescription('get information on a live channel') + .addStringOption(o => + o + .setName('channel') + .setDescription('channel name') + .setRequired(true) + ) + ), + async execute(interaction) { + switch (interaction.options._subcommand) { + case 'subscribe': + SubscribeChannel(interaction) + break; + case 'unsubscribe': + UnsubscribeChannel(interaction) + break; + case 'list': + ListChannel(interaction) + break; + case 'info': + InfoChannel(interaction) + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/events/ClientReady.js b/events/ClientReady.js new file mode 100644 index 0000000..ba7dc2c --- /dev/null +++ b/events/ClientReady.js @@ -0,0 +1,17 @@ +const { Events, ActivityType } = require('discord.js'); +module.exports = { + name: Events.ClientReady, + once: true, + async execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`) + client.user.setPresence({ + activities: [{ + name: 'Notyfing', + type: ActivityType.Streaming, + url: 'https://twitch.tv/desq_blocki' + }], + status: 'online' + }) + + } +} \ No newline at end of file diff --git a/events/InteractionCreate.js b/events/InteractionCreate.js new file mode 100644 index 0000000..5fae1b1 --- /dev/null +++ b/events/InteractionCreate.js @@ -0,0 +1,27 @@ +const { Events } = require('discord.js') + +module.exports = { + name: Events.InteractionCreate, + once: false, + async execute(interaction) { + if (interaction.isChatInputCommand()) { commandHandler(interaction) }; + } +} + +async function commandHandler(interaction) { + const command = interaction.client.commands.get(interaction.commandName); + if (!command) { + console.error(`No command matching ${interaction.commandName} was found.`); + return; + } + try { + await command.execute(interaction); + } catch (error) { + console.error(error); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }); + } else { + await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } + } +} \ No newline at end of file diff --git a/handlers/commands.js b/handlers/commands.js new file mode 100644 index 0000000..fe46475 --- /dev/null +++ b/handlers/commands.js @@ -0,0 +1,48 @@ +const { REST, Routes } = require('discord.js'); +const { configDotenv } = require('dotenv'); +configDotenv +const fs = require('node:fs'); +const path = require('node:path'); +const { dClient } = require('../index'); + +const commands = []; +// Grab all the command folders from the commands directory you created earlier +const foldersPath = path.join(__dirname, '../commands'); +const commandFolders = fs.readdirSync(foldersPath); + +for (const folder of commandFolders) { + // Grab all the command files from the commands directory you created earlier + const commandsPath = path.join(foldersPath, folder); + const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); + for (const file of commandFiles) { + const filePath = path.join(commandsPath, file); + const command = require(filePath); + if ('data' in command && 'execute' in command) { + commands.push(command.data.toJSON()); + dClient.commands.set(command.data.name, command); + } else { + console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`); + } + } +} + +// Construct and prepare an instance of the REST module +const rest = new REST().setToken(process.env.DISCORD_Token); + +// and deploy your commands! +(async () => { + try { + console.log(`Started refreshing ${commands.length} application (/) commands.`); + + // The put method is used to fully refresh all commands in the guild with the current set + const data = await rest.put( + Routes.applicationCommands(process.env.DISCORD_ID), + { body: commands }, + ); + + console.log(`Successfully reloaded ${data.length} application (/) commands.`); + } catch (error) { + // And of course, make sure you catch and log any errors! + console.error(error); + } +})(); \ No newline at end of file diff --git a/handlers/events.js b/handlers/events.js new file mode 100644 index 0000000..fba429b --- /dev/null +++ b/handlers/events.js @@ -0,0 +1,18 @@ +const fs = require('node:fs') +const path = require('node:path') +const { dClient } = require('../index') + +const eventsPath = path.join(__dirname, '../events') +const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')) + +for (const file of eventFiles) { + const filePath = path.join(eventsPath, file) + const event = require(filePath) + if (event.once) { + dClient.once(event.name, (...args) => event.execute(...args, dClient)) + // added dClient to commomerate global usage + } else { + dClient.on(event.name, (...args) => event.execute(...args, dClient)) + // added dClient to commomerate global usage + } +} diff --git a/index.js b/index.js index 751f4d6..7270bc6 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,7 @@ -const { Client, Events, GatewayIntentBits, Partials, EmbedBuilder } = require('discord.js'); -const client = new Client({ +require('dotenv').config() +const { Client, Collection, GatewayIntentBits, Partials } = require('discord.js'); +const fs = require('node:fs') +const dClient = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, @@ -13,126 +15,125 @@ const client = new Client({ ] }); -const TwitchApi = require("node-twitch").default -const fs = require('fs') -const channels = JSON.parse(fs.readFileSync('./channels.json', 'utf-8')) -console.log(channels) -const isLive = new Set() -require('dotenv').config() +dClient.commands = new Collection() // slash commands collection +exports.dClient = dClient -const TwitchClient = new TwitchApi({ - client_id: process.env.TTV_ID, - client_secret: process.env.TTV_SECRET -}); -async function getStreamdata(stream) { - var streamData - await TwitchClient.getStreams({ channel: stream }).then(async data => { - const r = data.data[0] - if (r) { - //stream online - if (!isLive.has(stream)) { - //not yet in memory - streamData = { - "game": r.game_name, - "title": r.title, - } - isLive.add(stream) - } else { - //already in memory - } - } else { - //stream offline - if (isLive.has(stream)) { - //was in memory - console.log(`${stream} went offline :c`) - isLive.delete(stream) - } else { - //was not in memory - } - } - }) - return streamData -} - -async function doInterval() { - const guild = client.guilds.fetch('848610258306072576') - for (const [key, value] of Object.entries(channels)) { - //key: channel, value: [ users ] - let streamdata = await getStreamdata(key) - if(streamdata){ - value.forEach(async userID =>{ - (await guild).members.fetch(userID) - .then((u => { - u.send(`https://twitch.tv/${key} is live!`) - console.log(`${key} is live!`) - })) - }) - } - } -} -client.once(Events.ClientReady, async client => { - console.log(`Ready! Logged in as ${client.user.tag}`) - doInterval() - setInterval(async () => { - doInterval() - }, 2000) +fs.readdirSync('./handlers').forEach((handler) => { + require(`./handlers/${handler}`) }); -client.on(Events.MessageCreate, async (msg) => { - if (msg.author.bot) { return } - console.log(msg.content) - if (!msg.content.startsWith('!')) { return } +dClient.login(process.env.DISCORD_Token) - const args = msg.content.substring(1).split(' ') - switch (args[0]) { - case "add": - addChannel(args[1], msg) - break; - case "remove": - delChannel(args[1], msg) - break; - case "list": - listChannels(msg) - default: - break; - } -}) -function addChannel(channel, msg) { - if (!channels[channel]) { - channels[channel] = [msg.author.id] - } else { - channels[channel].push(msg.author.id) - } - fs.writeFileSync('./channels.json', JSON.stringify(channels), 'utf-8') - msg.reply({ - content: `Subscribed to [${channel}] Notifications!` - }) -} -function delChannel(channel, msg) { - let index = channels[channel].indexOf(msg.author.id) - channels[channel].splice(index) - if (channels[channel].length === 0) { - delete channels[channel] - } - fs.writeFileSync('./channels.json', JSON.stringify(channels), 'utf-8') - msg.reply({ - content: `Unsubscribed from [${channel}] Notifications!` - }) -} -function listChannels(msg){ - let subscribed = [] - let embed = new EmbedBuilder() - .setTitle('Lists of Subscribed Channels:') - for (const [key, value] of Object.entries(channels)) { - if(value.includes(msg.author.id)){ - subscribed.push(key) - } - } - embed.setDescription(subscribed.join("\n")) +// async function getStreamdata(stream) { +// var streamData +// await TwitchClient.getStreams({ channel: stream }).then(async data => { +// const r = data.data[0] +// if (r) { +// //stream online +// if (!isLive.has(stream)) { +// //not yet in memory +// streamData = { +// "game": r.game_name, +// "title": r.title, +// } +// isLive.add(stream) +// } else { +// //already in memory +// } +// } else { +// //stream offline +// if (isLive.has(stream)) { +// //was in memory +// console.log(`${stream} went offline :c`) +// isLive.delete(stream) +// } else { +// //was not in memory +// } +// } +// }) +// return streamData +// } + +// async function doInterval() { +// const guild = client.guilds.fetch('848610258306072576') +// for (const [key, value] of Object.entries(channels)) { +// //key: channel, value: [ users ] +// let streamdata = await getStreamdata(key) +// if(streamdata){ +// value.forEach(async userID =>{ +// (await guild).members.fetch(userID) +// .then((u => { +// u.send(`https://twitch.tv/${key} is live!`) +// console.log(`${key} is live!`) +// })) +// }) +// } +// } +// } +// client.once(Events.ClientReady, async client => { +// console.log(`Ready! Logged in as ${client.user.tag}`) +// doInterval() +// setInterval(async () => { +// doInterval() +// }, 2000) +// }); + +// client.on(Events.MessageCreate, async (msg) => { +// if (msg.author.bot) { return } +// console.log(msg.content) +// if (!msg.content.startsWith('!')) { return } + +// const args = msg.content.substring(1).split(' ') +// switch (args[0]) { +// case "add": +// addChannel(args[1], msg) +// break; +// case "remove": +// delChannel(args[1], msg) +// break; +// case "list": +// listChannels(msg) +// default: +// break; +// } +// }) + +// function addChannel(channel, msg) { +// if (!channels[channel]) { +// channels[channel] = [msg.author.id] +// } else { +// channels[channel].push(msg.author.id) +// } +// fs.writeFileSync('./channels.json', JSON.stringify(channels), 'utf-8') +// msg.reply({ +// content: `Subscribed to [${channel}] Notifications!` +// }) +// } +// function delChannel(channel, msg) { +// let index = channels[channel].indexOf(msg.author.id) +// channels[channel].splice(index) +// if (channels[channel].length === 0) { +// delete channels[channel] +// } +// fs.writeFileSync('./channels.json', JSON.stringify(channels), 'utf-8') +// msg.reply({ +// content: `Unsubscribed from [${channel}] Notifications!` +// }) +// } +// function listChannels(msg){ +// let subscribed = [] +// let embed = new EmbedBuilder() +// .setTitle('Lists of Subscribed Channels:') +// for (const [key, value] of Object.entries(channels)) { +// if(value.includes(msg.author.id)){ +// subscribed.push(key) +// } +// } +// embed.setDescription(subscribed.join("\n")) - msg.reply({ - embeds: [embed] - }) -} -client.login(process.env.DISCORD_Token); +// msg.reply({ +// embeds: [embed] +// }) +// } +// client.login(process.env.DISCORD_Token); diff --git a/package-lock.json b/package-lock.json index 99524f2..5ae8a05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,215 +5,426 @@ "packages": { "": { "dependencies": { - "discord.js": "^14.7.1", + "discord.js": "^14.16.3", "dotenv": "^16.0.3", + "mongodb": "^6.12.0", "node-twitch": "^0.5.0" } }, "node_modules/@discordjs/builders": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", - "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.9.0.tgz", + "integrity": "sha512-0zx8DePNVvQibh5ly5kCEei5wtPBIUbSoE9n+91Rlladz4tgtFbJ36PZMxxZrTEOQ7AHMZ/b0crT/0fCy6FTKg==", + "license": "Apache-2.0", "dependencies": { - "@discordjs/util": "^0.1.0", - "@sapphire/shapeshift": "^3.7.1", - "discord-api-types": "^0.37.20", + "@discordjs/formatters": "^0.5.0", + "@discordjs/util": "^1.1.1", + "@sapphire/shapeshift": "^4.0.0", + "discord-api-types": "0.37.97", "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.2", - "tslib": "^2.4.1" + "ts-mixer": "^6.0.4", + "tslib": "^2.6.3" }, "engines": { - "node": ">=16.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, + "node_modules/@discordjs/builders/node_modules/discord-api-types": { + "version": "0.37.97", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz", + "integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==", + "license": "MIT" + }, "node_modules/@discordjs/collection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.3.0.tgz", - "integrity": "sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", + "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", + "license": "Apache-2.0", "engines": { - "node": ">=16.9.0" + "node": ">=16.11.0" } }, - "node_modules/@discordjs/rest": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.5.0.tgz", - "integrity": "sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==", + "node_modules/@discordjs/formatters": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.5.0.tgz", + "integrity": "sha512-98b3i+Y19RFq1Xke4NkVY46x8KjJQjldHUuEbCqMvp1F5Iq9HgnGpu91jOi/Ufazhty32eRsKnnzS8n4c+L93g==", + "license": "Apache-2.0", "dependencies": { - "@discordjs/collection": "^1.3.0", - "@discordjs/util": "^0.1.0", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.23", - "file-type": "^18.0.0", - "tslib": "^2.4.1", - "undici": "^5.13.0" + "discord-api-types": "0.37.97" }, "engines": { - "node": ">=16.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, - "node_modules/@discordjs/util": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.1.0.tgz", - "integrity": "sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==", + "node_modules/@discordjs/formatters/node_modules/discord-api-types": { + "version": "0.37.97", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz", + "integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==", + "license": "MIT" + }, + "node_modules/@discordjs/rest": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.4.0.tgz", + "integrity": "sha512-Xb2irDqNcq+O8F0/k/NaDp7+t091p+acb51iA4bCKfIn+WFWd6HrNvcsSbMMxIR9NjcMZS6NReTKygqiQN+ntw==", + "license": "Apache-2.0", + "dependencies": { + "@discordjs/collection": "^2.1.1", + "@discordjs/util": "^1.1.1", + "@sapphire/async-queue": "^1.5.3", + "@sapphire/snowflake": "^3.5.3", + "@vladfrangu/async_event_emitter": "^2.4.6", + "discord-api-types": "0.37.97", + "magic-bytes.js": "^1.10.0", + "tslib": "^2.6.3", + "undici": "6.19.8" + }, "engines": { - "node": ">=16.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest/node_modules/@discordjs/collection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz", + "integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/rest/node_modules/discord-api-types": { + "version": "0.37.97", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.97.tgz", + "integrity": "sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==", + "license": "MIT" + }, + "node_modules/@discordjs/util": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz", + "integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.1.1.tgz", + "integrity": "sha512-PZ+vLpxGCRtmr2RMkqh8Zp+BenUaJqlS6xhgWKEZcgC/vfHLEzpHtKkB0sl3nZWpwtcKk6YWy+pU3okL2I97FA==", + "license": "Apache-2.0", + "dependencies": { + "@discordjs/collection": "^2.1.0", + "@discordjs/rest": "^2.3.0", + "@discordjs/util": "^1.1.0", + "@sapphire/async-queue": "^1.5.2", + "@types/ws": "^8.5.10", + "@vladfrangu/async_event_emitter": "^2.2.4", + "discord-api-types": "0.37.83", + "tslib": "^2.6.2", + "ws": "^8.16.0" + }, + "engines": { + "node": ">=16.11.0" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws/node_modules/@discordjs/collection": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz", + "integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" + } + }, + "node_modules/@discordjs/ws/node_modules/discord-api-types": { + "version": "0.37.83", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz", + "integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==", + "license": "MIT" + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" } }, "node_modules/@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz", + "integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==", + "license": "MIT", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, "node_modules/@sapphire/shapeshift": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz", - "integrity": "sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-4.0.0.tgz", + "integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "lodash": "^4.17.21" }, "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" + "node": ">=v16" } }, "node_modules/@sapphire/snowflake": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz", - "integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz", + "integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==", + "license": "MIT", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, "node_modules/@types/node": { - "version": "18.15.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.0.tgz", - "integrity": "sha512-z6nr0TTEOBGkzLGmbypWOGnpSpSIBorEhC4L+4HeQ2iezKCi4f77kyslRwvHeNitymGQ+oFyIWGP96l/DPSV9w==" + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } }, "node_modules/@types/ws": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", - "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, + "node_modules/@vladfrangu/async_event_emitter": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.6.tgz", + "integrity": "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==", + "license": "MIT", "engines": { - "node": ">=10.16.0" + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/bson": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.1.tgz", + "integrity": "sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" } }, "node_modules/discord-api-types": { - "version": "0.37.35", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz", - "integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg==" + "version": "0.37.100", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.100.tgz", + "integrity": "sha512-a8zvUI0GYYwDtScfRd/TtaNBDTXwP5DiDVX7K5OmE+DRT57gBqKnwtOC5Ol8z0mRW8KQfETIgiB8U0YZ9NXiCA==", + "license": "MIT" }, "node_modules/discord.js": { - "version": "14.7.1", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.7.1.tgz", - "integrity": "sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==", + "version": "14.16.3", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.16.3.tgz", + "integrity": "sha512-EPCWE9OkA9DnFFNrO7Kl1WHHDYFXu3CNVFJg63bfU7hVtjZGyhShwZtSBImINQRWxWP2tgo2XI+QhdXx28r0aA==", + "license": "Apache-2.0", "dependencies": { - "@discordjs/builders": "^1.4.0", - "@discordjs/collection": "^1.3.0", - "@discordjs/rest": "^1.4.0", - "@discordjs/util": "^0.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.20", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.1", - "undici": "^5.13.0", - "ws": "^8.11.0" + "@discordjs/builders": "^1.9.0", + "@discordjs/collection": "1.5.3", + "@discordjs/formatters": "^0.5.0", + "@discordjs/rest": "^2.4.0", + "@discordjs/util": "^1.1.1", + "@discordjs/ws": "1.1.1", + "@sapphire/snowflake": "3.5.3", + "discord-api-types": "0.37.100", + "fast-deep-equal": "3.1.3", + "lodash.snakecase": "4.1.1", + "tslib": "^2.6.3", + "undici": "6.19.8" }, "engines": { - "node": ">=16.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/discordjs/discord.js?sponsor" } }, "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/file-type": { - "version": "18.2.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz", - "integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==", - "dependencies": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0", - "token-types": "^5.0.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.snakecase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "license": "MIT" + }, + "node_modules/magic-bytes.js": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz", + "integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==", + "license": "MIT" + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, + "node_modules/mongodb": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", + "integrity": "sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.1", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -233,166 +444,83 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/node-twitch/-/node-twitch-0.5.0.tgz", "integrity": "sha512-4sN4P8R5NeBuuBMZhqKHqLYB9fKcyR8sCU39eGKe/xU5TiFRA3M/2ou9FeyD5EU7EzAb7TgunKQOaY2wMdAFSQ==", + "license": "ISC", "dependencies": { "node-fetch": "2" } }, - "node_modules/peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">=6" } }, - "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "memory-pager": "^1.0.2" } }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/ts-mixer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", - "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz", + "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", + "license": "MIT" }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/undici": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz", - "integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==", - "dependencies": { - "busboy": "^1.6.0" - }, + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz", + "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==", + "license": "MIT", "engines": { - "node": ">=12.18" + "node": ">=18.17" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "license": "MIT" }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "node_modules/ws": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", - "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 7d4acb0..d0ff853 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "dependencies": { - "discord.js": "^14.7.1", + "discord.js": "^14.16.3", "dotenv": "^16.0.3", + "mongodb": "^6.12.0", "node-twitch": "^0.5.0" } }