aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--app.js79
-rw-r--r--commands.js81
-rw-r--r--package-lock.json341
-rw-r--r--package.json4
-rw-r--r--utils.js47
6 files changed, 455 insertions, 101 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1012323
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/.env
+.env
+jobs.json
+/node_modules/
diff --git a/app.js b/app.js
index c387daf..b5d505d 100644
--- a/app.js
+++ b/app.js
@@ -6,44 +6,89 @@ import {
InteractionResponseType,
verifyKeyMiddleware,
} from 'discord-interactions';
+import { Client, GatewayIntentBits } from 'discord.js';
+import fs from 'node:fs';
+import { v4 as uuidv4 } from 'uuid';
+
+const client = new Client ({ intents: [GatewayIntentBits.Guilds] });
+var jobs = {};
+const job_crons = {};
+client.on('ready', () => {
+ console.log(`Logged in as ${client.user.tag}!`);
+ fs.readFile('jobs.json', 'utf8', (err,data) => {
+ jobs = err ? {} : JSON.parse(data);
+
+ Object.keys(jobs).forEach((job) => {
+ job_crons[job] = cron.schedule(jobs[job].crontab, () => {
+ client.channels.cache.get(jobs[job].channel_id).send(jobs[job].message);
+ });
+ });
+ });
+});
+
+client.login(process.env.DISCORD_TOKEN);
-// Create an express app
const app = express();
-// Get port, or default to 3000
const PORT = process.env.PORT || 3000;
-/**
- * Interactions endpoint URL where Discord will send HTTP requests
- * Parse request body and verifies incoming requests using discord-interactions package
- */
app.post('/', verifyKeyMiddleware(process.env.PUBLIC_KEY), async function (req, res) {
- // Interaction type and data
const { type, data } = req.body;
- /**
- * Handle verification requests
- */
if (type === InteractionType.PING) {
return res.send({ type: InteractionResponseType.PONG });
}
- /**
- * Handle slash command requests
- * See https://discord.com/developers/docs/interactions/application-commands#slash-commands
- */
if (type === InteractionType.APPLICATION_COMMAND) {
- const { name, options } = data;
+ const { name, options, guild_id } = data;
if (name === 'schedule_message') {
const message = options[0].value;
const crontab = options[1].value;
const valid = cron.validate(crontab);
+ const id = uuidv4();
- const content = valid ? 'registered message "' + message + '" with cron "' + crontab + '"' : 'invalid cron';
+ const content = valid ? `registered message: "${message}" with cron: "${crontab}" and id: "${id}"` : 'invalid cron';
if (valid) {
+ jobs[id] = {
+ message: message,
+ crontab: crontab,
+ channel_id: req.body.channel_id,
+ };
+ job_crons[id] = cron.schedule(crontab, () => {
+ client.channels.cache.get(req.body.channel_id).send(message);
+ });
+
+ const json = JSON.stringify(jobs);
+ fs.writeFile('jobs.json', json, 'utf8', err => {
+ if (err) {
+ console.error(err);
+ }
+ });
+
cron.schedule(crontab, () => {
- console.log(message);
+ client.channels.cache.get(req.body.channel_id).send(message)
+ });
+ }
+
+ return res.send({
+ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
+ data: {
+ content: content,
+ },
+ });
+ } else if (name === 'unschedule_message') {
+ const id = options[0].value;
+ const content = id in jobs ? `stopped job ${id}` : `no such job ${id}`;
+ if (id in jobs) {
+ delete jobs[id]
+ delete job_crons[id];
+
+ const json = JSON.stringify(jobs);
+ fs.writeFile('jobs.json', json, 'utf8', err => {
+ if (err) {
+ console.error(err);
+ }
});
}
diff --git a/commands.js b/commands.js
index 7df2f8c..2af766a 100644
--- a/commands.js
+++ b/commands.js
@@ -1,35 +1,54 @@
import 'dotenv/config';
-import {InstallGlobalCommands} from './utils.js';
-const SCHEDULE_MESSAGE = {
- name: 'schedule_message',
- description: 'Register a message to be sent at a specific time',
- type: 1,
- options: [
- {
- type: 3,
- name: 'message',
- description: 'the message to send',
- required: true,
- },
- {
- type: 3,
- name: 'crontab_string',
- description: 'the time the message should be sent at in crontab format',
- required: true,
- },
- {
- type: 4,
- name: 'repeat',
- description: 'how many times should the message be repeated? (0 is infinite and the default)',
- required: false,
- min_value: 0,
- },
- ],
- integration_types: [0, 1],
- contexts: [0, 1, 2],
-};
+import { REST, Routes } from 'discord.js';
-const ALL_COMMANDS = [SCHEDULE_MESSAGE];
+const commands = [
+ {
+ name: 'schedule_message',
+ description: 'Register a message to run as a cron job',
+ type: 1,
+ options: [
+ {
+ type: 3,
+ name: 'message',
+ description: 'the message to send',
+ required: true,
+ },
+ {
+ type: 3,
+ name: 'crontab',
+ description: 'the schedule for the message',
+ required: true,
+ },
+ ],
+ integration_types: [0],
+ contexts: [0],
+ },
+ {
+ name: 'unschedule_message',
+ description: 'Stop sending a scheduled message',
+ type: 1,
+ options: [
+ {
+ type: 3,
+ name: 'id',
+ description: 'the id of the message to stop',
+ required: true,
+ },
+ ],
+ integration_types: [0],
+ contexts: [0],
+ },
+];
-InstallGlobalCommands(process.env.APP_ID, ALL_COMMANDS);
+const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
+
+try {
+ console.log('Started refreshing application commands.');
+
+ await rest.put(Routes.applicationCommands(process.env.APP_ID), { body: commands });
+
+ console.log('Successfully reloaded application commands.');
+} catch (error) {
+ console.error(error);
+}
diff --git a/package-lock.json b/package-lock.json
index 42d52cb..256eba1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,9 +10,11 @@
"license": "MIT",
"dependencies": {
"discord-interactions": "^4.0.0",
+ "discord.js": "^14.16.3",
"dotenv": "^16.0.3",
"express": "^4.18.2",
- "node-cron": "^3.0.3"
+ "node-cron": "^3.0.3",
+ "uuid": "^11.0.3"
},
"devDependencies": {
"nodemon": "^3.0.0"
@@ -21,6 +23,218 @@
"node": ">=18.x"
}
},
+ "node_modules/@discordjs/builders": {
+ "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/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.4",
+ "tslib": "^2.6.3"
+ },
+ "engines": {
+ "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.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.11.0"
+ }
+ },
+ "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": {
+ "discord-api-types": "0.37.97"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/discordjs/discord.js?sponsor"
+ }
+ },
+ "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": ">=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/@sapphire/async-queue": {
+ "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": "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": ">=v16"
+ }
+ },
+ "node_modules/@sapphire/snowflake": {
+ "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/@types/node": {
+ "version": "22.10.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
+ "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/@types/ws": {
+ "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/@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": ">=v14.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -275,6 +489,12 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/discord-api-types": {
+ "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-interactions": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/discord-interactions/-/discord-interactions-4.1.0.tgz",
@@ -284,6 +504,32 @@
"node": ">=18.4.0"
}
},
+ "node_modules/discord.js": {
+ "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.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": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/discordjs/discord.js?sponsor"
+ }
+ },
"node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
@@ -404,6 +650,12 @@
"url": "https://opencollective.com/express"
}
},
+ "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==",
+ "license": "MIT"
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -666,6 +918,24 @@
"node": ">=0.12.0"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "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==",
+ "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/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -766,6 +1036,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/node-cron/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/nodemon": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz",
@@ -1155,6 +1434,18 @@
"nodetouch": "bin/nodetouch.js"
}
},
+ "node_modules/ts-mixer": {
+ "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.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -1175,6 +1466,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici": {
+ "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": ">=18.17"
+ }
+ },
+ "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/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -1194,12 +1500,16 @@
}
},
"node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz",
+ "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
"license": "MIT",
"bin": {
- "uuid": "dist/bin/uuid"
+ "uuid": "dist/esm/bin/uuid"
}
},
"node_modules/vary": {
@@ -1210,6 +1520,27 @@
"engines": {
"node": ">= 0.8"
}
+ },
+ "node_modules/ws": {
+ "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"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
}
}
}
diff --git a/package.json b/package.json
index dbcd515..6872a5c 100644
--- a/package.json
+++ b/package.json
@@ -17,9 +17,11 @@
"license": "MIT",
"dependencies": {
"discord-interactions": "^4.0.0",
+ "discord.js": "^14.16.3",
"dotenv": "^16.0.3",
"express": "^4.18.2",
- "node-cron": "^3.0.3"
+ "node-cron": "^3.0.3",
+ "uuid": "^11.0.3"
},
"devDependencies": {
"nodemon": "^3.0.0"
diff --git a/utils.js b/utils.js
deleted file mode 100644
index 506aea6..0000000
--- a/utils.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import 'dotenv/config';
-
-export async function DiscordRequest(endpoint, options) {
- // append endpoint to root API URL
- const url = 'https://discord.com/api/v10/' + endpoint;
- // Stringify payloads
- if (options.body) options.body = JSON.stringify(options.body);
- // Use fetch to make requests
- const res = await fetch(url, {
- headers: {
- Authorization: `Bot ${process.env.DISCORD_TOKEN}`,
- 'Content-Type': 'application/json; charset=UTF-8',
- 'User-Agent': 'DiscordBot (https://github.com/discord/discord-example-app, 1.0.0)',
- },
- ...options
- });
- // throw API errors
- if (!res.ok) {
- const data = await res.json();
- console.log(res.status);
- throw new Error(JSON.stringify(data));
- }
- // return original response
- return res;
-}
-
-export async function InstallGlobalCommands(appId, commands) {
- // API endpoint to overwrite global commands
- const endpoint = `applications/${appId}/commands`;
-
- try {
- // This is calling the bulk overwrite endpoint: https://discord.com/developers/docs/interactions/application-commands#bulk-overwrite-global-application-commands
- await DiscordRequest(endpoint, { method: 'PUT', body: commands });
- } catch (err) {
- console.error(err);
- }
-}
-
-// Simple method that returns a random emoji from list
-export function getRandomEmoji() {
- const emojiList = ['😭','πŸ˜„','😌','πŸ€“','😎','😀','πŸ€–','πŸ˜Άβ€πŸŒ«οΈ','🌏','πŸ“Έ','πŸ’Ώ','πŸ‘‹','🌊','✨'];
- return emojiList[Math.floor(Math.random() * emojiList.length)];
-}
-
-export function capitalize(str) {
- return str.charAt(0).toUpperCase() + str.slice(1);
-}