-
-
Notifications
You must be signed in to change notification settings - Fork 741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing new Discord features: Interaction & Slash commands #1717
Conversation
Thanks for the contribution! However, before the changes can be moved forward to any future code review, please discard any non-essential changes in the csprojs and add proper documentation for all public members. Thanks! |
I'm aware the latest pushes added an analyzer that complains a lot, but please ignore it and make your classes consistent with the others (like removing the spaces between properties etc). I'll review when this PR gets closer to completion. |
Temporarily disabled the style enforcement via 36de7b2 |
…rked on SocketInteraction
fae3fbe fixes the above mentioned issues and adds comments to everything except SocketInteraction |
…correct documentation. Added AlwaysAcknowledgeInteractions to the socket client config
…into Interactions
If some people want to test the new event in the socket client, and let me know if there's any issues. I've tested it a bit and have found no issues. There are still some stuff todo though:
I think the best way we can implement writing slash command is with the default Discord.Net.Commands command service, I'm not too familiar with that project so if someone else could take a look at it that would be great |
I'm thinking more about command service stuff, should Slash Commands be written with attributes? [SlashCommand("CommandName", "Description", new Option()
{
"user", // option name
"a user", // option description
OptionType.User, // option type
true, // required?
},
new Option()
{
"reason", // option name
"the reason", // option description
OptionType.String, // option type
true, // required?
})]
public async Task TestCommand(SocketGuildUser user, string reason)
{
} There are a lot of parameters for slash commands so its kind of hard to decide how to implement them. The downside to the attribute method is that it gets messy really fast |
Won't work. Attribute parameters must be constants, which means no |
Just realized that. This is going to be complicated... Another possibility is to make a class for your slash command, something like this: public class MySlashCommand : SlashCommandBase
{
private DiscordSocketClient client;
public MySlashCommand(DiscordSocketClient client)
: base()
{
// Init
this.client = client;
// Maybe listen for this command with an event?
this.Executed += HandleExecute;
// Register the command here with all the command args?
base.Create("some arguments");
}
public async Task HandleExecute(SocketInteraction arg)
{
await arg.RespondAsync("Success!");
}
} |
Nice job! Maybe the command service changes could be a different PR? Since that's a bit separate from the implementation of the API on the client, and probably going to be complicated. Not everyone needs the Discord.Net command service to use this. |
I agree, Im going to make a mockup command service for SocketInteractions as a reference. We do still need a public way of fetching, creating, modifying, and deleting Global/guild application commands. I'm going to work on that now, and then I think we're ready for a review! |
New Rest entities: RestApplicationCommand,RestGlobalCommand, RestGuildCommand, RestApplicationCommandOption, RestApplicationCommandChoice, RestApplicationCommandType. Added public methods to the RestClient to fetch/create/edit interactions.
I'm unable to test the functionality of the new rest methods until tomorrow so you are all free to go let me know what to fix lol |
…LICATION_COMMAND_CREATE gateway events. Added SocketApplicationCommands, Added method in SocketGuild to fetch that guilds ApplicationCommands. Tested all rest routes and fixed them accordingly. Did more testing and I think its ready to go
All the rest functionality works now, and the socket stuff also works. |
I may be a bit late to the party, but couldn't we parse the currently existing parameter attributes and use them for the SlashCommand? For example, my current Bot looks like this: [Command("item")]
[Summary("Search for an item in the manifest.")]
public async Task ShowItems(
[Remainder]
[Name("Name")]
[Summary("Specify the name of the item here. You can use RegExp to give a more specific search term.")]
string name)
{
await ShowItemsLang(name, "en");
} And we could simply modify it to something like this: [Command("item")]
[SlashCommand("item")] // NEW
[Summary("Search for an item in the manifest.")]
public async Task ShowItems(
[Remainder]
[Required] // NEW (if required)
[Name("Name")]
[Summary("Specify the name of the item here. You can use RegExp to give a more specific search term.")]
string name)
{
await ShowItemsLang(name, "en");
} This way, we would have all the information your example above would also have. The types are already defined, so I doubt there is a need to re-define them.
|
I think creating choices can also be accomplished by attributes since there are only 2 fields that need to be filled. I don't think there will be a lot of people who will add more than a handful of choices per option so i think this should'nt be that messy, relatively speaking. [SlashCommand("rainbow6", "description")]
public class Rainbow6
{
[SubCommandGroup("player", "description")]
[SubCommand("casual", "description")]
public async Task GetCasual ( [Description("")] [Required]string username,
[Description("")] [Choices("UPlay", "uplay")][Choices("XBox Live", "xbl")][Choices("PlayStation Network", "psn")]string platform)
{
}
[SubCommandGroup("player", "description")]
[SubCommand("ranked", "description")]
public void GetRanked ( [Description("")] [Required]string username,
[Choices("UPlay", "uplay")][Choices("XBox Live", "xbl")][Choices("PlayStation Network", "psn")] string platform )
{
}
[SubCommandGroup("operator", "description")]
[SubCommand("stats", "description")]
public void GetStats ( [Description("")] [Required]string username,
[Choices("Seasonal", "seasonal")][Choices("Overall", "overall")]string scope,
[Choices("Close", 5)][Choices("Long", 10)]int saesons)
{
}
} |
@Cenngo |
As mentioned before, using Attributes will get really messy. I mean just look at your own code @Cenngo and now imagine more parameters. client.RegisterSlashCommand(
new SlashCommandBuilder("testCommand")
.AddParameter("name", "type", "description", ["choices"])
.AddParameter(...)
.MakeGlobal()
.AddSubCommand(new SlashCommandBuilder(...)...)
.Handler(typeof(TestCommandHandler))
.Build()
) Inside the handler, which is a class that inherits from - let's say - |
@ZargorNET @Mijago @Cenngo I'm going to open a new PR for implementing slash commands to the command service, this pull is just implementing them into the client. I like the idea of a The reason why I think we should support both is both are easy to write, understandable, and can be interpreted easily with reflection. With my bots and custom command service I have each command in its own class and its much more manageable to write commands that way. Another + for class based slash commands is the class is the context, meaning your context and useful methods lives in Attributes are good because it would be very easy to migrate/add slash commands to your existing commands, meaning you don't have to re-write all your commands. The only down side I see with attributes is there's gonna be a lot of them. Tomorrow I'l open a PR for discussion and testing the command service with slash commands. |
Updates and TODOAfter looking at the changes with slash commands on discord site, this PR is not merge ready anymore. There are some issues to address: Invalid follow up message typesWhen sending follow up messages, the API route is based off of websocket and how the current build parses it is to a RestUserMessage. The issue with this is that you should be able to Modify and Delete your follow up messages based off of the docs. Currently this is unsupported. TODO Batch edit application command permissionsCurrently this is not supported at all, this is a TODO. Get Guild Application and Application Command permissionsThis is currently not supported either, this is a TODO. Edit and delete original response.This is also currently unsupported with the current build... Add it to the TODO Bulk Overwrite Guild Application CommandThis is a very useful route and not supported in the build. You guessed it! TODO Bulk Overwrite Global Application CommandSame as above but for global commands. TODO
|
…mission routes Bug fixes and general improvements
@NotOfficer After going in depth with your branch, it looks like you solved some of the issues I was experiencing. At some point soon I will start merging the two as some stuff has changed with the api |
Is the dependency injection issue taken care of in this branch? |
Not entirely true, you can use |
What about this: Instead of using attributes, have the class inherit an interface. That interface has a method you need to implement that will return the slash command, using some SlashCommandBuilder class. |
Why not have it like how we make commands currently, but have an optional bool value that if set to true makes it a slash command. And with it optional it would be by default false so it does not break anyone at all either. |
I mean, from what I'm seeing, there's a lot more to slash commands (Sub command groups and such) than can be effectively created within an attribute |
Could that not be handled by the way sub commands are handled with the |
That could work, yeah. One big class represents the whole slash command. Sub commands are methods, and subcommandgroups are sub-classes, with their own methods as commands.
[SlashCommand("Name", "Description")]
public class SlashCommand1 : SlashCommand
{
// Option types are taken from the parameter types. No sense in defining them twice.
[SlashCommand("Name1", "Description")]
public async Task SubCommand1([SlashOption("Name", "Description")]SocketGuildUser user) { }
public class SubCommandGroup1 {
[SlashCommand("Name2", "Description")]
public async Task SubCommand2() { }
}
} |
I think the best option is to use the pre-existing attributes, and use the |
With the recent chatter and the PR owners statements (@quinchs) I’m not sure where this thing actually is in terms of getting pushed along to being usable. Where is slash command support currently? Where is this wonderful group of people trying to take it? And how can I help? |
The lib maintainers are reworking dnet, once thats done il update the PR's as they are currently out of date. Slash commands and message components are being developed in Discord.NET Labs. They are stable enough to use there and thats where the PRs to dnet will originate. If you want to help out you can check the labs repo and join our Discord server |
Closing as this is implemented in #1923 |
Awesome work! Is there a documentation or example project we can use to reference these new features? |
The docs are sort of limited but yes, The readme of Discord.Net Labs has some documentation of the new features |
Hi, When will this be implemented in Discord.NET instead of labs? |
AFAIK it's already merged but there's no oficial nuget yet, you can download the source and compile it yourself if you want to start using it |
And when will it be available in the official nuget streamline ? We use CI/CD so it's easier for us to setup if we just have to update the nuget. |
Remora.Discord supports slash commands as well, so if you want you could switch to that. I have also migrated from Discord.NET and overall it simplified my bot to the point 75% of it's code was due to problems with Discord.NET and hacks to try to mitigate them. After the migrations I was able to nuke all of it and it would work the same. |
That's a shame but I think I'll give it a try soon, thanks. |
Its currently still in a PR. its a big pr so it will take a bit to get reviewed and refined |
Alright, lets hope it will be merged soon and by available. |
I am really curious for what is the currently status with the PR? |
Hello, I've started writing support for the new discord interaction features.
I think we should talk about Slash commands here, There are some questions I think we all have:
I have wrote in some methods for the RestClient to get, create, edit, and delete global and guild slash commands, I've also created some interfaces to use for Interaction with discord.