discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.43k stars 3.97k forks source link

Slash Commands Support #5103

Closed wonderlandpark closed 3 years ago

wonderlandpark commented 3 years ago

Is your feature request related to a problem? Please describe. Slash commands will be added to the API at December 15th.

https://github.com/discord/discord-api-docs/pull/2295

Describe the ideal solution Should support slash command to support new api updates

Describe alternatives you've considered I think it should support Slash command gateway events and way to add slash commands for global or each guilds in discord.js

Working on #5448

vladfrangu commented 3 years ago

Slash commands were just announced, and, as the PR you linked showed, they may still be WIP. The library will definitely have support for them in the future tho👀

ChosenQuill commented 3 years ago

Documentation has been released on the developer docs! https://discord.com/developers/docs/interactions/slash-commands

AmoleR commented 3 years ago

As a person who just finished writing some things using Discord's API I can add a few comments on this (that are hard to find normally):

  1. If you're interested in creating a slash command, at this point, you require to have your bot authenticated to the server with application.commands in addition to bot. In particular, I (believe) it may have to be manually removed and added to every server.
  2. To create a (global) command, you can add this to your code:
    bot.api.applications(bot.user.id).commands.post({
    data: {
    name: "commandname",
    description: "Command Description",
    },
    });

    You can pass other options and things in the data (check the docs for this). Keep in mind that it's not possible to add spaces in the command name, so you want to use subcommands (or subcommand groups) for this. If you want to update a command, you can either post (as above) or use a patch request, such as:

    bot.api.applications(bot.user.id).commands(commandID).patch({
    data: {
    name: "commandname",
    description: "Command Description",
    },
    });

    To delete, you can just use bot.api.applications(bot.user.id).commands(commandID).delete(), and to get all of them, you can use bot.api.applications(bot.user.id).commands.get().

Note that you can add a .guilds(guildID) after applications(bot.user.id) to deploy to a specific guild (which is instant). The above method will work within an hour.

To receive, you can create an interaction event:

bot.ws.on("INTERACTION_CREATE", async interaction => {
  // Do stuff here - interaction is an InteractionResponse object. To get the name, use interaction.data.name
  // In particular, the values you passed to the interaction when creating it will be passed back here
});

To send a response to an interaction, you can use the following:

bot.api.interactions(interaction.id, interaction.token).callback.post({
  data: {
    type: 3,
    data: {
      content: `I'm currently looking it up - it'll be directly messaged to you soon.`,
    },
  },
});

