Discord slash command not showing (sometime yes and sometime no)

Viewed 95

i create a discord bot in js and its my first bot ever. i add 5 slash command but when i add my bot to my server there is not all of my slash command. i retry a lot of time to add my bot to my server (delete and re-invite) but its always the same :

  • there is 2,3 or 4 commands (never 5).
  • its never the same.

i use Glitch but i dont thinks it's from this.

app.js :

import pg from "pg";
import {
  InteractionType,
  InteractionResponseType,
  InteractionResponseFlags,
  MessageComponentTypes,
  ButtonStyleTypes,
} from "discord-interactions";
import {
  VerifyDiscordRequest,
  getRandomEmoji,
  DiscordRequest,
} from "./utils.js";
import {
  ADDSTUFF_COMMAND,
  MYSTUFF_COMMAND,
  MYCREATORID_COMMAND,
  FROMCREATORID_COMMAND,
  STUFFBYCLASSE_COMMAND,
  HasGuildCommands,
} from "./commands.js";

// Create an express app
const app = express();
// Get port, or default to 3000
const PORT = process.env.PORT || 3000;
// Parse request body and verifies incoming requests using discord-interactions package
app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) }));

// Store for in-progress games. In production, you'd want to use a DB
const activeGames = {};

// Create a connection pool using the connection information provided on bit.io.
const client = new pg.Client({
  user: "delete for stack",
  host: "delete for stack",
  database: "delete for stack", // public database
  password: "", // key from bit.io database page connect menu
  port: 5432,
  ssl: true,
});

/**
 * Interactions endpoint URL where Discord will send HTTP requests
 */
app.post("/interactions", async function (req, res) {
  // Interaction type and data
  const { type, id, 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 } = data;
    // "test" guild command
    if (name === "mystuff") {
      const userId = req.body.member.user.id;
      var info = await mystuff(userId);
      // Send a message into the channel where command was triggered from
      return res.send({
        type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
        data: {
          // Fetches a random emoji to send from a helper function
          content: "stuff --> "+ info + getRandomEmoji(),
        },
      });
    }
    if (name === "mycreatorid") {
      const userId = req.body.member.user.id;
      // Send a message into the channel where command was triggered from
      return res.send({
        type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
        data: {
          // Fetches a random emoji to send from a helper function
          content: "Ton creator id est --> "+ userId,
        },
      });
    }
    
    if (name === "fromcreator") {
      const friendId = data.options[0].value;
      var info = await mystuff(friendId);
      // Send a message into the channel where command was triggered from
      return res.send({
        type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
        data: {
          content: "From " + friendId + "-->  "+ info + getRandomEmoji(),
        },
      });
    }
    
    if (name === "stuffbyclasse") {
      const classe = data.options[0].value;
      console.log(classe);
      var info = await findbyclasse(classe);
      // Send a message into the channel where command was triggered from
      return res.send({
        type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
        data: {
          content: "equipement trouvé pour " + classe + "-->  "+ info + getRandomEmoji(),
        },
      });
    }
        
    if (name === "addstuff") {
      const userId = req.body.member.user.id;
      const stuff_link = data.options[0].value;
      const classe = data.options[1].value;
      const note = data.options[2].value;
      addstuff(stuff_link,classe,note,userId);
      // Send a message into the channel where command was triggered from
      return res.send({
        type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
        data: {
          // Fetches a random emoji to send from a helper function
          content:
            "stuff {" + stuff_link + "} est dans la base ! " + getRandomEmoji(),
        },
      });
    }
  }
});

async function findbyclasse(classe){
  await client.connect();
  var retval;
  var res = await client.query("SELECT stuff, classe, note FROM dsstable WHERE classe='" + classe +"';");
  res.rows.forEach((row) => {
    if (row.stuff !== undefined){
    retval += " stuff : ";
    retval += row.stuff;
    retval += " classe : ";
    retval += row.classe;
    retval += " note : ";
    retval += row.note;
    retval += " ";
    retval += " // ";
    }
  });
  var retvalpur = retval.replace("undefined","");
  await client.end();
  return retvalpur;
}

async function mystuff(userId) {
  await client.connect();
  var retval;
  var res = await client.query("SELECT stuff, classe, note FROM dsstable WHERE creator='" + userId +"';");
  res.rows.forEach((row) => {
    if (row.stuff !== undefined){
    retval += " stuff : ";
    retval += row.stuff;
    retval += " classe : ";
    retval += row.classe;
    retval += " note : ";
    retval += row.note;
    retval += " ";
    retval += " // ";
    }
  });
  var retvalpur = retval.replace("undefined","");
  await client.end();
  return retvalpur;
}

async function addstuff(stufflink, classe, note,userId) {
  await client.connect();
  var res = await client.query(
    "INSERT INTO DSSTable (stuff,classe,note, creator) VALUES ('" + stufflink + "','"+ classe +"','"+ note +"','"+ userId +"');");
  res.rows.forEach((row) => {
    console.log(row);
  });
  await client.end();
}

app.listen(PORT, () => {
  console.log("Listening on port", PORT);

  // Check if guild commands from commands.json are installed (if not, install them)
  HasGuildCommands(process.env.APP_ID, process.env.GUILD_ID, [MYSTUFF_COMMAND,ADDSTUFF_COMMAND,MYCREATORID_COMMAND,FROMCREATORID_COMMAND,STUFFBYCLASSE_COMMAND,]);
});

