diff --git a/DisCatSharp.ApplicationCommands/Context/BaseContext.cs b/DisCatSharp.ApplicationCommands/Context/BaseContext.cs index a7443f35f..d88cd5163 100644 --- a/DisCatSharp.ApplicationCommands/Context/BaseContext.cs +++ b/DisCatSharp.ApplicationCommands/Context/BaseContext.cs @@ -1,180 +1,180 @@ // This file is part of the DisCatSharp project. // // Copyright (c) 2021 AITSYS // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using System; using System.Threading.Tasks; using DisCatSharp.Entities; using DisCatSharp.Enums; using Microsoft.Extensions.DependencyInjection; namespace DisCatSharp.ApplicationCommands { /// /// Respresents a base context for application command contexts. /// public class BaseContext { /// /// Gets the interaction that was created. /// public DiscordInteraction Interaction { get; internal set; } /// /// Gets the client for this interaction. /// public DiscordClient Client { get; internal set; } /// /// Gets the guild this interaction was executed in. /// public DiscordGuild Guild { get; internal set; } /// /// Gets the channel this interaction was executed in. /// public DiscordChannel Channel { get; internal set; } /// /// Gets the user which executed this interaction. /// public DiscordUser User { get; internal set; } /// /// Gets the member which executed this interaction, or null if the command is in a DM. /// public DiscordMember Member => this.User is DiscordMember member ? member : null; /// /// Gets the application command module this interaction was created in. /// public ApplicationCommandsExtension ApplicationCommandsExtension { get; internal set; } /// /// Gets the token for this interaction. /// public string Token { get; internal set; } /// /// Gets the id for this interaction. /// public ulong InteractionId { get; internal set; } /// /// Gets the name of the command. /// public string CommandName { get; internal set; } /// /// Gets the invoking user locale. /// public string Locale { get; internal set; } /// /// Gets the guild locale if applicable. /// public string GuildLocale { get; internal set; } /// /// Gets the type of this interaction. /// public ApplicationCommandType Type { get; internal set;} /// /// Gets the service provider. /// This allows passing data around without resorting to static members. /// Defaults to null. /// public IServiceProvider Services { get; internal set; } = new ServiceCollection().BuildServiceProvider(true); /// /// Creates a response to this interaction. /// You must create a response within 3 seconds of this interaction being executed; if the command has the potential to take more than 3 seconds, create a at the start, and edit the response later. /// /// The type of the response. /// The data to be sent, if any. /// public Task CreateResponseAsync(InteractionResponseType type, DiscordInteractionResponseBuilder builder = null) => this.Interaction.CreateResponseAsync(type, builder); /// /// Creates a modal response to this interaction. /// /// The data to send. - public Task CreateModalResponseAsync(DiscordInteractionModalBuilder builder) => - this.Interaction.CreateInteractionModalResponseAsync(builder); + public Task CreateModalResponseAsync(DiscordInteractionModalBuilder builder) + => this.Interaction.Type != InteractionType.Ping && this.Interaction.Type != InteractionType.ModalSubmit ? this.Interaction.CreateInteractionModalResponseAsync(builder) : throw new NotSupportedException("You can't respond to an PING with a modal."); /// /// Edits the interaction response. /// /// The data to edit the response with. /// public Task EditResponseAsync(DiscordWebhookBuilder builder) => this.Interaction.EditOriginalResponseAsync(builder); /// /// Deletes the interaction response. /// /// public Task DeleteResponseAsync() => this.Interaction.DeleteOriginalResponseAsync(); /// /// Creates a follow up message to the interaction. /// /// The message to be sent, in the form of a webhook. /// The created message. public Task FollowUpAsync(DiscordFollowupMessageBuilder builder) => this.Interaction.CreateFollowupMessageAsync(builder); /// /// Edits a followup message. /// /// The id of the followup message to edit. /// The webhook builder. /// public Task EditFollowupAsync(ulong followupMessageId, DiscordWebhookBuilder builder) => this.Interaction.EditFollowupMessageAsync(followupMessageId, builder); /// /// Deletes a followup message. /// /// The id of the followup message to delete. /// public Task DeleteFollowupAsync(ulong followupMessageId) => this.Interaction.DeleteFollowupMessageAsync(followupMessageId); /// /// Gets the followup message. /// /// The followup message id. public Task GetFollowupMessageAsync(ulong followupMessageId) => this.Interaction.GetFollowupMessageAsync(followupMessageId); /// /// Gets the original interaction response. /// /// The original interaction response. public Task GetOriginalResponseAsync() => this.Interaction.GetOriginalResponseAsync(); } } diff --git a/DisCatSharp/Entities/Interaction/DiscordInteraction.cs b/DisCatSharp/Entities/Interaction/DiscordInteraction.cs index e26159bc2..3c6f55402 100644 --- a/DisCatSharp/Entities/Interaction/DiscordInteraction.cs +++ b/DisCatSharp/Entities/Interaction/DiscordInteraction.cs @@ -1,218 +1,219 @@ // This file is part of the DisCatSharp project. // // Copyright (c) 2021 AITSYS // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +using System; using System.Threading.Tasks; using Newtonsoft.Json; namespace DisCatSharp.Entities { /// /// Represents an interaction that was invoked. /// public sealed class DiscordInteraction : SnowflakeObject { /// /// Gets the type of interaction invoked. /// [JsonProperty("type")] public InteractionType Type { get; internal set; } /// /// Gets the command data for this interaction. /// [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)] public DiscordInteractionData Data { get; internal set; } /// /// Gets the Id of the guild that invoked this interaction. /// [JsonIgnore] public ulong? GuildId { get; internal set; } /// /// Gets the guild that invoked this interaction. /// [JsonIgnore] public DiscordGuild Guild => (this.Discord as DiscordClient).InternalGetCachedGuild(this.GuildId); /// /// Gets the Id of the channel that invoked this interaction. /// [JsonIgnore] public ulong ChannelId { get; internal set; } /// /// Gets the channel that invoked this interaction. /// [JsonIgnore] public DiscordChannel Channel => (this.Discord as DiscordClient).InternalGetCachedChannel(this.ChannelId) ?? (DiscordChannel)(this.Discord as DiscordClient).InternalGetCachedThread(this.ChannelId) ?? (this.Guild == null ? new DiscordDmChannel { Id = this.ChannelId, Type = ChannelType.Private, Discord = this.Discord } : null); /// /// Gets the user that invoked this interaction. /// This can be cast to a if created in a guild. /// [JsonIgnore] public DiscordUser User { get; internal set; } /// /// Gets the continuation token for responding to this interaction. /// [JsonProperty("token")] public string Token { get; internal set; } /// /// Gets the version number for this interaction type. /// [JsonProperty("version")] public int Version { get; internal set; } /// /// Gets the ID of the application that created this interaction. /// [JsonProperty("application_id")] public ulong ApplicationId { get; internal set; } /// /// The message this interaction was created with, if any. /// [JsonProperty("message")] internal DiscordMessage Message { get; set; } /// /// Gets the invoking user locale. /// [JsonProperty("locale", NullValueHandling = NullValueHandling.Ignore)] public string Locale { get; internal set; } /// /// Gets the guild locale if applicable. /// [JsonProperty("guild_locale", NullValueHandling = NullValueHandling.Ignore)] public string GuildLocale { get; internal set; } /// /// Creates a response to this interaction. /// /// The type of the response. /// The data, if any, to send. - public Task CreateResponseAsync(InteractionResponseType type, DiscordInteractionResponseBuilder builder = null) => - this.Discord.ApiClient.CreateInteractionResponseAsync(this.Id, this.Token, type, builder); + public Task CreateResponseAsync(InteractionResponseType type, DiscordInteractionResponseBuilder builder = null) + => this.Discord.ApiClient.CreateInteractionResponseAsync(this.Id, this.Token, type, builder); /// /// Creates a modal response to this interaction. /// /// The data to send. - public Task CreateInteractionModalResponseAsync(DiscordInteractionModalBuilder builder) => - this.Discord.ApiClient.CreateInteractionModalResponseAsync(this.Id, this.Token, InteractionResponseType.Modal, builder); + public Task CreateInteractionModalResponseAsync(DiscordInteractionModalBuilder builder) + => this.Type != InteractionType.Ping && this.Type != InteractionType.ModalSubmit ? this.Discord.ApiClient.CreateInteractionModalResponseAsync(this.Id, this.Token, InteractionResponseType.Modal, builder) : throw new NotSupportedException("You can't respond to an PING with a modal."); /// /// Gets the original interaction response. /// /// The origingal message that was sent. This does not work on ephemeral messages. - public Task GetOriginalResponseAsync() => - this.Discord.ApiClient.GetOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token); + public Task GetOriginalResponseAsync() + => this.Discord.ApiClient.GetOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token); /// /// Edits the original interaction response. /// /// The webhook builder. /// The edited . public async Task EditOriginalResponseAsync(DiscordWebhookBuilder builder) { builder.Validate(isInteractionResponse: true); if (builder._keepAttachments.HasValue && builder._keepAttachments.Value) { var attachments = this.Discord.ApiClient.GetOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token).Result.Attachments; if (attachments?.Count > 0) { builder._attachments.AddRange(attachments); } } else if (builder._keepAttachments.HasValue) { builder._attachments.Clear(); } return await this.Discord.ApiClient.EditOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token, builder).ConfigureAwait(false); } /// /// Deletes the original interaction response. /// > - public Task DeleteOriginalResponseAsync() => - this.Discord.ApiClient.DeleteOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token); + public Task DeleteOriginalResponseAsync() + => this.Discord.ApiClient.DeleteOriginalInteractionResponseAsync(this.Discord.CurrentApplication.Id, this.Token); /// /// Creates a follow up message to this interaction. /// /// The webhook builder. /// The created . public async Task CreateFollowupMessageAsync(DiscordFollowupMessageBuilder builder) { builder.Validate(); return await this.Discord.ApiClient.CreateFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, builder).ConfigureAwait(false); } /// /// Gets a follow up message. /// /// The id of the follow up message. - public Task GetFollowupMessageAsync(ulong messageId) => - this.Discord.ApiClient.GetFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId); + public Task GetFollowupMessageAsync(ulong messageId) + => this.Discord.ApiClient.GetFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId); /// /// Edits a follow up message. /// /// The id of the follow up message. /// The webhook builder. /// The edited . public async Task EditFollowupMessageAsync(ulong messageId, DiscordWebhookBuilder builder) { builder.Validate(isFollowup: true); if (builder._keepAttachments.HasValue && builder._keepAttachments.Value) { var attachments = this.Discord.ApiClient.GetFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId).Result.Attachments; if (attachments?.Count > 0) { builder._attachments.AddRange(attachments); } } else if (builder._keepAttachments.HasValue) { builder._attachments.Clear(); } return await this.Discord.ApiClient.EditFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId, builder).ConfigureAwait(false); } /// /// Deletes a follow up message. /// /// The id of the follow up message. - public Task DeleteFollowupMessageAsync(ulong messageId) => - this.Discord.ApiClient.DeleteFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId); + public Task DeleteFollowupMessageAsync(ulong messageId) + => this.Discord.ApiClient.DeleteFollowupMessageAsync(this.Discord.CurrentApplication.Id, this.Token, messageId); } }