Code Monkey home page Code Monkey logo

discord.net-labs's Introduction

Logo

NuGet MyGet Build Status Discord

What is labs?

Discord.NET Labs is an experimental branch of Discord.NET that introduces the newest features of discord for testing and experimenting. Nothing here is guaranteed to work but you are more than welcome to submit bugs in the issues tabs


Sponsor us! โค

  • If this library benefits you consider sponsoring us through Open Collective, Github Sponsors, or Paypal. Your financial contributions help us pay for Discord.Net related services like our doc hosts. Only sponsor if you're financially stable!

Known compatibility issues

  • Playwo's InteractivityAddon
    • โŒ Reason: The default package depends on Discord.NET instead of labs.
    • โœ” Fix: InteractivityAddon.Labs, which implements some of the features added in Discord.Net-Labs.

How to use

Setting up labs in your project is really simple, here's how to do it:

  1. Remove Discord.Net from your project
  2. Add Discord.Net Labs nuget to your project
  3. That's all!

Additional installation info can be found here.

Branches

Dev

This branch is kept up to date with dnets dev branch. we pull of it to ensure that labs will work with pre existing dnet code.

release/3.x

This branch is what will be pushed to nuget, sometimes its not up to date as we wait for other features to be finished.

feature/xyz

These branches are features for new things, you are more than welcome to clone them and give feedback in the discord server or issues tab.

discord.net-labs's People

Contributors

antitcb avatar auralytical avatar bond-009 avatar cenngo avatar chris-johnston avatar cottagedwellingcat avatar csmir avatar d4n3436 avatar digitechs avatar drobbins329 avatar finitereality avatar flamanis avatar foxbot avatar googie2149 avatar helpfulstranger999 avatar inikoni avatar joe4evr avatar k-boyle avatar khionu avatar killerfrienddk avatar lassieme avatar mattthedev avatar moiph avatar mrcakeslayer avatar nekzor avatar obsidianminor avatar quinchs avatar rutherther avatar still34 avatar subzero0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

discord.net-labs's Issues

Having AlwaysAcknowledgeInteractions = false breaks FollowupAsync

Context

Version: Discord.Net.Labs 2.4.9

Problem

It appears that setting AlwaysAcknowledgeInteractions = false always makes it so that the wrong REST endpoint is used

interactions/{application.id}/{interaction.token}/callback

Same phenomenon is experienced with AcknowledgeAsync to RespondAsync.

Data:
Request (taken from AcknowledgeAsync to RespondAsync example, exception from RespondAsync):

Method: POST
Endpoint: interactions/{application.id}/{interaction.token}/callback
Json: {"type":4,"data":{"tts":false,"content":"hi","allowed_mentions":null,"components":[{"type":1,"components":[{"type":2,"style":1,"label":"Confirm","custom_id":"id_1","url":null,"disabled":false},{"type":2,"style":4,"label":"Cancel","custom_id":"id_2","url":null,"disabled":false}]}]}}

"Response":

Message: The server responded with error 10062: Unknown interaction
HttpCode: 404

Joining a thread throws exception

Summary

When joining a thread, an exception is thrown because of a bucket id error.

09:56:21 Gateway     A ThreadCreated handler has thrown an unhandled exception.:
System.ArgumentNullException: Value cannot be null. (Parameter 'key')
   at System.ThrowHelper.ThrowArgumentNullException(String name)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Discord.Net.Queue.RequestQueue.GetOrCreateBucket(RequestOptions options, IRequest request)
   at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request)
   at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request)
   at Discord.API.DiscordRestApiClient.SendAsync(String method, String endpoint, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options)
   at Discord.API.DiscordRestApiClient.JoinThreadAsync(UInt64 channelId, RequestOptions options)
   at bot_class._client_ThreadCreated(SocketThreadChannel arg) in C:\Users\nozsa\source\repos\GameHubSlave_V2\GHS_V2\GHS_V2\BotMain.cs:line 797
   at Discord.EventExtensions.InvokeAsync[T](AsyncEvent`1 eventHandler, T arg)
   at Discord.WebSocket.DiscordSocketClient.TimeoutWrap(String name, Func`1 action)

