diff --git a/apps/Leonidias/orchistrator/.dockerignore b/apps/Leonidias/orchistrator/.dockerignore new file mode 100644 index 000000000..37d7e7348 --- /dev/null +++ b/apps/Leonidias/orchistrator/.dockerignore @@ -0,0 +1,2 @@ +node_modules +.env diff --git a/apps/Leonidias/orchistrator/.env.example b/apps/Leonidias/orchistrator/.env.example new file mode 100644 index 000000000..1c5de46c4 --- /dev/null +++ b/apps/Leonidias/orchistrator/.env.example @@ -0,0 +1,3 @@ +DISCORD_TOKEN= +DISCORD_CLIENT_ID= +DISCORD_GUILD_ID= \ No newline at end of file diff --git a/apps/Leonidias/orchistrator/.gitignore b/apps/Leonidias/orchistrator/.gitignore new file mode 100644 index 000000000..1dcef2d9f --- /dev/null +++ b/apps/Leonidias/orchistrator/.gitignore @@ -0,0 +1,2 @@ +node_modules +.env \ No newline at end of file diff --git a/apps/Leonidias/orchistrator/Dockerfile b/apps/Leonidias/orchistrator/Dockerfile new file mode 100644 index 000000000..3a112e19a --- /dev/null +++ b/apps/Leonidias/orchistrator/Dockerfile @@ -0,0 +1,14 @@ +FROM node:19-slim + +WORKDIR /app + +COPY package.json /app +RUN npm install + +COPY . . + +ENV DISCORD_TOKEN "" \ + DISCORD_CLIENT_ID "" \ + DISCORD_GUILD_ID "" + +CMD [ "node", "index.js" ] diff --git a/apps/Leonidias/orchistrator/README.md b/apps/Leonidias/orchistrator/README.md new file mode 100644 index 000000000..b1e3b419f --- /dev/null +++ b/apps/Leonidias/orchistrator/README.md @@ -0,0 +1,42 @@ + +# Server-Bot + +[View on Docker Hub](https://hub.docker.com/r/allenrkeen/server-bot) +### Discord bot to remotely monitor and control a docker based server. Using the docker socket. + +Setup is pretty straightforward. +1. Create a new application in the *[discord developer portal](https://discord.com/developers/applications)* +2. Go to the bot section and click *Add Bot* +3. Reset Token and keep the token somewhere secure (This will be referred to as "DISCORD_TOKEN" in .env and docker environment variables) +4. Get the "Application ID" from the General Information tab of your application (This will be referred to as "DISCORD_CLIENT_ID" in .env and docker environment variables) +5. *Optional:* If you have developer mode enabled in Discord, get your server's ID by right-clicking on the server name and clicking "Copy ID" (This will be referred to as "DISCORD_GUILD_ID" in .env and docker environment variables) + - If you skip this, it will still work, but commands will be published globally instead of to your server and can take up to an hour to be available in your server. + - Using the Server ID will be more secure, making the commands available only in the specified server. +6. Run the application in your preffered method. + - Run the docker container with the provided [docker-compose.yml](docker-compose.yml) or the docker run command below. + + ```bash + docker run -v /var/run/docker.sock:/var/run/docker.sock --name server-bot \ + -e DISCORD_TOKEN=your_token_here \ + -e DISCORD_CLIENT_ID=your_client_id_here \ + -e DISCORD_GUILD_ID=your_guild_id_here \ + allenrkeen/server-bot:latest + ``` + + - Clone the repo, cd into the server-bot directory and run "npm install" to install dependencies, then "npm run start" to start the server +7. The program will build an invite link with the correct permissions and put it in the logs. Click the link and confirm the server to add the bot to. + + +Current commands: + - /allcontainers + - provides container name and status for all containers + - /restartcontainer + - provides an autocomplete list of running containers to select from, or just type in container name then restarts the container + - /stopcontainer + - provides an autocomplete list of running containers to select from, or just type in container name then stops the container + - /startcontainer + - provides an autocomplete list of stopped containers to select from, or just type in container name then starts the container + - /ping + - Replies with "Pong!" when the bot is listening + - /server + - Replies with Server Name and member count, good for testing. diff --git a/apps/Leonidias/orchistrator/backend/deleteCommands.js b/apps/Leonidias/orchistrator/backend/deleteCommands.js new file mode 100644 index 000000000..79a77b4ec --- /dev/null +++ b/apps/Leonidias/orchistrator/backend/deleteCommands.js @@ -0,0 +1,22 @@ +/* + * This file is used to delete all commands from the Discord API. + * Only use this if you want to delete all commands and understand the consequences. +*/ + +require('dotenv').config(); +const token = process.env.DISCORD_TOKEN; +const clientID = process.env.DISCORD_CLIENT_ID; +const guildID = process.env.DISCORD_GUILD_ID; +const { REST, Routes } = require('discord.js'); +const fs = require('node:fs'); + +const rest = new REST({ version: '10' }).setToken(token); + +rest.put(Routes.applicationCommands(clientID), { body: [] }) + .then(() => console.log('Successfully deleted application (/) commands.')) + .catch(console.error); + +rest.put(Routes.applicationGuildCommands(clientID, guildID), { body: [] }) + .then(() => console.log('Successfully deleted guild (/) commands.')) + .catch(console.error); + diff --git a/apps/Leonidias/orchistrator/backend/deployCommands.js b/apps/Leonidias/orchistrator/backend/deployCommands.js new file mode 100644 index 000000000..4034b6248 --- /dev/null +++ b/apps/Leonidias/orchistrator/backend/deployCommands.js @@ -0,0 +1,53 @@ +/* +This script pushes all commands in the commands folder to be usable in discord. +*/ + +require('dotenv').config(); +const token = process.env.DISCORD_TOKEN; +const clientID = process.env.DISCORD_CLIENT_ID; +const guildID = process.env.DISCORD_GUILD_ID; +const { REST, Routes } = require('discord.js'); +const fs = require('node:fs'); + +const commands = []; + +// Get all commands from the commands folder + +const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js')); +console.log(commandFiles); + +for (const file of commandFiles) { + const command = require(`../commands/${file}`); + commands.push(command.data.toJSON()); +} + +const rest = new REST({ version: '10' }).setToken(token); + +// console.log(commands); + +(async () => { + try { + const rest = new REST({ version: '10' }).setToken(token); + + console.log('Started refreshing application (/) commands.'); + + //publish to guild if guildID is set, otherwise publish to global + if (guildID) { + const data = await rest.put( + Routes.applicationGuildCommands(clientID, guildID), + { body: commands }, + ); + console.log('Successfully reloaded '+ data.length +' commands.'); + } else { + const data = await rest.put( + Routes.applicationCommands(clientID), + { body: commands }, + ); + console.log('Successfully reloaded '+ data.length +' commands.'); + } + + } catch (error) { + console.error(error); + } +})(); + diff --git a/apps/Leonidias/orchistrator/commands/allContainers.js b/apps/Leonidias/orchistrator/commands/allContainers.js new file mode 100644 index 000000000..452d24685 --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/allContainers.js @@ -0,0 +1,39 @@ +/* A command that lists all containers with their status */ + +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const Docker = require('node-docker-api').Docker; + +module.exports = { + data: new SlashCommandBuilder() + .setName("allcontainers") + .setDescription("Lists all containers"), + async execute(interaction) { + outArray = []; + interaction.reply('Listing all containers...'); + + //create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // get all containers + const containers = await docker.container.list({ all: true}); + + // create array of containers with name and status + outArray = containers.map(c => { + return { + name: c.data.Names[0].slice(1), + status: c.data.State + }; + }); + + embedCount = Math.ceil(outArray.length / 25); + for (let i = 0; i < embedCount; i++) { + const embed = new EmbedBuilder() + .setTitle('Containers') + .addFields(outArray.slice(i * 25, (i + 1) * 25).map(e => { + return { name: e.name, value: e.status }; + })) + .setColor(0x00AE86); + interaction.channel.send({ embeds: [embed] }); + } + }, +}; \ No newline at end of file diff --git a/apps/Leonidias/orchistrator/commands/ping.js b/apps/Leonidias/orchistrator/commands/ping.js new file mode 100644 index 000000000..2fee3436f --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/ping.js @@ -0,0 +1,14 @@ +/* +A ping command that replies with "Pong!" when bot is running. +*/ + +const { SlashCommandBuilder } = require("discord.js"); + +module.exports = { + data: new SlashCommandBuilder() + .setName("ping") + .setDescription("Replies with Pong!"), + async execute(interaction) { + await interaction.reply("Pong!"); + }, +}; \ No newline at end of file diff --git a/apps/Leonidias/orchistrator/commands/restart.js b/apps/Leonidias/orchistrator/commands/restart.js new file mode 100644 index 000000000..38a7b485e --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/restart.js @@ -0,0 +1,69 @@ +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const Docker = require('node-docker-api').Docker; + +module.exports = { + data: new SlashCommandBuilder() + .setName("restartcontainer") + .setDescription("Restarts a Docker container") + .addStringOption(option => + option.setName('container') + .setDescription('The container to restart') + .setRequired(true) + .setAutocomplete(true)), + async autocomplete(interaction) { + try { + // Create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // Get list of running containers + const containers = await docker.container.list({ all: true, filters: { status: ['running'] } }); + const runningContainers = containers.map(c => c.data.Names[0].slice(1)); + + // Filter list of containers by focused value + const focusedValue = interaction.options.getFocused(true); + const filteredContainers = runningContainers.filter(container => container.startsWith(focusedValue.value)); + + //slice if more than 25 + let sliced; + if (filteredContainers.length > 25) { + sliced = filteredContainers.slice(0, 25); + } else { + sliced = filteredContainers; + } + + // Respond with filtered list of containers + await interaction.respond(sliced.map(container => ({ name: container, value: container }))); + + } catch (error) { + // Handle error + console.error(error); + await interaction.reply('An error occurred while getting the list of running containers.'); + } + }, + async execute(interaction) { + try { + // create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // Get container name from options + const container = interaction.options.getString('container'); + + // Restart container + await interaction.reply(`Restarting container "${container}"...`); + const containers = await docker.container.list({ all: true, filters: { name: [container] } }); + if (containers.length === 0) { + await interaction.followUp(`Container "${container}" does not exist.`); + throw new Error(`Container "${container}" does not exist.`); + } + await containers[0].restart(); + + + // Confirm that container was restarted + await interaction.followUp(`Container "${container}" was successfully restarted.`); + } catch (error) { + // Handle error + console.error(error); + await interaction.followUp(`An error occurred while trying to restart the container "${container}".`); + } + } +}; diff --git a/apps/Leonidias/orchistrator/commands/server.js b/apps/Leonidias/orchistrator/commands/server.js new file mode 100644 index 000000000..ae2b6627e --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/server.js @@ -0,0 +1,10 @@ +const { SlashCommandBuilder } = require('discord.js'); + +module.exports = { + data: new SlashCommandBuilder() + .setName("server") + .setDescription("Replies with server name and member count."), + async execute(interaction) { + await interaction.reply(`Server name: ${interaction.guild.name}\nTotal members: ${interaction.guild.memberCount}`); + }, +}; diff --git a/apps/Leonidias/orchistrator/commands/startContainer.js b/apps/Leonidias/orchistrator/commands/startContainer.js new file mode 100644 index 000000000..43dc4e248 --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/startContainer.js @@ -0,0 +1,92 @@ +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const Docker = require('node-docker-api').Docker; + +module.exports = { + data: new SlashCommandBuilder() + .setName("startcontainer") + .setDescription("Starts a Docker container") + .addStringOption(option => + option.setName('container') + .setDescription('The container to start') + .setRequired(true) + .setAutocomplete(true)), + async autocomplete(interaction) { + try { + // Create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // Get list of running containers + const containers = await docker.container.list({ all: true, filters: { status: ['exited'] } }); + const runningContainers = containers.map(c => c.data.Names[0].slice(1)); + + // Filter list of containers by focused value + const focusedValue = interaction.options.getFocused(true); + const filteredContainers = runningContainers.filter(container => container.startsWith(focusedValue.value)); + + //slice if more than 25 + let sliced; + if (filteredContainers.length > 25) { + sliced = filteredContainers.slice(0, 25); + } else { + sliced = filteredContainers; + } + + // Respond with filtered list of containers + await interaction.respond(sliced.map(container => ({ name: container, value: container }))); + + } catch (error) { + // Handle error + console.error(error); + await interaction.reply('An error occurred while getting the list of running containers.'); + } + }, + async execute(interaction) { + try { + // Get container name from options + const containerName = interaction.options.getString('container'); + + // Start container in interactive mode + await interaction.reply(`Starting container "${containerName}" in interactive mode...`); + const container = docker.getContainer(containerName); + const info = await container.inspect(); + if (!info) { + await interaction.followUp(`Container "${containerName}" does not exist.`); + throw new Error(`Container "${containerName}" does not exist.`); + } + await container.start({ + AttachStdin: true, + AttachStdout: true, + AttachStderr: true, + Tty: true, + OpenStdin: true, + StdinOnce: false + }); + + // Attach to container's streams + const stream = await container.attach({ + stream: true, + stdin: true, + stdout: true, + stderr: true + }); + + // Use socket.io for real-time communication with the container + io.on('connection', (socket) => { + socket.on('containerInput', (data) => { + stream.write(data + '\n'); // Send input to the container + }); + + stream.on('data', (data) => { + socket.emit('containerOutput', data.toString()); // Send container's output to the client + }); + }); + + // Confirm that container was started + await interaction.followUp(`Container "${containerName}" was successfully started in interactive mode.`); + } catch (error) { + // Handle error + console.error(error); + await interaction.followUp(`An error occurred while trying to start the container "${containerName}" in interactive mode.`); + } + }, +}; diff --git a/apps/Leonidias/orchistrator/commands/stopContainer.js b/apps/Leonidias/orchistrator/commands/stopContainer.js new file mode 100644 index 000000000..d424c73d0 --- /dev/null +++ b/apps/Leonidias/orchistrator/commands/stopContainer.js @@ -0,0 +1,68 @@ +const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); +const Docker = require('node-docker-api').Docker; + +module.exports = { + data: new SlashCommandBuilder() + .setName("stopcontainer") + .setDescription("Stops a Docker container") + .addStringOption(option => + option.setName('container') + .setDescription('The container to stop') + .setRequired(true) + .setAutocomplete(true)), + async autocomplete(interaction) { + try { + // Create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // Get list of running containers + const containers = await docker.container.list({ all: true, filters: { status: ['running'] } }); + const runningContainers = containers.map(c => c.data.Names[0].slice(1)); + + // Filter list of containers by focused value + const focusedValue = interaction.options.getFocused(true); + const filteredContainers = runningContainers.filter(container => container.startsWith(focusedValue.value)); + + //slice if more than 25 + let sliced; + if (filteredContainers.length > 25) { + sliced = filteredContainers.slice(0, 25); + } else { + sliced = filteredContainers; + } + + // Respond with filtered list of containers + await interaction.respond(sliced.map(container => ({ name: container, value: container }))); + + } catch (error) { + // Handle error + console.error(error); + await interaction.reply('An error occurred while getting the list of running containers.'); + } + }, + async execute(interaction) { + try { + // create docker client + const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + + // Get container name from options + const container = interaction.options.getString('container'); + + // Restart container + await interaction.reply(`Stopping container "${container}"...`); + const containers = await docker.container.list({ all: true, filters: { name: [container] } }); + if (containers.length === 0) { + await interaction.followUp(`Container "${container}" does not exist.`); + throw new Error(`Container "${container}" does not exist.`); + } + await containers[0].stop(); + + // Confirm that container was restarted + await interaction.followUp(`Container "${container}" was successfully stopped.`); + } catch (error) { + // Handle error + console.error(error); + await interaction.followUp(`An error occurred while trying to stop the container "${container}".`); + } + } +}; diff --git a/apps/Leonidias/orchistrator/docker-compose.yml b/apps/Leonidias/orchistrator/docker-compose.yml new file mode 100644 index 000000000..044875a5b --- /dev/null +++ b/apps/Leonidias/orchistrator/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3' + +services: + server-bot: + container_name: server-bot + image: allenrkeen/server-bot:latest + volumes: + - /var/run/docker.sock:/var/run/docker.sock #required + environment: + - DISCORD_TOKEN=your_token_here #required + - DISCORD_CLIENT_ID=your_client_id_here #required + - DISCORD_GUILD_ID=your_guild_id_here #optional diff --git a/apps/Leonidias/orchistrator/index.js b/apps/Leonidias/orchistrator/index.js new file mode 100644 index 000000000..9b1979320 --- /dev/null +++ b/apps/Leonidias/orchistrator/index.js @@ -0,0 +1,89 @@ +require('dotenv').config(); +const fs = require('node:fs'); +const path = require('node:path'); +const token = process.env.DISCORD_TOKEN; +const clientID = process.env.DISCORD_CLIENT_ID; + +// Require the necessary discord.js classes +const { Client, Collection, Events, GatewayIntentBits } = require('discord.js'); + +// Create a new client instance +const client = new Client({ intents: [GatewayIntentBits.Guilds] }); + +//run backend/deployCommands.js +const { exec } = require('child_process'); +exec('node backend/deployCommands.js', (err, stdout, stderr) => { + if (err) { + //some err occurred + console.error(err); + } else { + // print complete output + console.log(stdout); + } +}); + + + +// When the client is ready, run this code +client.once(Events.ClientReady, c => { + console.log(`Ready! Logged in as ${c.user.tag}`); +}); + +// Log in to Discord with your client's token +client.login(token); + +// Create a new collection for commands +client.commands = new Collection(); + +const commandsPath = path.join(__dirname, 'commands'); +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); + // Set a new item in the Collection with the key as the name of the command and the value as the exported module + if ('data' in command && 'execute' in command) { + client.commands.set(command.data.name, command); + } else { + console.log(`Command ${file} is missing 'data' or 'execute'`); + } +} +//build and display invite link +const inviteLink = 'https://discord.com/oauth2/authorize?client_id='+clientID+'&permissions=2147534912&scope=bot%20applications.commands'; + +console.log(`Invite link: ${inviteLink}`); + +// execute on slash command +client.on(Events.InteractionCreate, async interaction => { + if (interaction.isChatInputCommand()) { + const command = 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); + // await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); + } + } else if (interaction.isAutocomplete()) { + + const command = client.commands.get(interaction.commandName); + + if (!command) { + console.error('No command matching ${interaction.commandName} was found.'); + return; + } + + try { + await command.autocomplete(interaction); + } catch (error) { + console.error(error); + // await interaction.({ content: 'There was an error while executing this command!', ephemeral: true }); + } + } +}); + diff --git a/apps/Leonidias/orchistrator/package-lock.json b/apps/Leonidias/orchistrator/package-lock.json new file mode 100644 index 000000000..f351e4710 --- /dev/null +++ b/apps/Leonidias/orchistrator/package-lock.json @@ -0,0 +1,723 @@ +{ + "name": "server-bot", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "server-bot", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "discord.js": "^14.7.1", + "dockerode": "^3.3.4", + "dotenv": "^16.0.3", + "node-docker-api": "^1.1.22" + } + }, + "node_modules/@balena/dockerignore": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", + "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==" + }, + "node_modules/@discordjs/builders": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.4.0.tgz", + "integrity": "sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==", + "dependencies": { + "@discordjs/util": "^0.1.0", + "@sapphire/shapeshift": "^3.7.1", + "discord-api-types": "^0.37.20", + "fast-deep-equal": "^3.1.3", + "ts-mixer": "^6.0.2", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "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==", + "engines": { + "node": ">=16.9.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==", + "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" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "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==", + "engines": { + "node": ">=16.9.0" + } + }, + "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==", + "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==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "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==", + "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.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + }, + "node_modules/@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buildcheck": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz", + "integrity": "sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "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" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cpu-features": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.4.tgz", + "integrity": "sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "0.0.3", + "nan": "^2.15.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/discord-api-types": { + "version": "0.37.24", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.24.tgz", + "integrity": "sha512-1+Fb4huJCihdbkJLcq2p7nBmtlmAryNwjefT8wwJnL8c7bc7WA87Oaa5mbLe96QvZyfwnwRCDX40H0HhcVV50g==" + }, + "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==", + "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" + }, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/docker-modem": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.6.tgz", + "integrity": "sha512-h0Ow21gclbYsZ3mkHDfsYNDqtRhXS8fXr51bU0qr1dxgTMJj0XufbzX+jhNOvA8KuEEzn6JbvLVhXyv+fny9Uw==", + "dependencies": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.11.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/dockerode": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.4.tgz", + "integrity": "sha512-3EUwuXnCU+RUlQEheDjmBE0B7q66PV9Rw5NiH1sXwINq0M9c5ERP9fxgkw36ZHOtzf4AGEEYySnkx/sACC9EgQ==", + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "docker-modem": "^3.0.0", + "tar-fs": "~2.0.1" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "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.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", + "integrity": "sha512-jjMwFpnW8PKofLE/4ohlhqwDk5k0NC6iy0UHAJFKoY1fQeGMN0GDdLgHQrvCbSpMwbqzoCZhRI5dETCZna5qVA==", + "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/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "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==" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha512-fw7Q/8gFR8iSekUi9I+HqWIap6mywuoe7hQIg3buTVjuZgALKj4HAmm0X6f+TaL4c9NJbvyFQdaI2ppr5p6dnQ==", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz", + "integrity": "sha512-8XbSFFd43EG+1thjLNFIzCBlwXti0yKa7L+ak/f0T/pkC+31b7G41DXL/JzYpAoYWZ2eCPiu4IIqzijM8N0a/w==", + "dependencies": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "index.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "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==" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, + "node_modules/node-docker-api": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/node-docker-api/-/node-docker-api-1.1.22.tgz", + "integrity": "sha512-8xfOiuLDJQw+l58i66lUNQhRhS5fAExqQbLolmyqMucrsDON7k7eLMIHphcBwwB7utwCHCQkcp73gSAmzSiAiw==", + "dependencies": { + "docker-modem": "^0.3.1", + "memorystream": "^0.3.1" + } + }, + "node_modules/node-docker-api/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/node-docker-api/node_modules/docker-modem": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-0.3.7.tgz", + "integrity": "sha512-4Xn4ZVtc/2DEFtxY04lOVeF7yvxwXGVo0sN8FKRBnLhBcwQ78Hb56j+Z5yAXXUhoweVhzGeBeGWahS+af0/mcg==", + "dependencies": { + "debug": "^2.6.0", + "JSONStream": "0.10.0", + "readable-stream": "~1.0.26-4", + "split-ca": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-docker-api/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/node-docker-api/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/node-docker-api/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "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==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/split-ca": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==" + }, + "node_modules/ssh2": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.11.0.tgz", + "integrity": "sha512-nfg0wZWGSsfUe/IBJkXVll3PEZ//YH2guww+mP88gTpuSU4FtZN7zu9JoeTGOyCNx2dTDtT9fOpWwlzyj4uOOw==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.4", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.4", + "nan": "^2.16.0" + } + }, + "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/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "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" + } + }, + "node_modules/ts-mixer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.2.tgz", + "integrity": "sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==" + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/undici": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz", + "integrity": "sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "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 + } + } + } + } +} diff --git a/apps/Leonidias/orchistrator/package.json b/apps/Leonidias/orchistrator/package.json new file mode 100644 index 000000000..97dfb0551 --- /dev/null +++ b/apps/Leonidias/orchistrator/package.json @@ -0,0 +1,30 @@ +{ + "name": "server-bot", + "version": "1.0.0", + "description": "Discord bot to remotely monitor and control a docker based server", + "main": "index.js", + "scripts": { + "start": "nodemon index.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/allenrkeen/server-bot.git" + }, + "keywords": [ + "discord", + "docker", + "linux", + "selfhost" + ], + "author": "allenrkeen", + "license": "MIT", + "bugs": { + "url": "https://github.com/allenrkeen/server-bot/issues" + }, + "homepage": "https://github.com/allenrkeen/server-bot#readme", + "dependencies": { + "discord.js": "^14.7.1", + "dotenv": "^16.0.3", + "node-docker-api": "^1.1.22" + } +} diff --git a/apps/Open-Sourcerer/main.py b/apps/Open-Sourcerer/main.py index 153ff8c40..b288e78da 100644 --- a/apps/Open-Sourcerer/main.py +++ b/apps/Open-Sourcerer/main.py @@ -4,7 +4,7 @@ import interpreter import dotenv import whisper -from jarvis import transcribe +from voice import transcribe dotenv.load_dotenv(".env")