Note (this isn't well-documented as far as I know) that if you want an ephemeral message to be sent, you should add a flag of 64 (1 << 6) to whatever flags you send in the message response. The documentation (should) have everything else there, and if you want, you can also send a regular channel message (get channel id by interaction.channel_id).

These things can (and should) be implemented in the official library (unless I'm using something which I shouldn't use).

almostSouji commented 3 years ago

please stop recommending people to use the undocumented, unsupported and private Client#api accessor in production bots.

5106 will add discord.js support for this, anything else does simply not belong on this repository, as they are increasingly hacky workaround and partial applications of that PR.

KevSlashNull commented 3 years ago

@almostSouji, nobody suggested using that in production, I explicitly stated that my solution was intended for non-production test uses, so people don‘t need to set up a web socket with the Discord API. I also understood @AmoleR’s solution as temporary workaround (in non-production uses) but that’s up for debate. However, I fully agree with your point, which is why I’ve deleted my message. Looking forward to #5106!

sylv256 commented 3 years ago

Nice! Looking forward to using this in production once it's in stable.

gaycookie commented 3 years ago

As a person who just finished writing some things using Discord's API I can add a few comments on this (that are hard to find normally):

  1. If you're interested in creating a slash command, at this point, you require to have your bot authenticated to the server with application.commands in addition to bot. In particular, I (believe) it may have to be manually removed and added to every server.
  2. To create a (global) command, you can add this to your code:
bot.api.applications(bot.user.id).commands.post({
  data: {
    name: "commandname",
    description: "Command Description",
  },
});

You can pass other options and things in the data (check the docs for this). Keep in mind that it's not possible to add spaces in the command name, so you want to use subcommands (or subcommand groups) for this. If you want to update a command, you can either post (as above) or use a patch request, such as:

bot.api.applications(bot.user.id).commands(commandID).patch({
  data: {
    name: "commandname",
    description: "Command Description",
  },
});

To delete, you can just use bot.api.applications(bot.user.id).commands(commandID).delete(), and to get all of them, you can use bot.api.applications(bot.user.id).commands.get().

Note that you can add a .guilds(guildID) after applications(bot.user.id) to deploy to a specific guild (which is instant). The above method will work within an hour.

To receive, you can create an interaction event:

bot.ws.on("INTERACTION_CREATE", async interaction => {
  // Do stuff here - interaction is an InteractionResponse object. To get the name, use interaction.data.name
  // In particular, the values you passed to the interaction when creating it will be passed back here
});

To send a response to an interaction, you can use the following:

bot.api.interactions(interaction.id, interaction.token).callback.post({
  data: {
    type: 3,
    data: {
      content: `I'm currently looking it up - it'll be directly messaged to you soon.`,
    },
  },
});

Note (this isn't well-documented as far as I know) that if you want an ephemeral message to be sent, you should add a flag of 64 (1 << 6) to whatever flags you send in the message response. The documentation (should) have everything else there, and if you want, you can also send a regular channel message (get channel id by interaction.channel_id).

These things can (and should) be implemented in the official library (unless I'm using something which I shouldn't use).

Sadly using Typescript this is an issue! Argument of type '"INTERACTION_CREATE"' is not assignable to parameter of type 'WSEventType'

almostSouji commented 3 years ago

Again, this issue is used to track the completion of the feature and linked PR, not to support, supply, or discuss hacky workarounds prior to release.

amiga-500 commented 3 years ago

ephemeral add a flag of 64 (1 << 6) to whatever flags you send in the message response. The

Just a heads up about this.....it only works on slash command responses. Slash responses are not "Message" objects so your saying (and linking) the message object as reference is incorrect. Also to implement this correctly one uses the "flags" parameter in the slash response BUT it only works for plain vanilla content responses back. So if you include embed rich content the flag will take affect but will completely ignore your embed content -- meaning, the display will show as empty. Seems like that is a bug in the api.

almostSouji commented 3 years ago

Is there a way to send a private response that ONLY the original /slash command requester sees it?

Precisely what ephemeral messages are. Flags on outgoing interaction responses are currently not documented and as said above slash commands are not yet fully released (discord calls it "public dev beta") and discord.js has not yet adopted them. This issue serves to track the feature, not to provide or receive support for using raw API requests.

amiga-500 commented 3 years ago

Is there a way to send a private response that ONLY the original /slash command requester sees it?

Precisely what ephemeral messages are. Flags on outgoing interaction responses are currently not documented and as said above slash commands are not yet fully released (discord calls it "public dev beta") and discord.js has not yet adopted them. This issue serves to track the feature, not to provide or receive support for using raw API requests.

Thanks for the quick reply. I got it working but it seems to only work on interaction responses while only using the content parameter. The embeds doesnt work with it. So if the response back doesnt use content but instead uses embeds it will just show a empty response :( :( Any work around for that so as to have ephemeral while showing embed content?

almostSouji commented 3 years ago

no, embeds are not supported in ephemeral responses

amiga-500 commented 3 years ago

no, embeds are not supported in ephemeral responses

Thanks again for the clarification.

amiga-500 commented 3 years ago

Quick questions.

  1. Is it possible to get back an interactive request when a user clicks a reaction found on a bot's message? Or are the only interaction requests we get are from slash commands?

  2. I dont use the gateway but instead have discord send back http post requests to a url. It works well for my case (since i use php). Is there a special scope that i must enable to be notified when a new message is posted in a specific channel on my server? I am still roaming the API docs but dont see anything. Could have sworn it was somewhere.

seiyria commented 3 years ago

@amiga-500 please see this comment: https://github.com/discordjs/discord.js/issues/5103#issuecomment-757887662

sindrekjr commented 3 years ago

Any good guess on when support for slash commands will be finalized and merged, and if it will be ready for when slash commands move out of beta?

ckohen commented 3 years ago

It's unrealistic to give any guesses here, since discord is still making breaking changes to the API that we'll need to acommadate. We have been told that the API will be stable after https://github.com/discord/discord-api-docs/pull/2615 is merged, so that's likely when work can pick back up.

FlyCrafting commented 3 years ago

It's unrealistic to give any guesses here, since discord is still making breaking changes to the API that we'll need to acommadate. We have been told that the API will be stable after discord/discord-api-docs#2615 is merged, so that's likely when work can pick back up.

the pr in discord repo is merged, what about support in discordjs? Cant wait for this feature, all my work of bot stopped due to waiting of slash commands..

ghost commented 3 years ago

how to delete the slash commands? just ask..

wonderlandpark commented 3 years ago

how to delete the slash commands? just ask..

https://github.com/discordjs/discord.js/issues/5103#issuecomment-757887662

ghost commented 3 years ago

ok thx..

NateLevin1 commented 3 years ago

Since we can now use this, is there a PR for a nicer API? At the moment the API is pretty hacky looking.

advaith1 commented 3 years ago

5448

Colonel-Ltd commented 3 years ago

How awaitMessages can be done with slash command ?

monbrey commented 3 years ago

How awaitMessages can be done with slash command ?

The issue tracker is only for bug reports and enhancement suggestions. If you have a question, please ask it in the Discord server instead of opening an issue – you will get redirected there anyway.

LoneDev6 commented 3 years ago

As a person who just finished writing some things using Discord's API I can add a few comments on this (that are hard to find normally):

1. If you're interested in creating a slash command, at this point, you require to have your bot authenticated to the server with `application.commands` in addition to `bot`. In particular, I (believe) it may have to be manually removed and added to every server.

2. To create a (global) command, you can add this to your code:
bot.api.applications(bot.user.id).commands.post({
  data: {
    name: "commandname",
    description: "Command Description",
  },
});

You can pass other options and things in the data (check the docs for this). Keep in mind that it's not possible to add spaces in the command name, so you want to use subcommands (or subcommand groups) for this. If you want to update a command, you can either post (as above) or use a patch request, such as:

bot.api.applications(bot.user.id).commands(commandID).patch({
  data: {
    name: "commandname",
    description: "Command Description",
  },
});

To delete, you can just use bot.api.applications(bot.user.id).commands(commandID).delete(), and to get all of them, you can use bot.api.applications(bot.user.id).commands.get().

Note that you can add a .guilds(guildID) after applications(bot.user.id) to deploy to a specific guild (which is instant). The above method will work within an hour.

To receive, you can create an interaction event:

bot.ws.on("INTERACTION_CREATE", async interaction => {
  // Do stuff here - interaction is an InteractionResponse object. To get the name, use interaction.data.name
  // In particular, the values you passed to the interaction when creating it will be passed back here
});

To send a response to an interaction, you can use the following:

bot.api.interactions(interaction.id, interaction.token).callback.post({
  data: {
    type: 3,
    data: {
      content: `I'm currently looking it up - it'll be directly messaged to you soon.`,
    },
  },
});

Note (this isn't well-documented as far as I know) that if you want an ephemeral message to be sent, you should add a flag of 64 (1 << 6) to whatever flags you send in the message response. The documentation (should) have everything else there, and if you want, you can also send a regular channel message (get channel id by interaction.channel_id).

These things can (and should) be implemented in the official library (unless I'm using something which I shouldn't use).

Keep in mind that this message type is deprecated and won't work anymore https://discord.com/channels/533407895010803753/786912739313975336/838704482463645727

neelkarma commented 3 years ago

5448 got merged 🎉