├── .env.example ├── .gitignore ├── commands ├── .gitkeep └── context-menu │ └── quick-replies.js ├── deploy-commands.js ├── index.js ├── package-lock.json └── package.json /.env.example: -------------------------------------------------------------------------------- 1 | ADMIN_ROLE_ID=1004118272893009930 2 | GUIDELINES_CHANNEL_ID=883264995603935272 3 | HELP_CHANNEL_ID=1080807837833384017 4 | CLIENT_ID= 5 | TOKEN= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /commands/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/filamentphp/discord-bot/24fe702c6d259f777247735128df4d031799811a/commands/.gitkeep -------------------------------------------------------------------------------- /commands/context-menu/quick-replies.js: -------------------------------------------------------------------------------- 1 | const { ContextMenuCommandBuilder, ApplicationCommandType, ActionRowBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, Collection } = require('discord.js'); 2 | 3 | require('dotenv').config() 4 | 5 | const quickReplies = [ 6 | { 7 | key: 'docs', 8 | label: 'Docs', 9 | description: 'Answered on the docs', 10 | reply: `We're confident that you can find the answer to this question in the docs. Please visit and use the search input to find what you are looking for. If you are still having trouble, please reply to this message to provide more information about your use case.`, 11 | }, 12 | { 13 | key: 'troubleshoot', 14 | label: 'Troubleshoot', 15 | description: 'Run \`php artisan filament:upgrade\`, delete published views, clear cache etc', 16 | reply: `Please run \`php artisan filament:upgrade\`, recompile any frontend assets you may have, clear your browser cache, and delete the \`/resources/views/vendor\` directory if it exists. If the problem still persists, please reply to this message and let us know.`, 17 | }, 18 | { 19 | key: 'confusingQuestion', 20 | label: 'Confusing Question', 21 | description: 'We need more information', 22 | reply: `We're confused about what you mean by this question. Please read the <#${process.env.GUIDELINES_CHANNEL_ID}> and reply to this message to provide more information about your use case.`, 23 | }, 24 | { 25 | key: 'offTopic', 26 | label: 'Off Topic', 27 | description: 'Not related to Filament', 28 | reply: `It seems that your question is not related to Filament. To help as many Filament users as possible, we need to be selective over which questions get posted here.`, 29 | }, 30 | { 31 | key: 'moreInfo', 32 | label: 'More Info', 33 | description: 'Share Error/Code', 34 | reply: `We need more information to help you debug your problem. Please click on the top left 'SHARE' button of the error page you're seeing and share the link with us.`, 35 | }, 36 | { 37 | key: 'xyProblem', 38 | label: 'XY Problem', 39 | description: 'Ask about the problem, not your attempted solution', 40 | reply: `Please ask about the actual _problem_ you're trying to solve, instead of your attempted _solution_. `, 41 | }, 42 | { 43 | key: 'codeFormatting', 44 | label: 'Code Formatting', 45 | description: 'Read the guidelines on Code Formatting', 46 | reply: `Please read the <#${process.env.GUIDELINES_CHANNEL_ID}> about how to format your code properly.`, 47 | }, 48 | { 49 | key: 'wrongChannel', 50 | label: 'Wrong Channel', 51 | description: 'Post in the correct channel', 52 | reply: `Your question is posted in the wrong channel. For questions please use <#${process.env.HELP_CHANNEL_ID}> or the appropriate plugin channel.`, 53 | }, 54 | { 55 | key: 'upgrade', 56 | label: 'Upgrade', 57 | description: 'Upgrade to latest version', 58 | reply: `Please upgrade to the latest Filament version using \`composer update\`.`, 59 | }, 60 | { 61 | key: 'crossPost', 62 | label: 'Cross Post', 63 | description: 'Do not post same message across multiple channels', 64 | reply: `Please don't post the same message across different channels.`, 65 | }, 66 | { 67 | key: 'fileUploadPreview', 68 | label: 'File Upload Preview', 69 | description: 'File upload previews not loading', 70 | reply: `https://filamentphp.com/community/danharrin-file-previews-not-loading`, 71 | }, 72 | ]; 73 | 74 | const keyReplyCollection = new Collection() 75 | 76 | for (const quickReply of quickReplies) { 77 | keyReplyCollection.set(quickReply.key, quickReply.reply) 78 | } 79 | 80 | module.exports = { 81 | data: new ContextMenuCommandBuilder() 82 | .setName('Quick Replies') 83 | .setType(ApplicationCommandType.Message), 84 | async execute(interaction) { 85 | const targetMessage = interaction.targetMessage; 86 | 87 | const memberManager = targetMessage.guild.members; 88 | const member = await memberManager.fetch(interaction.user); 89 | 90 | if (! member.roles.cache.has(process.env.ADMIN_ROLE_ID)) { 91 | await interaction.reply({ content: 'You do not have permission to run this command!', ephemeral: true }); 92 | return; 93 | } 94 | 95 | let quickReplySelectOptions = []; 96 | 97 | for (const quickReply of quickReplies) { 98 | quickReplySelectOptions.push( 99 | new StringSelectMenuOptionBuilder() 100 | .setLabel(quickReply.label) 101 | .setValue(targetMessage.id + ':' + quickReply.key) 102 | .setDescription(quickReply.description) 103 | ); 104 | } 105 | 106 | const quickReplySelect = new StringSelectMenuBuilder() 107 | .setCustomId('quickReplySelect') 108 | .setPlaceholder('Select a quick reply') 109 | .addOptions(quickReplySelectOptions); 110 | 111 | const actionRow = new ActionRowBuilder().addComponents(quickReplySelect); 112 | 113 | await interaction.reply({ 114 | content: 'Choose a quick reply!', 115 | components: [actionRow], 116 | ephemeral: true, 117 | }); 118 | }, 119 | keyReplyCollection: keyReplyCollection, 120 | }; 121 | -------------------------------------------------------------------------------- /deploy-commands.js: -------------------------------------------------------------------------------- 1 | const { REST, Routes } = require('discord.js'); 2 | const quickReplies = require('./commands/context-menu/quick-replies'); 3 | 4 | require('dotenv').config() 5 | 6 | const commands = [ 7 | quickReplies.data.toJSON(), 8 | ] 9 | 10 | const rest = new REST().setToken(process.env.TOKEN); 11 | 12 | (async () => { 13 | try { 14 | console.log(`Started refreshing ${commands.length} application (/) commands.`); 15 | 16 | const data = await rest.put( 17 | Routes.applicationCommands(process.env.CLIENT_ID), 18 | { body: commands }, 19 | ); 20 | 21 | console.log(`Successfully reloaded ${data.length} application (/) commands.`); 22 | } catch (error) { 23 | console.error(error); 24 | } 25 | })() -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { Client, GatewayIntentBits, Collection, Events } = require('discord.js') 2 | const quickReplies = require('./commands/context-menu/quick-replies') 3 | 4 | require('dotenv').config() 5 | 6 | const client = new Client({ 7 | intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages] 8 | }) 9 | 10 | const commandCollection = new Collection() 11 | const contextMenuCommandCollection = new Collection() 12 | contextMenuCommandCollection.set(quickReplies.data.name, quickReplies); 13 | 14 | const keyReplyCollection = quickReplies.keyReplyCollection; 15 | 16 | client.on('ready', () => { 17 | console.log(`Logged in as ${client.user.tag}!`) 18 | }) 19 | 20 | client.on('threadCreate', async (thread) => { 21 | if (! thread.joinable) { 22 | return 23 | } 24 | 25 | await thread.join() 26 | }) 27 | 28 | client.on(Events.InteractionCreate, async interaction => { 29 | // Slash commands 30 | if (interaction.isChatInputCommand()) { 31 | const command = commandCollection.get(interaction.commandName) 32 | 33 | if (! command) return 34 | 35 | try { 36 | await command.execute(interaction) 37 | } catch (e) { 38 | console.error(e) 39 | 40 | if (interaction.replied || interaction.deferred) { 41 | await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }) 42 | } else { 43 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }) 44 | } 45 | } 46 | } 47 | 48 | // Context menu commands 49 | if (interaction.isMessageContextMenuCommand()) { 50 | const command = contextMenuCommandCollection.get(interaction.commandName) 51 | 52 | if (! command) return 53 | 54 | try { 55 | await command.execute(interaction) 56 | } catch (e) { 57 | console.error(e) 58 | 59 | if (interaction.replied || interaction.deferred) { 60 | await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }) 61 | } else { 62 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }) 63 | } 64 | } 65 | } 66 | 67 | if (interaction.isStringSelectMenu()) { 68 | if (interaction.customId !== 'quickReplySelect') { 69 | return 70 | } 71 | 72 | try { 73 | const [targetMessageId, key] = interaction.values[0].split(':') 74 | 75 | const message = keyReplyCollection.get(key) ?? null 76 | 77 | if (! message) { 78 | return 79 | } 80 | 81 | const targetMessage = await interaction.channel.messages.fetch(targetMessageId) 82 | 83 | await targetMessage.reply({ content: message }) 84 | 85 | await interaction.reply({ 86 | content: `You ran a quick reply command!`, 87 | ephemeral: true, 88 | }) 89 | 90 | await interaction.deleteReply() 91 | } catch (e) { 92 | console.error(e) 93 | 94 | if (interaction.replied || interaction.deferred) { 95 | await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true }) 96 | } else { 97 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }) 98 | } 99 | } 100 | 101 | } 102 | 103 | }) 104 | 105 | client.login(process.env.TOKEN).then(() => { 106 | client.user.setPresence({ 107 | 'activities': [{ 108 | 'name': 'Filament users', 109 | 'type': 'WATCHING', 110 | }], 111 | }) 112 | }) 113 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "filament-discord-bot", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "discord.js": "^14.1.2", 9 | "dotenv": "^16.0.1" 10 | } 11 | }, 12 | "node_modules/@discordjs/builders": { 13 | "version": "1.6.5", 14 | "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.6.5.tgz", 15 | "integrity": "sha512-SdweyCs/+mHj+PNhGLLle7RrRFX9ZAhzynHahMCLqp5Zeq7np7XC6/mgzHc79QoVlQ1zZtOkTTiJpOZu5V8Ufg==", 16 | "dependencies": { 17 | "@discordjs/formatters": "^0.3.2", 18 | "@discordjs/util": "^1.0.1", 19 | "@sapphire/shapeshift": "^3.9.2", 20 | "discord-api-types": "0.37.50", 21 | "fast-deep-equal": "^3.1.3", 22 | "ts-mixer": "^6.0.3", 23 | "tslib": "^2.6.1" 24 | }, 25 | "engines": { 26 | "node": ">=16.11.0" 27 | } 28 | }, 29 | "node_modules/@discordjs/collection": { 30 | "version": "1.5.3", 31 | "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz", 32 | "integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==", 33 | "engines": { 34 | "node": ">=16.11.0" 35 | } 36 | }, 37 | "node_modules/@discordjs/formatters": { 38 | "version": "0.3.2", 39 | "resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.3.2.tgz", 40 | "integrity": "sha512-lE++JZK8LSSDRM5nLjhuvWhGuKiXqu+JZ/DsOR89DVVia3z9fdCJVcHF2W/1Zxgq0re7kCzmAJlCMMX3tetKpA==", 41 | "dependencies": { 42 | "discord-api-types": "0.37.50" 43 | }, 44 | "engines": { 45 | "node": ">=16.11.0" 46 | } 47 | }, 48 | "node_modules/@discordjs/rest": { 49 | "version": "2.0.1", 50 | "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.0.1.tgz", 51 | "integrity": "sha512-/eWAdDRvwX/rIE2tuQUmKaxmWeHmGealttIzGzlYfI4+a7y9b6ZoMp8BG/jaohs8D8iEnCNYaZiOFLVFLQb8Zg==", 52 | "dependencies": { 53 | "@discordjs/collection": "^1.5.3", 54 | "@discordjs/util": "^1.0.1", 55 | "@sapphire/async-queue": "^1.5.0", 56 | "@sapphire/snowflake": "^3.5.1", 57 | "@vladfrangu/async_event_emitter": "^2.2.2", 58 | "discord-api-types": "0.37.50", 59 | "magic-bytes.js": "^1.0.15", 60 | "tslib": "^2.6.1", 61 | "undici": "5.22.1" 62 | }, 63 | "engines": { 64 | "node": ">=16.11.0" 65 | } 66 | }, 67 | "node_modules/@discordjs/util": { 68 | "version": "1.0.1", 69 | "resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.0.1.tgz", 70 | "integrity": "sha512-d0N2yCxB8r4bn00/hvFZwM7goDcUhtViC5un4hPj73Ba4yrChLSJD8fy7Ps5jpTLg1fE9n4K0xBLc1y9WGwSsA==", 71 | "engines": { 72 | "node": ">=16.11.0" 73 | } 74 | }, 75 | "node_modules/@discordjs/ws": { 76 | "version": "1.0.1", 77 | "resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.0.1.tgz", 78 | "integrity": "sha512-avvAolBqN3yrSvdBPcJ/0j2g42ABzrv3PEL76e3YTp2WYMGH7cuspkjfSyNWaqYl1J+669dlLp+YFMxSVQyS5g==", 79 | "dependencies": { 80 | "@discordjs/collection": "^1.5.3", 81 | "@discordjs/rest": "^2.0.1", 82 | "@discordjs/util": "^1.0.1", 83 | "@sapphire/async-queue": "^1.5.0", 84 | "@types/ws": "^8.5.5", 85 | "@vladfrangu/async_event_emitter": "^2.2.2", 86 | "discord-api-types": "0.37.50", 87 | "tslib": "^2.6.1", 88 | "ws": "^8.13.0" 89 | }, 90 | "engines": { 91 | "node": ">=16.11.0" 92 | } 93 | }, 94 | "node_modules/@sapphire/async-queue": { 95 | "version": "1.5.0", 96 | "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", 97 | "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", 98 | "engines": { 99 | "node": ">=v14.0.0", 100 | "npm": ">=7.0.0" 101 | } 102 | }, 103 | "node_modules/@sapphire/shapeshift": { 104 | "version": "3.9.2", 105 | "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.9.2.tgz", 106 | "integrity": "sha512-YRbCXWy969oGIdqR/wha62eX8GNHsvyYi0Rfd4rNW6tSVVa8p0ELiMEuOH/k8rgtvRoM+EMV7Csqz77YdwiDpA==", 107 | "dependencies": { 108 | "fast-deep-equal": "^3.1.3", 109 | "lodash": "^4.17.21" 110 | }, 111 | "engines": { 112 | "node": ">=v14.0.0", 113 | "npm": ">=7.0.0" 114 | } 115 | }, 116 | "node_modules/@sapphire/snowflake": { 117 | "version": "3.5.1", 118 | "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.1.tgz", 119 | "integrity": "sha512-BxcYGzgEsdlG0dKAyOm0ehLGm2CafIrfQTZGWgkfKYbj+pNNsorZ7EotuZukc2MT70E0UbppVbtpBrqpzVzjNA==", 120 | "engines": { 121 | "node": ">=v14.0.0", 122 | "npm": ">=7.0.0" 123 | } 124 | }, 125 | "node_modules/@types/node": { 126 | "version": "20.8.2", 127 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz", 128 | "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==" 129 | }, 130 | "node_modules/@types/ws": { 131 | "version": "8.5.6", 132 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.6.tgz", 133 | "integrity": "sha512-8B5EO9jLVCy+B58PLHvLDuOD8DRVMgQzq8d55SjLCOn9kqGyqOvy27exVaTio1q1nX5zLu8/6N0n2ThSxOM6tg==", 134 | "dependencies": { 135 | "@types/node": "*" 136 | } 137 | }, 138 | "node_modules/@vladfrangu/async_event_emitter": { 139 | "version": "2.2.2", 140 | "resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.2.2.tgz", 141 | "integrity": "sha512-HIzRG7sy88UZjBJamssEczH5q7t5+axva19UbZLO6u0ySbYPrwzWiXBcC0WuHyhKKoeCyneH+FvYzKQq/zTtkQ==", 142 | "engines": { 143 | "node": ">=v14.0.0", 144 | "npm": ">=7.0.0" 145 | } 146 | }, 147 | "node_modules/busboy": { 148 | "version": "1.6.0", 149 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 150 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 151 | "dependencies": { 152 | "streamsearch": "^1.1.0" 153 | }, 154 | "engines": { 155 | "node": ">=10.16.0" 156 | } 157 | }, 158 | "node_modules/discord-api-types": { 159 | "version": "0.37.50", 160 | "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.50.tgz", 161 | "integrity": "sha512-X4CDiMnDbA3s3RaUXWXmgAIbY1uxab3fqe3qwzg5XutR3wjqi7M3IkgQbsIBzpqBN2YWr/Qdv7JrFRqSgb4TFg==" 162 | }, 163 | "node_modules/discord.js": { 164 | "version": "14.13.0", 165 | "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.13.0.tgz", 166 | "integrity": "sha512-Kufdvg7fpyTEwANGy9x7i4od4yu5c6gVddGi5CKm4Y5a6sF0VBODObI3o0Bh7TGCj0LfNT8Qp8z04wnLFzgnbA==", 167 | "dependencies": { 168 | "@discordjs/builders": "^1.6.5", 169 | "@discordjs/collection": "^1.5.3", 170 | "@discordjs/formatters": "^0.3.2", 171 | "@discordjs/rest": "^2.0.1", 172 | "@discordjs/util": "^1.0.1", 173 | "@discordjs/ws": "^1.0.1", 174 | "@sapphire/snowflake": "^3.5.1", 175 | "@types/ws": "^8.5.5", 176 | "discord-api-types": "0.37.50", 177 | "fast-deep-equal": "^3.1.3", 178 | "lodash.snakecase": "^4.1.1", 179 | "tslib": "^2.6.1", 180 | "undici": "5.22.1", 181 | "ws": "^8.13.0" 182 | }, 183 | "engines": { 184 | "node": ">=16.11.0" 185 | } 186 | }, 187 | "node_modules/dotenv": { 188 | "version": "16.3.1", 189 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", 190 | "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", 191 | "engines": { 192 | "node": ">=12" 193 | }, 194 | "funding": { 195 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 196 | } 197 | }, 198 | "node_modules/fast-deep-equal": { 199 | "version": "3.1.3", 200 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 201 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 202 | }, 203 | "node_modules/lodash": { 204 | "version": "4.17.21", 205 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 206 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 207 | }, 208 | "node_modules/lodash.snakecase": { 209 | "version": "4.1.1", 210 | "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", 211 | "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==" 212 | }, 213 | "node_modules/magic-bytes.js": { 214 | "version": "1.5.0", 215 | "resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.5.0.tgz", 216 | "integrity": "sha512-wJkXvutRbNWcc37tt5j1HyOK1nosspdh3dj6LUYYAvF6JYNqs53IfRvK9oEpcwiDA1NdoIi64yAMfdivPeVAyw==" 217 | }, 218 | "node_modules/streamsearch": { 219 | "version": "1.1.0", 220 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 221 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", 222 | "engines": { 223 | "node": ">=10.0.0" 224 | } 225 | }, 226 | "node_modules/ts-mixer": { 227 | "version": "6.0.3", 228 | "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz", 229 | "integrity": "sha512-k43M7uCG1AkTyxgnmI5MPwKoUvS/bRvLvUb7+Pgpdlmok8AoqmUaZxUUw8zKM5B1lqZrt41GjYgnvAi0fppqgQ==" 230 | }, 231 | "node_modules/tslib": { 232 | "version": "2.6.2", 233 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 234 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" 235 | }, 236 | "node_modules/undici": { 237 | "version": "5.22.1", 238 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", 239 | "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", 240 | "dependencies": { 241 | "busboy": "^1.6.0" 242 | }, 243 | "engines": { 244 | "node": ">=14.0" 245 | } 246 | }, 247 | "node_modules/ws": { 248 | "version": "8.14.2", 249 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", 250 | "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", 251 | "engines": { 252 | "node": ">=10.0.0" 253 | }, 254 | "peerDependencies": { 255 | "bufferutil": "^4.0.1", 256 | "utf-8-validate": ">=5.0.2" 257 | }, 258 | "peerDependenciesMeta": { 259 | "bufferutil": { 260 | "optional": true 261 | }, 262 | "utf-8-validate": { 263 | "optional": true 264 | } 265 | } 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "node index.js", 4 | "deploy-commands": "node deploy-commands.js" 5 | }, 6 | "dependencies": { 7 | "discord.js": "^14.1.2", 8 | "dotenv": "^16.0.1" 9 | } 10 | } 11 | --------------------------------------------------------------------------------