A way to send a SocketInteraction response without retrieving the original response

Currently when using SocketInteraction.RespondAsync(), the method makes 2 API calls:

  1. POST /interactions/{interaction.id}/{interaction.token}/callback, to send a response to the interaction.
  2. GET /webhooks/{application.id}/{interaction.token}/messages/@original, to get the original interaction response.

Making an extra API call is expensive if you only want to send the interaction response (e.g. modify the message).

My suggestion is the following:

  • Remove the 2nd API call from RespondAsync(), or create a new method SendResponseAsync() that only sends the response.
  • Create a new method GetOriginalResponseAsync() that gets the original interaction response.

"ComponentBuilder.WithButton" takes customID as a required param but still accepts a Url despite not being allowed to use both.

Changing CustomID to be optional and assume the writer knows the constaint there seems like a solid solution, since an error is thrown if you pass both together. There are a few other solutions you could employ, so I didn't want to just commit this change myself.

Alternatively -- Remove URL from this method entirely. Using a link would require no customID and a specific style, so it would remove some ambiguity if you just left links out of this.

Also, in the same class, is this not redundent?

public ComponentBuilder WithButton(ButtonBuilder button)

when this exists?

public ComponentBuilder WithButton(ButtonBuilder button, int row = 0)

SocketMessageComponent respond async with component vs SocketSlashCommand respond async with component

I am having a bit of trouble making the bot show my buttons with a component builder for a slash command. I am unable to get the Await command.RespondAsync() to send the buttons with the component builder, the function accepts it as an argument but will not display them. However clicking a button and sending a component through the Await button.RespondAsync() will show them. There are no errors displaying either. Examples:

(vb.net) button click sends buttons in response with component builder

Private Async Function HandleButton(ByVal button As SocketMessageComponent) As Task
        Dim customID As String = button.Data.CustomId
        If customID = "guess-hint" Then
                Dim cbuilder As ComponentBuilder = New ComponentBuilder
                cbuilder.WithButton("Hint", customId:="guess-hint", ButtonStyle.Primary, row:=0)
                cbuilder.WithButton("Skip", customId:="guess-skip", ButtonStyle.Danger, row:=0)
       
                Dim builder As EmbedBuilder = New EmbedBuilder
                builder.WithAuthor("Embed Example", "http://imglink.com/image.jpg")
                builder.WithThumbnailUrl("http://imglink.com/image.jpg")
                builder.WithColor(System.Drawing.Color.FromArgb(255, 255, 65, 65))
                builder.WithDescription("Description example.")

                Await button.RespondAsync(embed:=builder.Build, component:=cbuilder.Build)
        End If
End Function

(vb.net) slash command does not send buttons in response with component builder

Private Async Function HandleCommand(ByVal command As SocketSlashCommand) As Task
        If command.Data.Name = "start" Then
                Dim cbuilder As ComponentBuilder = New ComponentBuilder
                cbuilder.WithButton("Hint", customId:="guess-hint", ButtonStyle.Primary, row:=0)
                cbuilder.WithButton("Skip", customId:="guess-skip", ButtonStyle.Danger, row:=0)
       
                Dim builder As EmbedBuilder = New EmbedBuilder
                builder.WithAuthor("Embed Example", "http://imglink.com/image.jpg")
                builder.WithThumbnailUrl("http://imglink.com/image.jpg")
                builder.WithColor(System.Drawing.Color.FromArgb(255, 255, 65, 65))
                builder.WithDescription("Description example.")

                Await command.RespondAsync(embed:=builder.Build, component:=cbuilder.Build)
        End If
End Function

Setting emoji to the component button makes the server respond with "Bad Request".

