Browse Source

Comment updates and explicit conversions for SocketInteractionDataOption's

pull/1717/head
quin lynch 4 years ago
parent
commit
ff08f34779
18 changed files with 198 additions and 52 deletions
  1. +1
    -1
      src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs
  2. +3
    -3
      src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs
  3. +1
    -1
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
  4. +4
    -4
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs
  5. +1
    -1
      src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs
  6. +1
    -1
      src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs
  7. +11
    -1
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs
  8. +5
    -0
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandChoice.cs
  9. +14
    -0
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandOption.cs
  10. +10
    -0
      src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs
  11. +4
    -2
      src/Discord.Net.Rest/Entities/Interactions/RestGlobalCommand.cs
  12. +8
    -0
      src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs
  13. +12
    -0
      src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommand.cs
  14. +3
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommandChoice.cs
  15. +6
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommandOption.cs
  16. +27
    -27
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs
  17. +13
    -5
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteractionData.cs
  18. +74
    -4
      src/Discord.Net.WebSocket/Entities/Interaction/SocketInteractionDataOption.cs

+ 1
- 1
src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs View File

@@ -58,7 +58,7 @@ namespace Discord
public bool? Required { get; set; }

/// <summary>
/// choices for string and int types for the user to pick from
/// choices for string and int types for the user to pick from.
/// </summary>
public List<ApplicationCommandOptionChoiceProperties> Choices { get; set; }



+ 3
- 3
src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs View File

@@ -7,14 +7,14 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// Represents a choice for a <see cref="IApplicationCommandInteractionDataOption"/>. This class is used when making new commands
/// Represents a choice for a <see cref="IApplicationCommandInteractionDataOption"/>. This class is used when making new commands.
/// </summary>
public class ApplicationCommandOptionChoiceProperties
{
private string _name;
private object _value;
/// <summary>
/// The name of this choice
/// The name of this choice.
/// </summary>
public string Name
{
@@ -30,7 +30,7 @@ namespace Discord
// Note: discord allows strings & ints as values. how should that be handled?
// should we make this an object and then just type check it?
/// <summary>
/// The value of this choice
/// The value of this choice.
/// </summary>
public object Value
{


+ 1
- 1
src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs View File

@@ -40,7 +40,7 @@ namespace Discord
/// Deletes this command
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns></returns>
/// <returns>A task that represents the asynchronous delete operation.</returns>
Task DeleteAsync(RequestOptions options = null);
}
}

+ 4
- 4
src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs View File

@@ -7,22 +7,22 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// Represents data of an Interaction Command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondata"/>
/// Represents data of an Interaction Command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondata"/>.
/// </summary>
public interface IApplicationCommandInteractionData
{
/// <summary>
/// The snowflake id of this command
/// The snowflake id of this command.
/// </summary>
ulong Id { get; }

/// <summary>
/// The name of this command
/// The name of this command.
/// </summary>
string Name { get; }

/// <summary>
/// The params + values from the user
/// The params + values from the user.
/// </summary>
IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; }
}


