Add orchistrator

Former-commit-id: 8f456a1505
discord-bot-framework
Zack 1 year ago
parent 120346e037
commit a39e527b32

@ -0,0 +1,2 @@
node_modules
.env

@ -0,0 +1,3 @@
DISCORD_TOKEN=
DISCORD_CLIENT_ID=
DISCORD_GUILD_ID=

@ -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" ]

@ -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.

@ -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);

@ -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);
}
})();

@ -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] });
}
},
};

@ -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!");
},
};

@ -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}".`);
}
}
};

@ -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}`);
},
};

@ -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.`);
}
},
};

@ -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}".`);
}
}
};

@ -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

@ -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 });
}
}
});

@ -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
}
}
}
}
}

@ -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"
}
}
Loading…
Cancel
Save