This is how I made the builder:
builder = new ComponentBuilder().WithButton("Private", ButtonStyle.Secondary, customId: "private", emote: new Emoji("๐Ÿ”’"));

When I send it I get the error as stated in the issue title. If I remove the emote it works properly. I don't know if I'm doing something wrong (by the way, thanks for the great job on the new features).

Multi-row buttons gives bad request

The following code produces a bad request error when attempting to send

var successButton = new ButtonBuilder()
      .WithStyle(ButtonStyle.Success);

var primaryButton = new ButtonBuilder()
      .WithStyle(ButtonStyle.Primary);

var secondaryButton = new ButtonBuilder()
      .WithStyle(ButtonStyle.Secondary);
            
var dangerButton = new ButtonBuilder()
      .WithStyle(ButtonStyle.Danger);

var component = new ComponentBuilder()
      .WithButton(successButton, 0)
      .WithButton(primaryButton, 1)
      .WithButton(secondaryButton, 2)
      .WithButton(dangerButton, 3)
      .Build();

await Context.Channel.SendMessageAsync("Multi-Buttons!", component: component);

Hyperlink buttons raise a bad request error

Using this code

        [Command("button")]
        public async Task ButtonAsync()
        {
            var builder = new ComponentBuilder().WithButton("Hello!", ButtonStyle.Link, emote: null, customId: "hello_button",
                url: "https://github.com/shift-eleven/Alexandra", disabled: false, row: 0);

            await Context.Channel.SendMessageAsync("Buttons!", component: builder.Build());
        }

Upon attempting to send them to a channel, Im getting a bad request error

 Discord.Commands.CommandService[0]
      Command:
      Discord.Commands.CommandException: Error occurred executing "button" for shift-eleven#7304 in Black Rose/bot-test.
       ---> Discord.Net.HttpException: The server responded with error 400: BadRequest
         at Discord.Net.Queue.RequestBucket.SendAsync(RestRequest request)
         at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request)
         at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request)
         at Discord.API.DiscordRestApiClient.SendJsonAsync[TResponse](String method, String endpoint, Object payload, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options)
         at Discord.API.DiscordRestApiClient.CreateMessageAsync(UInt64 channelId, CreateMessageParams args, RequestOptions options)
         at Discord.Rest.ChannelHelper.SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, String text, Boolean isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageCo
mponent component, RequestOptions options)
         at Harley.Modules.GeneralModule.ButtonAsync() in D:\Projects\C# projects\Harley\Harley\Modules\GeneralModule.cs:line 21
         at Discord.Commands.ModuleClassBuilder.<>c__DisplayClass6_0.<<BuildCommand>g__ExecuteCallback|0>d.MoveNext()
      --- End of stack trace from previous location ---
         at Discord.Commands.CommandInfo.ExecuteInternalAsync(ICommandContext context, Object[] args, IServiceProvider services)
         --- End of inner exception stack trace ---
dbug: Discord.WebSocket.DiscordSocketClient[0]
      Rest: POST channels/825360796153544735/messages: 507.73 ms

Full Stack trace

It is noted that the example in the readme works as intended, alongside with the event handler

Message component's Message property is SocketSystemMessage?

Summary

SocketMessage.Create thinks that the message for a message component is a system message:

            if (model.Type == MessageType.Default || model.Type == MessageType.Reply)
                return SocketUserMessage.Create(discord, state, author, channel, model);
            else
                return SocketSystemMessage.Create(discord, state, author, channel, model);

This means that there is a message type that is passed along that is not handled here.

Weird issue with buttons