+ 1
- 1
src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// Represents a option group for a command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondataoption"/>
/// Represents a option group for a command, see <see href="https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondataoption"/>.
/// </summary>
public interface IApplicationCommandInteractionDataOption
{


+ 1
- 1
src/Discord.Net.Core/Entities/Interactions/SlashCommandCreationProperties.cs View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Discord
{
/// <summary>
/// A class used to create slash commands
/// A class used to create slash commands.
/// </summary>
public class SlashCommandCreationProperties
{


+ 11
- 1
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommand.cs View File

@@ -9,20 +9,30 @@ using Model = Discord.API.ApplicationCommand;
namespace Discord.Rest
{
/// <summary>
/// Represents a rest implementation of the <see cref="IApplicationCommand"/>
/// Represents a Rest-based implementation of the <see cref="IApplicationCommand"/>.
/// </summary>
public abstract class RestApplicationCommand : RestEntity<ulong>, IApplicationCommand
{
/// <inheritdoc/>
public ulong ApplicationId { get; private set; }

/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public string Description { get; private set; }

/// <summary>
/// The options of this command.
/// </summary>
public IReadOnlyCollection<RestApplicationCommandOption> Options { get; private set; }

/// <summary>
/// The type of this rest application command.
/// </summary>
public RestApplicationCommandType CommandType { get; internal set; }

/// <inheritdoc/>
public DateTimeOffset CreatedAt
=> SnowflakeUtils.FromSnowflake(this.Id);



+ 5
- 0
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandChoice.cs View File

@@ -7,10 +7,15 @@ using Model = Discord.API.ApplicationCommandOptionChoice;

namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based implementation of <see cref="IApplicationCommandOptionChoice"/>.
/// </summary>
public class RestApplicationCommandChoice : IApplicationCommandOptionChoice
{
/// <inheritdoc/>
public string Name { get; }

/// <inheritdoc/>
public object Value { get; }

internal RestApplicationCommandChoice(Model model)


+ 14
- 0
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandOption.cs View File

@@ -8,20 +8,34 @@ using Model = Discord.API.ApplicationCommandOption;

namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based implementation of <see cref="IApplicationCommandOption"/>.
/// </summary>
public class RestApplicationCommandOption : IApplicationCommandOption
{
/// <inheritdoc/>
public ApplicationCommandOptionType Type { get; private set; }

/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public string Description { get; private set; }

/// <inheritdoc/>
public bool? Default { get; private set; }

/// <inheritdoc/>
public bool? Required { get; private set; }

/// <summary>
/// A collection of <see cref="RestApplicationCommandChoice"/>'s for this command.
/// </summary>
public IReadOnlyCollection<RestApplicationCommandChoice> Choices { get; private set; }

/// <summary>
/// A collection of <see cref="RestApplicationCommandOption"/>'s for this command.
/// </summary>
public IReadOnlyCollection<RestApplicationCommandOption> Options { get; private set; }

internal RestApplicationCommandOption() { }


+ 10
- 0
src/Discord.Net.Rest/Entities/Interactions/RestApplicationCommandType.cs View File

@@ -6,9 +6,19 @@ using System.Threading.Tasks;

namespace Discord.Rest
{
/// <summary>
/// Represents a type of Rest-based command.
/// </summary>
public enum RestApplicationCommandType
{
/// <summary>
/// Specifies that this command is a Global command.
/// </summary>
GlobalCommand,

/// <summary>
/// Specifies that this command is a Guild specific command.
/// </summary>
GuildCommand
}
}

+ 4
- 2
src/Discord.Net.Rest/Entities/Interactions/RestGlobalCommand.cs View File

@@ -8,7 +8,7 @@ using Model = Discord.API.ApplicationCommand;
namespace Discord.Rest
{
/// <summary>
/// Represents a global Slash command
/// Represents a global Slash command.
/// </summary>
public class RestGlobalCommand : RestApplicationCommand
{
@@ -24,6 +24,8 @@ namespace Discord.Rest
entity.Update(model);
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGlobalCommand(Discord, this).ConfigureAwait(false);

@@ -33,7 +35,7 @@ namespace Discord.Rest
/// <param name="func">The delegate containing the properties to modify the command with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// The modified command
/// The modified command.
/// </returns>
public async Task<RestGlobalCommand> ModifyAsync(Action<ApplicationCommandProperties> func, RequestOptions options = null)
=> await InteractionHelper.ModifyGlobalCommand(Discord, this, func, options).ConfigureAwait(false);


+ 8
- 0
src/Discord.Net.Rest/Entities/Interactions/RestGuildCommand.cs View File

@@ -7,9 +7,16 @@ using Model = Discord.API.ApplicationCommand;

namespace Discord.Rest
{
/// <summary>
/// Represents a Rest-based guild command.
/// </summary>
public class RestGuildCommand : RestApplicationCommand
{
/// <summary>
/// The guild Id where this command originates.
/// </summary>
public ulong GuildId { get; set; }

internal RestGuildCommand(BaseDiscordClient client, ulong id, ulong guildId)
: base(client, id)
{
@@ -24,6 +31,7 @@ namespace Discord.Rest
return entity;
}

/// <inheritdoc/>
public override async Task DeleteAsync(RequestOptions options = null)
=> await InteractionHelper.DeleteGuildCommand(Discord, this).ConfigureAwait(false);



+ 12
- 0
src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommand.cs View File

@@ -8,19 +8,31 @@ using Model = Discord.API.Gateway.ApplicationCommandCreatedUpdatedEvent;

namespace Discord.WebSocket
{
/// <summary>
/// Represends a Websocket-based <see cref="IApplicationCommand"/> recieved over the gateway.
/// </summary>
public class SocketApplicationCommand : SocketEntity<ulong>, IApplicationCommand
{
/// <inheritdoc/>
public ulong ApplicationId { get; private set; }

/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public string Description { get; private set; }

/// <summary>
/// A collection of <see cref="SocketApplicationCommandOption"/>'s recieved over the gateway.
/// </summary>
public IReadOnlyCollection<SocketApplicationCommandOption> Options { get; private set; }

public DateTimeOffset CreatedAt
=> SnowflakeUtils.FromSnowflake(this.Id);

/// <summary>
/// The <see cref="SocketGuild"/> where this application was created.
/// </summary>
public SocketGuild Guild
=> Discord.GetGuild(this.GuildId);
private ulong GuildId { get; set; }


+ 3
- 1
src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommandChoice.cs View File

@@ -8,12 +8,14 @@ using Model = Discord.API.ApplicationCommandOptionChoice;
namespace Discord.WebSocket
{
/// <summary>
/// Represents a choice for a <see cref="SocketApplicationCommandOption"/>
/// Represents a choice for a <see cref="SocketApplicationCommandOption"/>.
/// </summary>
public class SocketApplicationCommandChoice : IApplicationCommandOptionChoice
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public object Value { get; private set; }

internal SocketApplicationCommandChoice() { }


+ 6
- 1
src/Discord.Net.WebSocket/Entities/Interaction/SocketApplicationCommandOption.cs View File

@@ -9,18 +9,23 @@ using Model = Discord.API.ApplicationCommandOption;
namespace Discord.WebSocket
{
/// <summary>
/// Represents an option for a <see cref="SocketApplicationCommand"/>
/// Represents an option for a <see cref="SocketApplicationCommand"/>.
/// </summary>
public class SocketApplicationCommandOption : IApplicationCommandOption
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <inheritdoc/>
public ApplicationCommandOptionType Type { get; private set; }

/// <inheritdoc/>
public string Description { get; private set; }

/// <inheritdoc/>
public bool? Default { get; private set; }

/// <inheritdoc/>
public bool? Required { get; private set; }

/// <summary>


+ 27
- 27
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs View File

@@ -9,52 +9,52 @@ using Model = Discord.API.Gateway.InteractionCreated;
namespace Discord.WebSocket
{
/// <summary>
/// Represents an Interaction recieved over the gateway
/// Represents an Interaction recieved over the gateway.
/// </summary>
public class SocketInteraction : SocketEntity<ulong>, IDiscordInteraction
{
/// <summary>
/// The <see cref="SocketGuild"/> this interaction was used in
/// The <see cref="SocketGuild"/> this interaction was used in.
/// </summary>
public SocketGuild Guild
=> Discord.GetGuild(GuildId);

/// <summary>
/// The <see cref="SocketTextChannel"/> this interaction was used in
/// The <see cref="SocketTextChannel"/> this interaction was used in.
/// </summary>
public SocketTextChannel Channel
=> Guild.GetTextChannel(ChannelId);

/// <summary>
/// The <see cref="SocketGuildUser"/> who triggered this interaction
/// The <see cref="SocketGuildUser"/> who triggered this interaction.
/// </summary>
public SocketGuildUser Member
=> Guild.GetUser(MemberId);

/// <summary>
/// The type of this interaction
/// The type of this interaction.
/// </summary>
public InteractionType Type { get; private set; }

/// <summary>
/// The data associated with this interaction
/// The data associated with this interaction.
/// </summary>
public SocketInteractionData Data { get; private set; }

/// <summary>
/// The token used to respond to this interaction
/// The token used to respond to this interaction.
/// </summary>
public string Token { get; private set; }

/// <summary>
/// The version of this interaction
/// The version of this interaction.
/// </summary>
public int Version { get; private set; }

public DateTimeOffset CreatedAt { get; }

/// <summary>
/// <see langword="true"/> if the token is valid for replying to, otherwise <see langword="false"/>
/// <see langword="true"/> if the token is valid for replying to, otherwise <see langword="false"/>.
/// </summary>
public bool IsValidToken
=> CheckToken();
@@ -78,7 +78,7 @@ namespace Discord.WebSocket
internal void Update(Model model)
{
this.Data = model.Data.IsSpecified
? SocketInteractionData.Create(this.Discord, model.Data.Value)
? SocketInteractionData.Create(this.Discord, model.Data.Value, model.GuildId)
: null;

this.GuildId = model.GuildId;
@@ -101,17 +101,17 @@ namespace Discord.WebSocket
/// <see cref="FollowupAsync(string, bool, Embed, InteractionResponseType, AllowedMentions, RequestOptions)"/> instead.
/// </para>
/// </summary>
/// <param name="text">The text of the message to be sent</param>
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/></param>
/// <param name="embed">A <see cref="Embed"/> to send with this response</param>
/// <param name="Type">The type of response to this Interaction</param>
/// <param name="allowedMentions">The allowed mentions for this response</param>
/// <param name="options">The request options for this response</param>
/// <param name="text">The text of the message to be sent.</param>
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param>
/// <param name="embed">A <see cref="Embed"/> to send with this response.</param>
/// <param name="Type">The type of response to this Interaction.</param>
/// <param name="allowedMentions">The allowed mentions for this response.</param>
/// <param name="options">The request options for this response.</param>
/// <returns>
/// The <see cref="IMessage"/> sent as the response. If this is the first acknowledgement, it will return null;
/// The <see cref="IMessage"/> sent as the response. If this is the first acknowledgement, it will return null.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid</exception>
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception>

public async Task<IMessage> RespondAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType Type = InteractionResponseType.ChannelMessageWithSource, AllowedMentions allowedMentions = null, RequestOptions options = null)
{
@@ -162,16 +162,16 @@ namespace Discord.WebSocket
}

/// <summary>
/// Sends a followup message for this interaction
/// Sends a followup message for this interaction.
/// </summary>
/// <param name="text">The text of the message to be sent</param>
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/></param>
/// <param name="embed">A <see cref="Embed"/> to send with this response</param>
/// <param name="Type">The type of response to this Interaction</param>
/// <param name="allowedMentions">The allowed mentions for this response</param>
/// <param name="options">The request options for this response</param>
/// <param name="isTTS"><see langword="true"/> if the message should be read out by a text-to-speech reader, otherwise <see langword="false"/>.</param>
/// <param name="embed">A <see cref="Embed"/> to send with this response.</param>
/// <param name="Type">The type of response to this Interaction.</param>
/// <param name="allowedMentions">The allowed mentions for this response.</param>
/// <param name="options">The request options for this response.</param>
/// <returns>
/// The sent message
/// The sent message.
/// </returns>
public async Task<IMessage> FollowupAsync(string text = null, bool isTTS = false, Embed embed = null, InteractionResponseType Type = InteractionResponseType.ChannelMessageWithSource,
AllowedMentions allowedMentions = null, RequestOptions options = null)
@@ -195,10 +195,10 @@ namespace Discord.WebSocket
}

/// <summary>
/// Acknowledges this interaction with the <see cref="InteractionResponseType.ACKWithSource"/>
/// Acknowledges this interaction with the <see cref="InteractionResponseType.ACKWithSource"/>.
/// </summary>
/// <returns>
/// A task that represents the asynchronous operation of acknowledging the interaction
/// A task that represents the asynchronous operation of acknowledging the interaction.
/// </returns>
public async Task AcknowledgeAsync(RequestOptions options = null)
{


+ 13
- 5
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteractionData.cs View File

@@ -10,28 +10,36 @@ namespace Discord.WebSocket
{
public class SocketInteractionData : SocketEntity<ulong>, IApplicationCommandInteractionData
{
/// <inheritdoc/>
public string Name { get; private set; }

/// <summary>
/// The <see cref="SocketInteractionDataOption"/>'s recieved with this interaction.
/// </summary>
public IReadOnlyCollection<SocketInteractionDataOption> Options { get; private set; }

private ulong guildId;

internal SocketInteractionData(DiscordSocketClient client, ulong id)
: base(client, id)
{

}

internal static SocketInteractionData Create(DiscordSocketClient client, Model model)
internal static SocketInteractionData Create(DiscordSocketClient client, Model model, ulong guildId)
{
var entity = new SocketInteractionData(client, model.Id);
entity.Update(model);
entity.Update(model, guildId);
return entity;
}
internal void Update(Model model)
internal void Update(Model model, ulong guildId)
{
this.Name = model.Name;
this.guildId = guildId;

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => new SocketInteractionDataOption(x)).ToImmutableArray()
? model.Options.Value.Select(x => new SocketInteractionDataOption(x, this.Discord, guildId)).ToImmutableArray()
: null;

}

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionData.Options => Options;


+ 74
- 4
src/Discord.Net.WebSocket/Entities/Interaction/SocketInteractionDataOption.cs View File

@@ -8,21 +8,91 @@ using Model = Discord.API.ApplicationCommandInteractionDataOption;

namespace Discord.WebSocket
{
/// <summary>
/// Represents a Websocket-based <see cref="IApplicationCommandInteractionDataOption"/> recieved by the gateway
/// </summary>
public class SocketInteractionDataOption : IApplicationCommandInteractionDataOption
{
/// <inheritdoc/>
public string Name { get; private set; }
public object? Value { get; private set; }

public IReadOnlyCollection<IApplicationCommandInteractionDataOption> Options { get; private set; }
/// <inheritdoc/>
public object Value { get; private set; }

internal SocketInteractionDataOption(Model model)
/// <summary>
/// The sub command options recieved for this sub command group.
/// </summary>
public IReadOnlyCollection<SocketInteractionDataOption> Options { get; private set; }

private DiscordSocketClient discord;
private ulong guild;

internal SocketInteractionDataOption() { }
internal SocketInteractionDataOption(Model model, DiscordSocketClient discord, ulong guild)
{
this.Name = Name;
this.Value = model.Value.IsSpecified ? model.Value.Value : null;
this.discord = discord;
this.guild = guild;

this.Options = model.Options.IsSpecified
? model.Options.Value.Select(x => new SocketInteractionDataOption(x)).ToImmutableArray()
? model.Options.Value.Select(x => new SocketInteractionDataOption(x, discord, guild)).ToImmutableArray()
: null;
}

// Converters
public static explicit operator bool(SocketInteractionDataOption option)
=> (bool)option.Value;
public static explicit operator int(SocketInteractionDataOption option)
=> (int)option.Value;
public static explicit operator string(SocketInteractionDataOption option)
=> option.Value.ToString();

public static explicit operator SocketGuildChannel(SocketInteractionDataOption option)
{
if (option.Value is ulong id)
{
var guild = option.discord.GetGuild(option.guild);

if (guild == null)
return null;

return guild.GetChannel(id);
}

return null;
}

public static explicit operator SocketRole(SocketInteractionDataOption option)
{
if (option.Value is ulong id)
{
var guild = option.discord.GetGuild(option.guild);

if (guild == null)
return null;

return guild.GetRole(id);
}

return null;
}

public static explicit operator SocketGuildUser(SocketInteractionDataOption option)
{
if(option.Value is ulong id)
{
var guild = option.discord.GetGuild(option.guild);

if (guild == null)
return null;

return guild.GetUser(id);
}

return null;
}

IReadOnlyCollection<IApplicationCommandInteractionDataOption> IApplicationCommandInteractionDataOption.Options => this.Options;
}
}

Loading…
Cancel
Save