command.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 {
    console.log("command is -> " + command['name']);
    await DiscordRequest(endpoint, { method: 'POST', body: command });
  } catch (err) {
    console.error(err);
  }
}

// Simple test command
export const MYSTUFF_COMMAND = {
  name: 'mystuff',
  description: 'get my stuff',
  type: 1,
};

export const MYCREATORID_COMMAND = {
  name: 'mycreatorid',
  description: 'get my creator id !',
  type: 1,
};


export const STUFFBYCLASSE_COMMAND = {
  name: 'stuffbyclasse',
  description: 'Trouve les stuffs pour une classe précise !',
  type: 1,
      "options": [
        {
            "name": "classe",
            "description": "j'espère que tu joues hupper !",
            "type": 3,
            "required": true,
            "choices" : [
                {
                    "name": "huppermage",
                    "value": "huppermage"
                },
                {
                    "name": "iop",
                    "value": "iop"
                },
                {
                    "name": "cra",
                    "value": "cra"
                },
                {
                    "name": "sram",
                    "value": "sram"
                },
                {
                    "name": "steamer",
                    "value": "steamer"
                },
                {
                    "name": "enutrof",
                    "value": "enutrof"
                },
                {
                    "name": "roublar",
                    "value": "roublar"
                },
                {
                    "name": "xelor",
                    "value": "xelor"
                },
                {
                    "name": "eniripsa",
                    "value": "eniripsa"
                },
                {
                    "name": "ouginak",
                    "value": "ouginak"
                },
                {
                    "name": "sadida",
                    "value": "sadida"
                },
                {
                    "name": "ecaflip",
                    "value": "ecaflip"
                },
                {
                    "name": "eliotrop",
                    "value": "eliotrop"
                },
                {
                    "name": "osamodas",
                    "value": "osamodas"
                },
                {
                    "name": "panda",
                    "value": "panda"
                },
                {
                    "name": "sacrieur",
                    "value": "sacrieur"
                },
                {
                    "name": "zobal",
                    "value": "zobal"
                },
                {
                    "name": "feca",
                    "value": "feca"
                },
                {
                    "name": "all",
                    "value": "all"
                }
            ]
        },        
      ]

};


export const FROMCREATORID_COMMAND = {
  name: 'fromcreator',
  description: 'get creator stuff',
  type: 1,
      "options": [
        {
            "name": "creatorid",
            "description": "l'id du createur du stuf !",
            "type": 3,
            "required": true,
        },
      ]
};


// Command containing options
export const ADDSTUFF_COMMAND = {
  name: 'addstuff',
    "type": 1,
    "description": "Send a random adorable animal photo",
    "options": [
        {
            "name": "stuff_link",
            "description": "dofus book ici !",
            "type": 3,
            "required": true,
        },
        {
            "name": "classe",
            "description": "j'espère que tu joues hupper !",
            "type": 3,
            "required": true,
            "choices" : [
                {
                    "name": "huppermage",
                    "value": "huppermage"
                },
                {
                    "name": "iop",
                    "value": "iop"
                },
                {
                    "name": "cra",
                    "value": "cra"
                },
                {
                    "name": "sram",
                    "value": "sram"
                },
                {
                    "name": "steamer",
                    "value": "steamer"
                },
                {
                    "name": "enutrof",
                    "value": "enutrof"
                },
                {
                    "name": "roublar",
                    "value": "roublar"
                },
                {
                    "name": "xelor",
                    "value": "xelor"
                },
                {
                    "name": "eniripsa",
                    "value": "eniripsa"
                },
                {
                    "name": "ouginak",
                    "value": "ouginak"
                },
                {
                    "name": "sadida",
                    "value": "sadida"
                },
                {
                    "name": "ecaflip",
                    "value": "ecaflip"
                },
                {
                    "name": "eliotrop",
                    "value": "eliotrop"
                },
                {
                    "name": "osamodas",
                    "value": "osamodas"
                },
                {
                    "name": "panda",
                    "value": "panda"
                },
                {
                    "name": "sacrieur",
                    "value": "sacrieur"
                },
                {
                    "name": "zobal",
                    "value": "zobal"
                },
                {
                    "name": "feca",
                    "value": "feca"
                },
                {
                    "name": "all",
                    "value": "all"
                }
            ]
        },        
        {
            "name": "note",
            "description": " Donne un peu de detail !",
            "type": 3,
            "required": true,
        },
      ]
};

utils.js :

import fetch from 'node-fetch';
import { verifyKey } from 'discord-interactions';

export function VerifyDiscordRequest(clientKey) {
  return function (req, res, buf, encoding) {
    const signature = req.get('X-Signature-Ed25519');
    const timestamp = req.get('X-Signature-Timestamp');

    const isValidRequest = verifyKey(buf, signature, timestamp, clientKey);
    if (!isValidRequest) {
      res.status(401).send('Bad request signature');
      throw new Error('Bad request signature');
    }
  };
}

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 node-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();
    throw new Error(JSON.stringify(data));
  }
  // return original response
  return res;
}

// 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);
}
0 Answers
Related