update command registration to npm

This commit is contained in:
Shay
2023-03-18 16:05:36 -07:00
parent bbe1a594a2
commit 767394582c
7 changed files with 37 additions and 66 deletions

View File

@@ -1,4 +1,3 @@
APP_ID=<YOUR_APP_ID>
GUILD_ID=<YOUR_GUILD_ID>
DISCORD_TOKEN=<YOUR_BOT_TOKEN>
PUBLIC_KEY=<YOUR_PUBLIC_KEY>

View File

@@ -48,12 +48,20 @@ npm install
```
### Get app credentials
Fetch the credentials from your app's settings and add them to a `.env` file (see `.env.sample` for an example). You'll need your app ID (`APP_ID`), server ID (`GUILD_ID`), bot token (`DISCORD_TOKEN`), and public key (`PUBLIC_KEY`).
Fetch the credentials from your app's settings and add them to a `.env` file (see `.env.sample` for an example). You'll need your app ID (`APP_ID`), bot token (`DISCORD_TOKEN`), and public key (`PUBLIC_KEY`).
Fetching credentials is covered in detail in the [getting started guide](https://discord.com/developers/docs/getting-started).
> 🔑 Environment variables can be added to the `.env` file in Glitch or when developing locally, and in the Secrets tab in Replit (the lock icon on the left).
### Install slash commands
The commands for the example app are set up in `commands.js`. All of the commands in the `ALL_COMMANDS` array at the bottom of `commands.js` will be installed when you run the `register` command configured in `package.json`:
```
npm run register
```
### Run the app
After your credentials are added, go ahead and run the app:

15
app.js
View File

@@ -9,11 +9,6 @@ import {
} from 'discord-interactions';
import { VerifyDiscordRequest, getRandomEmoji, DiscordRequest } from './utils.js';
import { getShuffledOptions, getResult } from './game.js';
import {
CHALLENGE_COMMAND,
TEST_COMMAND,
HasGuildCommands,
} from './commands.js';
// Create an express app
const app = express();
@@ -46,7 +41,7 @@ app.post('/interactions', async function (req, res) {
if (type === InteractionType.APPLICATION_COMMAND) {
const { name } = data;
// "test" guild command
// "test" command
if (name === 'test') {
// Send a message into the channel where command was triggered from
return res.send({
@@ -57,7 +52,7 @@ app.post('/interactions', async function (req, res) {
},
});
}
// "challenge" guild command
// "challenge" command
if (name === 'challenge' && id) {
const userId = req.body.member.user.id;
// User's object choice
@@ -177,10 +172,4 @@ app.post('/interactions', async function (req, res) {
app.listen(PORT, () => {
console.log('Listening on port', PORT);
// Check if guild commands from commands.js are installed (if not, install them)
HasGuildCommands(process.env.APP_ID, process.env.GUILD_ID, [
TEST_COMMAND,
CHALLENGE_COMMAND,
]);
});

View File

@@ -1,47 +1,6 @@
import 'dotenv/config';
import { getRPSChoices } from './game.js';
import { capitalize, DiscordRequest } from './utils.js';
export async function HasGuildCommands(appId, guildId, commands) {
if (guildId === '' || appId === '') return;
commands.forEach((c) => HasGuildCommand(appId, guildId, c));
}
// Checks for a command
async function HasGuildCommand(appId, guildId, command) {
// API endpoint to get and post guild commands
const endpoint = `applications/${appId}/guilds/${guildId}/commands`;
try {
const res = await DiscordRequest(endpoint, { method: 'GET' });
const data = await res.json();
if (data) {
const installedNames = data.map((c) => c['name']);
// This is just matching on the name, so it's not good for updates
if (!installedNames.includes(command['name'])) {
console.log(`Installing "${command['name']}"`);
InstallGuildCommand(appId, guildId, command);
} else {
console.log(`"${command['name']}" command already installed`);
}
}
} catch (err) {
console.error(err);
}
}
// Installs a command
export async function InstallGuildCommand(appId, guildId, command) {
// API endpoint to get and post guild commands
const endpoint = `applications/${appId}/guilds/${guildId}/commands`;
// install command
try {
await DiscordRequest(endpoint, { method: 'POST', body: command });
} catch (err) {
console.error(err);
}
}
import { capitalize, InstallGlobalCommands } from './utils.js';
// Get the game choices from game.js
function createCommandChoices() {
@@ -59,14 +18,14 @@ function createCommandChoices() {
}
// Simple test command
export const TEST_COMMAND = {
const TEST_COMMAND = {
name: 'test',
description: 'Basic guild command',
description: 'Basic command',
type: 1,
};
// Command containing options
export const CHALLENGE_COMMAND = {
const CHALLENGE_COMMAND = {
name: 'challenge',
description: 'Challenge to a match of rock paper scissors',
options: [
@@ -80,3 +39,7 @@ export const CHALLENGE_COMMAND = {
],
type: 1,
};
const ALL_COMMANDS = [TEST_COMMAND, CHALLENGE_COMMAND];
InstallGlobalCommands(process.env.APP_ID, ALL_COMMANDS);

View File

@@ -27,19 +27,18 @@ app.post('/interactions', function (req, res) {
async function createCommand() {
const appId = process.env.APP_ID;
const guildId = process.env.GUILD_ID;
/**
* Globally-scoped slash commands (generally only recommended for production)
* See https://discord.com/developers/docs/interactions/application-commands#create-global-application-command
*/
// const globalEndpoint = `applications/${appId}/commands`;
const globalEndpoint = `applications/${appId}/commands`;
/**
* Guild-scoped slash commands
* See https://discord.com/developers/docs/interactions/application-commands#create-guild-application-command
*/
const guildEndpoint = `applications/${appId}/guilds/${guildId}/commands`;
// const guildEndpoint = `applications/${appId}/guilds/<your guild id>/commands`;
const commandBody = {
name: 'test',
description: 'Just your average command',
@@ -49,7 +48,7 @@ async function createCommand() {
try {
// Send HTTP request with bot token
const res = await DiscordRequest(guildEndpoint, {
const res = await DiscordRequest(globalEndpoint, {
method: 'POST',
body: commandBody,
});

View File

@@ -1,11 +1,12 @@
{
"name": "getting-started",
"version": "1.0.0",
"description": "",
"description": "Discord example app",
"main": "app.js",
"type": "module",
"scripts": {
"start": "node app.js",
"register": "node commands.js",
"dev": "nodemon app.js"
},
"author": "Shay DeWael",

View File

@@ -39,6 +39,18 @@ export async function DiscordRequest(endpoint, options) {
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 = ['😭','😄','😌','🤓','😎','😤','🤖','😶‍🌫️','🌏','📸','💿','👋','🌊','✨'];