This morning i created buttons for my modules command, it worked perfectly fine until just now, it says this:
Discord.Net.HttpException: The server responded with error 50035: Invalid Form Body at Discord.Net.Queue.RequestBucket.SendAsync(RestRequest request) at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request) at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request) at Discord.API.DiscordRestApiClient.SendJsonAsync[TResponse](String method, String endpoint, Object payload, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options) at Discord.API.DiscordRestApiClient.CreateMessageAsync(UInt64 channelId, CreateMessageParams args, RequestOptions options) at Discord.Rest.ChannelHelper.SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, String text, Boolean isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, RequestOptions options) at Discord.WebSocket.SocketTextChannel.Discord.IMessageChannel.SendMessageAsync(String text, Boolean isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component) at Mewdeko.Modules.Help.Help.Commands(String module) in D:\Docs\Mewdeko\Mewdeko.Core\Modules\Help\Help.cs:line 307 at Discord.Commands.ModuleClassBuilder.<>c__DisplayClass6_0.<<BuildCommand>g__ExecuteCallback|0>d.MoveNext() --- End of stack trace from previous location --- at Discord.Commands.CommandInfo.ExecuteInternalAsync(ICommandContext context, Object[] args, IServiceProvider services) at Discord.Commands.CommandInfo.ExecuteInternalAsync(ICommandContext context, Object[] args, IServiceProvider services) at Discord.Commands.CommandInfo.ExecuteInternalAsync(ICommandContext context, Object[] args, IServiceProvider services) at Discord.Commands.CommandInfo.ExecuteAsync(ICommandContext context, IEnumerable`1 argList, IEnumerable`1 paramList, IServiceProvider services)

I havent changed my code at all whenthis happenned
Button Code:
var builder = new ComponentBuilder() .WithButton("Custom Reactions", customId: "customreactions", ButtonStyle.Primary, row: 0) .WithButton("Administration", customId: "administration", ButtonStyle.Primary, row: 0);

client.GetUser() returning null on valid args

var user = client.GetUser(name, discriminator); if (user != null) { await context.Response.SendResponseAsync("true"); return; }
Using Discord.Net 2.4 this works fine. Using Labs it fails and returns null.

Reaction rate limit issue from DDN not fixed

When you listen for reaction events, you'll eventually get your bot trying to delete a reaction which will repeat until you are temporarily banned from the gateway. This issue was fixed in DDN 2.4.0, but is still present in DNL.

DateTimeOffset is not nullable

Summary

When using DateTimeOffset of timestamps, discord can specify null for them. C# specifies that DateTimeOffset is a non nullable type.

Models effected

There are possibly more models that are effected that are not listed in this issue.

Clients using SetActivityAsync get disconnected and reconnected

Summary

Sharded clients seem to behave oddly when using the 3.X branch, the root cause of the behavior is still unknown and further testing is required.

image
image

Im unable to reproduce locally so if anyone has any debug information that they can supply please do

Embed[] alongside Embed

In a recently commit, RespondAsync and FollowupAsync lost their single embed overloads in favor of a single method that takes an array of embeds. This is a pretty code breaking change for many people, so I propose that instead of adding an overload or something adjacent, we take the current methods and add an optional single embed param.

Logically the flow is fairly simple. We would be to check if the embeds param is null, and if so check if the embed param isn't null. In the scenario where both of these is true, set embeds to be an array with that single embed and leave the rest of the code unchanged.

Now instead of leaving it up to the user to write new[]{myEmbed.build()}, they can just clarify embed: or embeds: as needed.

I've made a branch in my fork with this code change commit already if anyone would like to take a look and give opinions. I'm not saying this is necessary or something we need, but I think it's worth considering and getting input on.

The code change in my new branch can be found here:
Zeiin@88a8e95

Thread events/models new data

Looking at some beta stuff for threads there appears to be some new data models with them:

{
  "t": "THREAD_UPDATE",
  "s": 755,
  "op": 0,
  "d": {
    "type": 11,
    "thread_metadata": {
      "locked": true,
      "auto_archive_duration": 60,
      "archived": true,
      "archive_timestamp": "2021-08-06T02:18:35.736847+00:00"
    },
    "rate_limit_per_user": 0,
    "parent_id": "483409788508831754",
    "owner_id": "302968847353249813",
    "name": "test",
    "message_count": 1,
    "member_count": 1,
    "last_message_id": "873026548968611840",
    "id": "873026547810975795",
    "guild_id": "483409624100503562",
    "audience": {
      "parent_id": "483409788508831754",
      "member_ids": [
        "302968847353249813"
      ],
      "channel_type": 11
    }
  }
}

Source: A5rocks#9289

Getting an issue when modifying embeds on the new commits after everything was renamed to EMbeds

System.MissingMethodException: Method not found: 'Discord.Optional`1<Discord.Embed> Discord.MessageProperties.get_Embed()'.
   at Discord.Rest.MessageHelper.ModifyAsync(IMessage msg, BaseDiscordClient client, Action`1 func, RequestOptions options)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Discord.Rest.MessageHelper.ModifyAsync(IMessage msg, BaseDiscordClient client, Action`1 func, RequestOptions options)
   at Discord.WebSocket.SocketUserMessage.ModifyAsync(Action`1 func, RequestOptions options)
   at Mewdeko.Modules.Help.Help.HandleModules(SocketInteraction ine) in D:\Docs\Mewdeko\Mewdeko.Core\Modules\Help\Help.cs:line 119
   at Discord.EventExtensions.InvokeAsync[T](AsyncEvent`1 eventHandler, T arg)
   at Discord.WebSocket.DiscordSocketClient.TimeoutWrap(String name, Func`1 action)

Exception when responding to interaction with ephemeral true

Using RespondAsync to respond to an Interaction using ephemeral true will cause this exception. AlwaysAcknowledgeInteractions is set to False

Discord.Net.HttpException: The server responded with error 10008: Unknown Message
   at Discord.Net.Queue.RequestBucket.SendAsync(RestRequest request)
   at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request)
   at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request)
   at Discord.API.DiscordRestApiClient.SendAsync[TResponse](String method, String endpoint, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options)
   at Discord.API.DiscordRestApiClient.GetInteractionResponse(String interactionToken, RequestOptions options)
   at Discord.Rest.InteractionHelper.SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response, UInt64 interactionId, String interactionToken, RequestOptions options)
   at Discord.WebSocket.SocketMessageComponent.RespondAsync(String text, Boolean isTTS, Embed embed, InteractionResponseType type, Boolean ephemeral, AllowedMentions allowedMentions, RequestOptions options, MessageComponent component)

How do I make Slash Commands appear?

I'm trying to make my bot automatically create a slash command for every normal command it has, and for the most part, that is working fine. But, I have a question.

The first one is that even after I create the slash command, it doesn't show in the slash menu. I know it is there, if I tell my bot to reply with all slash commands I can see they are there, but when I type "/", all I can see are the built-in commands, and slash commands from other bots. Anything I should do for that?

Here is my code. I am using the latest Discord.Net.Labs

static void PropertiesApproach(CommandService cmds)
            {
                foreach (CommandInfo cmd in cmds.Commands)
                {
                    SlashCommandCreationProperties b = new()
                    {
                        Description = cmd.Summary,
                        Name = cmd.Name,
                        Options = new(new()),
                    };

                    if (cmd.Summary.Length > 100) b.Description = cmd.Summary.Remove(97) + "...";

                    foreach (ParameterInfo param in cmd.Parameters)
                    {
                        ApplicationCommandOptionProperties o = new()
                        {
                            Description = param.Summary,
                            Name = param.Name,
                            Required = !param.IsOptional,
                            Type = ApplicationCommandOptionType.String,
                        };

                        if (param.Summary.Length > 100) o.Description = cmd.Summary.Remove(97) + "...";

                        if (param.Type == typeof(int) || param.Type == typeof(ulong) || param.Type == typeof(float)) o.Type = ApplicationCommandOptionType.Integer;
                        else if (param.Type == typeof(bool)) o.Type = ApplicationCommandOptionType.Boolean;
                        else if (param.Type == typeof(IUser)) o.Type = ApplicationCommandOptionType.User;
                        else if (param.Type == typeof(IChannel)) o.Type = ApplicationCommandOptionType.Channel;
                        else if (param.Type == typeof(IRole)) o.Type = ApplicationCommandOptionType.Role;

                        b.Options.Value.Add(o);
                    }

                    Internals.client.Rest.CreateGlobalCommand(b);
                }
            }

any answer would be appreciated, thanks

Some perms missing

Some permissions missing according Discord docs:

PERMISSION VALUE DESCRIPTION CHANNEL TYPE
USE_SLASH_COMMANDS 0x0080000000ย (1 << 31) Allows members to use slash commands in text channels T
REQUEST_TO_SPEAK 0x0100000000ย (1 << 32) Allows for requesting to speak in stage channels. (This permission is under active development and may be changed or removed.) S
MANAGE_THREADS * 0x0400000000ย (1 << 34) Allows for deleting and archiving threads, and viewing all private threads T
USE_PUBLIC_THREADS 0x0800000000ย (1 << 35) Allows for creating and participating in threads T
USE_PRIVATE_THREADS 0x1000000000ย (1 << 36) Allows for creating and participating in private threads T

Respond an interaction with DeferredChannelMessageWithSource

The latest commits added SocketInteraction.ModifyOriginalResponseAsync() to SocketInteraction, which is necessary to update a message that comes from a deferred interaction with callback type 5 (DeferredChannelMessageWithSource).

Unfortunately, the type parameter was removed from SocketInteraction.RespondAsync(), making impossible to properly update a message using this callback type.

This issue should be easy to fix. Maybe adding a bool to DeferAsync() that determines whether to use DeferredUpdateMessage or DeferredChannelMessageWithSource?

Edit: It seems that SocketSlashCommand.DeferAsync() uses DeferredChannelMessageWithSource
..but SocketMessageComponent.DeferAsync() uses DeferredUpdateMessage ๐Ÿค”

In any case, there should be a way to use both types.

ReplyAsync is not found

Upon trying to use ReplyAsync within a command module, I'm hit with an error stating that the method is not found, using the SendMessageFunction on the channel however works as intended.

ArgumentNullException when trying to update a message after interaction with AlwaysAcknowledgeInteractions to false

With AlwaysAcknowledgeInteractions set to false (as suggested in the Readme file), I'm trying to update the original message of the interaction. After casting the interaction to SocketMessageComponent:

await interaction.RespondAsync("test", type: InteractionResponseType.UpdateMessage);

I get the following exception:

System.ArgumentNullException: Value cannot be null. (Parameter 'key')
at System.ThrowHelper.ThrowArgumentNullException(String name)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Discord.Net.Queue.RequestQueue.GetOrCreateBucket(RequestOptions options, IRequest request)
at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request)
at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request)
at Discord.API.DiscordRestApiClient.SendAsync[TResponse](String method, String endpoint, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options)
at Discord.API.DiscordRestApiClient.GetInteractionResponse(String interactionToken, RequestOptions options)
at Discord.Rest.InteractionHelper.SendInteractionResponse(BaseDiscordClient client, IMessageChannel channel, InteractionResponse response, UInt64 interactionId, String interactionToken, RequestOptions options)
at Discord.WebSocket.SocketMessageComponent.RespondAsync(String text, Boolean isTTS, Embed embed, InteractionResponseType type, Boolean ephemeral, AllowedMentions allowedMentions, RequestOptions options, MessageComponent component)
at EmpyManager.Bot.Modules.TemporaryChannels.UserOwnedChannel.PerformActionAsync(String action, SocketMessageComponent interaction) in C:\Users\Torto\source\repos\EmpyManager\Bot\Modules\TemporaryChannels\EmpyManager.Bot.Modules.TemporaryChannels\Entities\UserOwnedChannel.Text.cs:line 127

Update to include context menus

Docs reference: https://discord.com/developers/docs/interactions/application-commands#user-commands

Types:

  • CHAT_INPUT - 1 - Slash commands; a text-based command that shows up when a user types /
  • USER - 2 - A UI-based command that shows up when you right click or tap on a user
  • MESSAGE - 3 - A UI-based command that shows up when you right click or tap on a messages

While CHAT_INPUT requires command names to match ^[\w-]{1,32}$, USER and MESSAGE names can be fixed cased and can include spaces.

Unlike CHAT_INPUT, the other types do not allow the description to be set when creating the command. (and return an empty string instead of null for backward compatibility.)

Also note, you can only create 5 of each MESSAGE or USER command types. (Compared to the 100 of CHAT_INPUT)

AlwaysAcknowledgeGatewayInteractions = true breaks Message components

Context

Version: Discord.Net.Labs 2.4.9

Problem

It appears that setting AlwaysAcknowledgeInteractions = true makes it ignore message components. Changing this to false made them appear again.

It could be an issue with acknowledgement, but due to #95 was unable to test it.

Used command:

await command.RespondAsync(message, component: new ComponentBuilder()
                                .WithButton("Proceed", "id_1", ButtonStyle.Primary)
                                .WithButton("Cancel", "id_2", ButtonStyle.Danger)
                                .Build());

SocketInteraction Defer ephemerally

There is no option to SocketInteraction.DeferAsync ephemerally right now, even though Discord supports it (at least for slash commands).

The problem is that right now to respond ephemerally after 3 second timeout, you must send regular response before the timeout and then a followup for the real response. That creates two messages unnecessarily. If DeferAsync supported ephemeral, it could be done only with one message (loading that is then replaced).

This should be fairly easy to implement, I could do a PR if you confirm to me that changing the method to DeferAsync(bool ephemeral = false, RequestOptions options = null) is okay.

Just a note, this issue is about the same method as in #85, so it could be efficient to implement both issues at once.

SendMessageAsync and SendFileAsync should match RespondAsync and FollowupAsync in primarily taking an embed array since single embed properties are deprecated

SendMessageAsync currently doesn't take an array of embeds, rather just one. Discord's docs mention that messages can (and should) use an embed array instead.

I've started working on this change -- if anyone wants to review that I've done it correctly before I continue and do SendFileAsync.
Please note that currently to keep in line with my previous commit/suggestion, I also have an optional single embed param added to the end of the new method signatures, but those can be removed easily if that other suggestion is decided against.

Review the current code changes here:
Zeiin@1ef7e08

Split up SocketSlashCommand into core parts

Summary

The SocketSlashCommand class currently is a mess, It tries to be both an persistent entity and event data, this leads to confusion on how they are used.

Potential fixes

Split up the SocketSlashCommand class into the entity and event variant, basically the entity should be updateable and modifiable much like the Rest based counterpart is. This entity should also be cached for global and guild specific commands which allows for fetching socket slash commands in socket guilds. This also will help fix the issue of differentiating between slash commands the current bot owns and slash commands from other bots.

The event version of SocketSlashCommand should be something you can just receive and throw away. It shouldn't contain anything but the data received for the slash command interaction. It should also include a reference to its command counterpart so you can get an entity for the command executed.

Issues that this currently causes

  • Receiving APPLICATION_COMMAND_CREATE, APPLICATION_COMMAND_UPDATE, APPLICATION_COMMAND_DELETE from other bots will cause an exception to be thrown.
  • The mixed codebase of slash commands.

Unknown opcode when trying to request speaker

 ---> Discord.Net.WebSocketClosedException: The server sent close 4001: "Unknown opcode."
   at Discord.Net.WebSockets.DefaultWebSocketClient.RunAsync(CancellationToken cancelToken)
   --- End of inner exception stack trace ---
   at Discord.ConnectionManager.<>c__DisplayClass29_0.<<StartAsync>b__0>d.MoveNext()
[02:13:48 WRN] | #0 | Gateway | Failed to start the connection: System.Exception: WebSocket connection was closed
 ---> Discord.Net.WebSocketClosedException: The server sent close 4001: "Unknown opcode."
   at Discord.Net.WebSockets.DefaultWebSocketClient.RunAsync(CancellationToken cancelToken)
   --- End of inner exception stack trace ---
   at Discord.ConnectionManager.<>c__DisplayClass29_0.<<StartAsync>b__0>d.MoveNext()
System.Exception: WebSocket connection was closed
 ---> Discord.Net.WebSocketClosedException: The server sent close 4001: "Unknown opcode."
   at Discord.Net.WebSockets.DefaultWebSocketClient.RunAsync(CancellationToken cancelToken)
   --- End of inner exception stack trace ---
   at Discord.ConnectionManager.<>c__DisplayClass29_0.<<StartAsync>b__0>d.MoveNext()
[02:13:48 WRN] | #0 | Gateway | Failed to start the connection: System.Exception: WebSocket connection was closed
 ---> Discord.Net.WebSocketClosedException: The server sent close 4001: "Unknown opcode."
   at Discord.Net.WebSockets.DefaultWebSocketClient.RunAsync(CancellationToken cancelToken)
   --- End of inner exception stack trace ---
   at Discord.ConnectionManager.<>c__DisplayClass29_0.<<StartAsync>b__0>d.MoveNext()
System.Exception: WebSocket connection was closed
 ---> Discord.Net.WebSocketClosedException: The server sent close 4001: "Unknown opcode."
   at Discord.Net.WebSockets.DefaultWebSocketClient.RunAsync(CancellationToken cancelToken)
   --- End of inner exception stack trace ---
   at Discord.ConnectionManager.<>c__DisplayClass29_0.<<StartAsync>b__0>d.MoveNext()
[02:13:49 WRN] | #0 | Gateway | Failed to resume previous session
[02:13:50 WRN] | #0 | Gateway | Serializer Error

Some errors

Here's some fixes I had to do in order to be able to use some features

SocketApplicationCommand:
Null check on options

         internal void Update(Model model)
        {
            this.ApplicationId = model.ApplicationId;
            this.Description = model.Description;
            this.Name = model.Name;
            this.GuildId = model.GuildId;

            this.Options = model.Options != null && model.Options.Any()
                ? model.Options.Select(x => SocketApplicationCommandOption.Create(x)).ToImmutableArray()
                : new ImmutableArray<SocketApplicationCommandOption>();
        }

SocketMessageComponent:

Components not being forwarded to FollowUpAsync if the configuration is used

           if (Discord.AlwaysAcknowledgeInteractions)
                return await FollowupAsync(text, isTTS, embed, ephemeral, type, allowedMentions, options, component);


Author Null check for interaction triggered from other interactions

        internal override void Update(Model model)
        {
            base.Update(model);

            if (model.Message.IsSpecified)
            {
                if (this.Message == null)
                {
                    SocketUser author = null;
                    if (model.Message.Value.Author.IsSpecified)
                    {
                        if (this.Channel is SocketGuildChannel channel)
                        {
                            if (model.Message.Value.WebhookId.IsSpecified)
                                author = SocketWebhookUser.Create(channel.Guild, Discord.State, model.Message.Value.Author.Value, model.Message.Value.WebhookId.Value);
                            else
                                author = channel.Guild.GetUser(model.Message.Value.Author.Value.Id);
                        }
                        else
                            author = (this.Channel as SocketChannel).GetUser(model.Message.Value.Author.Value.Id);
                    }
                    this.Message = SocketMessage.Create(this.Discord, this.Discord.State, author, this.Channel, model.Message.Value);
                }
                else
                {
                    this.Message.Update(this.Discord.State, model.Message.Value);
                }
            }
        }

ApplicationCommandOption:
Issue prevent proper deserialization / serialization (forgot the exact case, its been a while already)

            this.Required = option.Required.HasValue
                ? option.Required.Value
                : Optional<bool>.Unspecified;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.