diff --git a/src/Discord.Net.Core/DiscordConfig.cs b/src/Discord.Net.Core/DiscordConfig.cs index 869d113d..4056484e 100644 --- a/src/Discord.Net.Core/DiscordConfig.cs +++ b/src/Discord.Net.Core/DiscordConfig.cs @@ -257,6 +257,21 @@ namespace Discord /// public const int MaxEntitlementsPerBatch = 100; + /// + /// Returns the maximum number of poll answer voters that can be gotten per-batch. + /// + public const int MaxPollVotersPerBatch = 100; + + /// + /// Returns the maximum length of a poll answer text. + /// + public const int MaxPollAnswerTextLength = 55; + + /// + /// Returns the maximum length of a poll question text. + /// + public const int MaxPollQuestionTextLength = 300; + /// /// Returns the maximum number of bans that can be banned in a single bulk request. /// diff --git a/src/Discord.Net.Core/DiscordErrorCode.cs b/src/Discord.Net.Core/DiscordErrorCode.cs index 37e469f5..33a022ee 100644 --- a/src/Discord.Net.Core/DiscordErrorCode.cs +++ b/src/Discord.Net.Core/DiscordErrorCode.cs @@ -249,7 +249,18 @@ namespace Discord #region Onboarding (350XXX) CannotEnableOnboardingUnmetRequirements = 350000, - CannotUpdateOnboardingBelowRequirements = 350001 + CannotUpdateOnboardingBelowRequirements = 350001, + #endregion + + #region Polls (520XXX) + + PollVotingBlocked = 520000, + PollExpired = 520001, + InvalidChannelTypeForPollCreation = 520002, + CannotEditAPollMessage = 520003, + CannotUseAnEmojiIncludedWithThePoll = 520004, + CannotExpireANonPollMessage = 520006, + #endregion } } diff --git a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs index 6e5d23f1..b381cbc4 100644 --- a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs @@ -33,11 +33,15 @@ namespace Discord /// A array of s to send with this response. Max 10. /// A message flag to be applied to the sent message, only /// and is permitted. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, + AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); + /// /// Sends a file to this message channel with an optional caption. /// @@ -74,11 +78,15 @@ namespace Discord /// A collection of stickers to send with the file. /// A array of s to send with this response. Max 10. /// A message flag to be applied to the sent message, only and is permitted. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, + bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, + ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); + /// /// Sends a file to this message channel with an optional caption. /// @@ -112,11 +120,15 @@ namespace Discord /// A collection of stickers to send with the file. /// A array of s to send with this response. Max 10. /// A message flag to be applied to the sent message, only and is permitted. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, + bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, + ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); + /// /// Sends a file to this message channel with an optional caption. /// @@ -142,11 +154,14 @@ namespace Discord /// A collection of stickers to send with the file. /// A array of s to send with this response. Max 10. /// A message flag to be applied to the sent message, only and is permitted. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, + AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); /// /// Sends a collection of files to this message channel. /// @@ -172,11 +187,14 @@ namespace Discord /// A collection of stickers to send with the file. /// A array of s to send with this response. Max 10. /// A message flag to be applied to the sent message, only and is permitted. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, + RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, + ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); /// /// Gets a message from this message channel. diff --git a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs index 73b7db9f..5b04de59 100644 --- a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs +++ b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs @@ -122,11 +122,12 @@ namespace Discord /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. /// - Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, - bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, + MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Responds to this interaction with a file attachment. @@ -141,13 +142,14 @@ namespace Discord /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { @@ -156,7 +158,7 @@ namespace Discord } #else Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a file attachment. @@ -171,13 +173,14 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER async Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { @@ -186,7 +189,7 @@ namespace Discord } #else Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a file attachment. @@ -200,17 +203,18 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); #else Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Responds to this interaction with a collection of file attachments. @@ -224,12 +228,13 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. /// @@ -241,12 +246,13 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. /// @@ -260,22 +266,23 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER async Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } #else Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Sends a followup message for this interaction. @@ -290,22 +297,23 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER async Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } #else Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Sends a followup message for this interaction. @@ -319,17 +327,18 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// #if NETCOREAPP3_0_OR_GREATER Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); #else Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); #endif /// /// Sends a followup message for this interaction. @@ -343,12 +352,13 @@ namespace Discord /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Gets the original response for this interaction. /// diff --git a/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs b/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs index 757c3e4a..6bd764f9 100644 --- a/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs +++ b/src/Discord.Net.Core/Entities/Messages/IUserMessage.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Discord @@ -29,6 +30,14 @@ namespace Discord /// IMessageInteractionMetadata InteractionMetadata { get; } + /// + /// Gets the poll sent with this message. + /// + /// + /// Will be if the message has no poll. + /// + Poll? Poll { get; } + /// /// Modifies this message. /// @@ -94,5 +103,23 @@ namespace Discord TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name); + + /// + /// Immediately ends the poll. + /// + /// + /// You cannot end polls from other users. + /// + /// The options to be used when sending the request. + Task EndPollAsync(RequestOptions options); + + /// + /// Get users that voted for this specific answer. + /// + /// The id on the answer to fetch voters for + /// The options to be used when sending the request. + /// The id of a user to start after. + /// The number of users to request. + IAsyncEnumerable> GetPollAnswerVotersAsync(uint answerId, int? limit = null, ulong? afterId = null, RequestOptions options = null); } } diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/Poll.cs b/src/Discord.Net.Core/Entities/Messages/Polls/Poll.cs new file mode 100644 index 00000000..687eb2b7 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/Poll.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; + +namespace Discord; + +/// +/// Represents a poll object. +/// +public readonly struct Poll +{ + /// + /// Gets the question for the poll. + /// + public readonly PollMedia Question; + + /// + /// Gets the answers for the poll. + /// + public readonly IReadOnlyCollection Answers; + + /// + /// Gets the expiration date for the poll. + /// + public readonly DateTimeOffset ExpiresAt; + + /// + /// Gets whether the poll allows multiple answers. + /// + public readonly bool AllowMultiselect; + + /// + /// Gets the layout type for the poll. + /// + public readonly PollLayout LayoutType; + + /// + /// Gets the results of the poll. This is if the poll is not finalized. + /// + public readonly PollResults? Results; + + internal Poll(PollMedia question, IReadOnlyCollection answers, DateTimeOffset expiresAt, bool allowMultiselect, PollLayout layoutType, PollResults? results) + { + Question = question; + Answers = answers; + ExpiresAt = expiresAt; + AllowMultiselect = allowMultiselect; + LayoutType = layoutType; + Results = results; + } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswer.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswer.cs new file mode 100644 index 00000000..88fec662 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswer.cs @@ -0,0 +1,23 @@ +namespace Discord; + +/// +/// Represents a poll answer object. +/// +public readonly struct PollAnswer +{ + /// + /// Gets the Id of the answer. + /// + public readonly uint AnswerId; + + /// + /// Gets the poll media of this answer. + /// + public readonly PollMedia PollMedia; + + internal PollAnswer(uint id, PollMedia media) + { + AnswerId = id; + PollMedia = media; + } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswerCounts.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswerCounts.cs new file mode 100644 index 00000000..1458870c --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollAnswerCounts.cs @@ -0,0 +1,29 @@ +namespace Discord; + +/// +/// Represents a poll answer counts object. +/// +public readonly struct PollAnswerCounts +{ + /// + /// Gets the Id of the answer. + /// + public readonly ulong AnswerId; + + /// + /// Gets the count of votes for this answer. + /// + public readonly uint Count; + + /// + /// Gets whether the current user voted for this answer. + /// + public readonly bool MeVoted; + + internal PollAnswerCounts(ulong answerId, uint count, bool meVoted) + { + AnswerId = answerId; + Count = count; + MeVoted = meVoted; + } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollLayout.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollLayout.cs new file mode 100644 index 00000000..47f9b18a --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollLayout.cs @@ -0,0 +1,6 @@ +namespace Discord; + +public enum PollLayout +{ + Default = 1 +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollMedia.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollMedia.cs new file mode 100644 index 00000000..c29c779c --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollMedia.cs @@ -0,0 +1,23 @@ +namespace Discord; + +/// +/// Represents a poll media object. +/// +public readonly struct PollMedia +{ + /// + /// Gets the text of the field. + /// + public readonly string Text; + + /// + /// Gets the emoji of the field. if no emoji is set. + /// + public readonly IEmote Emoji; + + internal PollMedia(string text, IEmote emoji) + { + Text = text; + Emoji = emoji; + } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollMediaProperties.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollMediaProperties.cs new file mode 100644 index 00000000..3f682ce4 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollMediaProperties.cs @@ -0,0 +1,17 @@ +namespace Discord; + +/// +/// Properties used to create a poll question. +/// +public class PollMediaProperties +{ + /// + /// Gets or sets the text of the question for the poll. + /// + public string Text { get; set; } + + /// + /// Gets or sets the emoji of the question for the poll. + /// + public IEmote Emoji { get; set; } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollProperties.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollProperties.cs new file mode 100644 index 00000000..dae36a5b --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollProperties.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace Discord; + +/// +/// Properties used to create a poll. +/// +public class PollProperties +{ + /// + /// Gets or sets the question for the poll. + /// + public PollMediaProperties Question { get; set; } + + /// + /// Gets or sets the answers for the poll. + /// + public List Answers { get; set; } + + /// + /// Gets or sets the duration for the poll in hours. Max duration is 168 hours (7 days). + /// + public uint Duration { get; set; } + + /// + /// Gets or sets whether the poll allows multiple answers. + /// + public bool AllowMultiselect { get; set; } + + /// + /// Gets or sets the layout type for the poll. + /// + public PollLayout LayoutType { get; set; } +} diff --git a/src/Discord.Net.Core/Entities/Messages/Polls/PollResults.cs b/src/Discord.Net.Core/Entities/Messages/Polls/PollResults.cs new file mode 100644 index 00000000..ed1873e4 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Polls/PollResults.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace Discord; + +/// +/// Represents the results of a poll. +/// +public readonly struct PollResults +{ + /// + /// Gets whether the poll results are finalized. + /// + public readonly bool IsFinalized; + + /// + /// Gets the answer counts for the poll. + /// + public readonly IReadOnlyCollection AnswerCounts; + + internal PollResults(bool isFinalized, IReadOnlyCollection answerCounts) + { + IsFinalized = isFinalized; + AnswerCounts = answerCounts; + } +} diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs index 72b49170..22a71a9b 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs @@ -192,5 +192,10 @@ namespace Discord /// Allows setting voice channel status. /// SetVoiceChannelStatus = 1L << 48, + + /// + /// Allows sending polls. + /// + SendPolls = 1L << 49, } } diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index 4b527e34..879c79eb 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -18,17 +18,17 @@ namespace Discord /// /// Gets a that grants all permissions for text channels. /// - public static readonly ChannelPermissions Text = new(0b110001_001111_110010_110011_111101_111111_111101_010001); + public static readonly ChannelPermissions Text = new(0b10_110001_001111_110010_110011_111101_111111_111101_010001); /// /// Gets a that grants all permissions for voice channels. /// - public static readonly ChannelPermissions Voice = new(0b1_110001_001010_001010_110011_111101_111111_111101_010001); + public static readonly ChannelPermissions Voice = new(0b11_110001_001010_001010_110011_111101_111111_111101_010001); /// /// Gets a that grants all permissions for stage channels. /// - public static readonly ChannelPermissions Stage = new(0b110000_000010_001110_010001_010101_111111_111001_010001); + public static readonly ChannelPermissions Stage = new(0b10_110000_000010_001110_010001_010101_111111_111001_010001); /// /// Gets a that grants all permissions for category channels. @@ -151,7 +151,9 @@ namespace Discord /// If , a user can use the Clyde AI bot in this channel. public bool UseClydeAI => Permissions.GetValue(RawValue, ChannelPermission.UseClydeAI); /// If , a user can set the status of a voice channel. - public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus); + public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, ChannelPermission.SetVoiceChannelStatus); + /// If , a user can send polls. + public bool SendPolls => Permissions.GetValue(RawValue, ChannelPermission.SendPolls); /// Creates a new with the provided packed value. public ChannelPermissions(ulong rawValue) { RawValue = rawValue; } @@ -191,7 +193,8 @@ namespace Discord bool? createEvents = null, bool? sendVoiceMessages = null, bool? useClydeAI = null, - bool? setVoiceChannelStatus = null) + bool? setVoiceChannelStatus = null, + bool? sendPolls = null) { ulong value = initialValue; @@ -230,6 +233,7 @@ namespace Discord Permissions.SetValue(ref value, sendVoiceMessages, ChannelPermission.SendVoiceMessages); Permissions.SetValue(ref value, useClydeAI, ChannelPermission.UseClydeAI); Permissions.SetValue(ref value, setVoiceChannelStatus, ChannelPermission.SetVoiceChannelStatus); + Permissions.SetValue(ref value, sendPolls, ChannelPermission.SendPolls); RawValue = value; } @@ -270,12 +274,13 @@ namespace Discord bool createEvents = false, bool sendVoiceMessages = false, bool useClydeAI = false, - bool setVoiceChannelStatus = false) + bool setVoiceChannelStatus = false, + bool sendPolls = false) : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, stream, manageRoles, manageWebhooks, useApplicationCommands, requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads, - startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages, useClydeAI, setVoiceChannelStatus) + startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages, useClydeAI, setVoiceChannelStatus, sendPolls) { } /// Creates a new from this one, changing the provided non-null permissions. @@ -314,7 +319,8 @@ namespace Discord bool? createEvents = null, bool? sendVoiceMessages = null, bool? useClydeAI = null, - bool? setVoiceChannelStatus = null) + bool? setVoiceChannelStatus = null, + bool? sendPolls = null) => new ChannelPermissions(RawValue, createInstantInvite, manageChannel, @@ -350,7 +356,8 @@ namespace Discord createEvents, sendVoiceMessages, useClydeAI, - setVoiceChannelStatus); + setVoiceChannelStatus, + sendPolls); public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs index 978161d7..79b3a4f9 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs @@ -282,5 +282,10 @@ namespace Discord /// Allows setting voice channel status. /// SetVoiceChannelStatus = 1L << 48, + + /// + /// Allows sending polls. + /// + SendPolls = 1L << 49, } } diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs index 90e41dd2..2ef5dcf7 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs @@ -116,6 +116,9 @@ namespace Discord public bool CreateGuildExpressions => Permissions.GetValue(RawValue, GuildPermission.CreateGuildExpressions); /// If , a user can set the status of a voice channel. public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus); + /// If , a user can send polls. + public bool SendPolls => Permissions.GetValue(RawValue, GuildPermission.SendPolls); + /// Creates a new with the provided packed value. public GuildPermissions(ulong rawValue) { RawValue = rawValue; } @@ -170,7 +173,8 @@ namespace Discord bool? sendVoiceMessages = null, bool? useClydeAI = null, bool? createGuildExpressions = null, - bool? setVoiceChannelStatus = null) + bool? setVoiceChannelStatus = null, + bool? sendPolls = null) { ulong value = initialValue; @@ -221,6 +225,7 @@ namespace Discord Permissions.SetValue(ref value, useClydeAI, GuildPermission.UseClydeAI); Permissions.SetValue(ref value, createGuildExpressions, GuildPermission.CreateGuildExpressions); Permissions.SetValue(ref value, setVoiceChannelStatus, GuildPermission.SetVoiceChannelStatus); + Permissions.SetValue(ref value, sendPolls, GuildPermission.SendPolls); RawValue = value; } @@ -273,7 +278,8 @@ namespace Discord bool sendVoiceMessages = false, bool useClydeAI = false, bool createGuildExpressions = false, - bool setVoiceChannelStatus = false) + bool setVoiceChannelStatus = false, + bool sendPolls = false) : this(0, createInstantInvite: createInstantInvite, manageRoles: manageRoles, @@ -321,7 +327,8 @@ namespace Discord sendVoiceMessages: sendVoiceMessages, useClydeAI: useClydeAI, createGuildExpressions: createGuildExpressions, - setVoiceChannelStatus: setVoiceChannelStatus) + setVoiceChannelStatus: setVoiceChannelStatus, + sendPolls: sendPolls) { } /// Creates a new from this one, changing the provided non-null permissions. @@ -372,13 +379,15 @@ namespace Discord bool? sendVoiceMessages = null, bool? useClydeAI = null, bool? createGuildExpressions = null, - bool? setVoiceChannelStatus = null) + bool? setVoiceChannelStatus = null, + bool? sendPolls = null) => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, viewAuditLog, viewGuildInsights, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojisAndStickers, useApplicationCommands, requestToSpeak, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads, - startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages, useClydeAI, createGuildExpressions, setVoiceChannelStatus); + startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages, useClydeAI, createGuildExpressions, setVoiceChannelStatus, + sendPolls); /// /// Returns a value that indicates if a specific is enabled diff --git a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs index 7e17c7cb..cc69686c 100644 --- a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs +++ b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs @@ -121,7 +121,7 @@ namespace Discord /// /// /// The following example checks if the current user has the ability to send a message with attachment in - /// this channel; if so, uploads a file via . + /// this channel; if so, uploads a file via . /// /// if (currentUser?.GetPermissions(targetChannel)?.AttachFiles) /// await targetChannel.SendFileAsync("fortnite.png"); diff --git a/src/Discord.Net.Core/GatewayIntents.cs b/src/Discord.Net.Core/GatewayIntents.cs index b7979afa..a4909fbf 100644 --- a/src/Discord.Net.Core/GatewayIntents.cs +++ b/src/Discord.Net.Core/GatewayIntents.cs @@ -59,6 +59,16 @@ namespace Discord /// AutoModerationActionExecution = 1 << 21, + /// + /// This intent includes MESSAGE_POLL_VOTE_ADD and MESSAGE_POLL_VOTE_REMOVE + /// + GuildMessagePolls = 1 << 24, + + /// + /// This intent includes MESSAGE_POLL_VOTE_ADD and MESSAGE_POLL_VOTE_REMOVE + /// + DirectMessagePolls = 1 << 25, + /// /// This intent includes all but , and /// which are privileged and must be enabled in the Developer Portal. @@ -66,7 +76,7 @@ namespace Discord AllUnprivileged = Guilds | GuildBans | GuildEmojis | GuildIntegrations | GuildWebhooks | GuildInvites | GuildVoiceStates | GuildMessages | GuildMessageReactions | GuildMessageTyping | DirectMessages | DirectMessageReactions | DirectMessageTyping | GuildScheduledEvents | AutoModerationConfiguration | - AutoModerationActionExecution, + AutoModerationActionExecution | GuildMessagePolls | DirectMessagePolls, /// /// This intent includes all of them, including privileged ones. /// diff --git a/src/Discord.Net.Core/Utils/Preconditions.cs b/src/Discord.Net.Core/Utils/Preconditions.cs index c3f2785d..2d3fa16f 100644 --- a/src/Discord.Net.Core/Utils/Preconditions.cs +++ b/src/Discord.Net.Core/Utils/Preconditions.cs @@ -77,7 +77,7 @@ namespace Discord #region Message Validation public static void WebhookMessageAtLeastOneOf(string text = null, MessageComponent components = null, ICollection embeds = null, - IEnumerable attachments = null) + IEnumerable attachments = null, PollProperties poll = null) { if (!string.IsNullOrEmpty(text)) return; @@ -91,11 +91,14 @@ namespace Discord if (embeds != null && embeds.Count != 0) return; - throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components' or 'Attachments' must be specified."); + if (poll is not null) + return; + + throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components', 'Attachments' or 'Poll' must be specified."); } public static void MessageAtLeastOneOf(string text = null, MessageComponent components = null, ICollection embeds = null, - ICollection stickers = null, IEnumerable attachments = null) + ICollection stickers = null, IEnumerable attachments = null, PollProperties poll = null) { if (!string.IsNullOrEmpty(text)) return; @@ -112,7 +115,31 @@ namespace Discord if (embeds != null && embeds.Count != 0) return; - throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components', 'Stickers' or 'Attachments' must be specified."); + if (poll is not null) + return; + + throw new ArgumentException($"At least one of 'Content', 'Embeds', 'Components', 'Stickers', 'Attachments' or 'Poll' must be specified."); + } + + public static void ValidatePoll(PollProperties poll) + { + if (poll is null) + return; + + if (poll.Answers.Count is < 1 or > 10) + throw new ArgumentOutOfRangeException(nameof(poll.Answers), "Poll answers must be between 1 and 10."); + if (poll.Answers.Any(x => x.Text.Length > DiscordConfig.MaxPollAnswerTextLength)) + throw new ArgumentOutOfRangeException(nameof(poll.Answers), $"Poll answer text must be less than or equal to {DiscordConfig.MaxPollAnswerTextLength} characters."); + if (poll.Answers.All(x => string.IsNullOrWhiteSpace(x.Text) && x.Emoji is null)) + throw new ArgumentException("Poll answers must have at least one of text or emoji.", nameof(poll.Answers)); + if (poll.Question is null) + throw new ArgumentNullException(nameof(poll.Question), "Poll question must not be null."); + if (poll.Question.Text.Length > DiscordConfig.MaxPollQuestionTextLength) + throw new ArgumentOutOfRangeException(nameof(poll.Question), $"Poll question text must be less than or equal to {DiscordConfig.MaxPollQuestionTextLength} characters."); + if (string.IsNullOrWhiteSpace(poll.Question.Text) && poll.Question.Emoji is null) + throw new ArgumentException("Poll question must have at least one of text or emoji.", nameof(poll.Question)); + if (poll.Duration is > 168 or 0) + throw new ArgumentOutOfRangeException(nameof(poll.Duration), "Poll duration must be between 1 and 168 hours."); } #endregion diff --git a/src/Discord.Net.Interactions/InteractionModuleBase.cs b/src/Discord.Net.Interactions/InteractionModuleBase.cs index a5e56e98..eb560db4 100644 --- a/src/Discord.Net.Interactions/InteractionModuleBase.cs +++ b/src/Discord.Net.Interactions/InteractionModuleBase.cs @@ -44,61 +44,61 @@ namespace Discord.Interactions protected virtual Task DeferAsync(bool ephemeral = false, RequestOptions options = null) => Context.Interaction.DeferAsync(ephemeral, options); - /// + /// protected virtual Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null) - => Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null) - => Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => Context.Interaction.FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); - /// + /// protected virtual Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); - /// + /// protected virtual Task ReplyAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) - => Context.Channel.SendMessageAsync(text, false, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags); + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) + => Context.Channel.SendMessageAsync(text, false, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll); /// protected virtual Task GetOriginalResponseAsync(RequestOptions options = null) diff --git a/src/Discord.Net.Interactions/RestInteractionModuleBase.cs b/src/Discord.Net.Interactions/RestInteractionModuleBase.cs index 26e527f6..1778b7ef 100644 --- a/src/Discord.Net.Interactions/RestInteractionModuleBase.cs +++ b/src/Discord.Net.Interactions/RestInteractionModuleBase.cs @@ -43,8 +43,8 @@ namespace Discord.Interactions /// A Task representing the operation of creating the interaction response. /// /// Thrown if the interaction isn't a type of . - protected override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null) - => HandleInteractionAsync(x => x.Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options)); + protected override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null) + => HandleInteractionAsync(x => x.Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll)); /// /// Responds to the interaction with a modal. diff --git a/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs b/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs index 132e38e5..c64920e3 100644 --- a/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs +++ b/src/Discord.Net.Rest/API/Common/ForumThreadMessage.cs @@ -1,33 +1,30 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Discord.API +namespace Discord.API.Rest; + +internal class ForumThreadMessage { - internal class ForumThreadMessage - { - [JsonProperty("content")] - public Optional Content { get; set; } + [JsonProperty("content")] + public Optional Content { get; set; } - [JsonProperty("nonce")] - public Optional Nonce { get; set; } + [JsonProperty("nonce")] + public Optional Nonce { get; set; } - [JsonProperty("embeds")] - public Optional Embeds { get; set; } + [JsonProperty("embeds")] + public Optional Embeds { get; set; } - [JsonProperty("allowed_mentions")] - public Optional AllowedMentions { get; set; } + [JsonProperty("allowed_mentions")] + public Optional AllowedMentions { get; set; } - [JsonProperty("components")] - public Optional Components { get; set; } + [JsonProperty("components")] + public Optional Components { get; set; } - [JsonProperty("sticker_ids")] - public Optional Stickers { get; set; } + [JsonProperty("sticker_ids")] + public Optional Stickers { get; set; } - [JsonProperty("flags")] - public Optional Flags { get; set; } - } + [JsonProperty("flags")] + public Optional Flags { get; set; } + + [JsonProperty("poll")] + public Optional Poll { get; set; } } diff --git a/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs b/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs index 3685d7a9..0b3302dd 100644 --- a/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs +++ b/src/Discord.Net.Rest/API/Common/InteractionCallbackData.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Newtonsoft.Json; namespace Discord.API @@ -30,5 +31,8 @@ namespace Discord.API [JsonProperty("custom_id")] public Optional CustomId { get; set; } + + [JsonProperty("poll")] + public Optional Poll { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Common/Message.cs b/src/Discord.Net.Rest/API/Common/Message.cs index c9cc61a2..14ec1afe 100644 --- a/src/Discord.Net.Rest/API/Common/Message.cs +++ b/src/Discord.Net.Rest/API/Common/Message.cs @@ -101,4 +101,7 @@ internal class Message [JsonProperty("interaction_metadata")] public Optional InteractionMetadata { get; set; } + + [JsonProperty("poll")] + public Optional Poll { get; set; } } diff --git a/src/Discord.Net.Rest/API/Common/Poll.cs b/src/Discord.Net.Rest/API/Common/Poll.cs new file mode 100644 index 00000000..8f30bab0 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/Poll.cs @@ -0,0 +1,25 @@ +using Newtonsoft.Json; +using System; + +namespace Discord.API; + +internal class Poll +{ + [JsonProperty("question")] + public PollMedia Question { get; set; } + + [JsonProperty("answers")] + public PollAnswer[] Answers { get; set; } + + [JsonProperty("expiry")] + public DateTimeOffset Expiry { get; set; } + + [JsonProperty("allow_multiselect")] + public bool AllowMultiselect { get; set; } + + [JsonProperty("layout_type")] + public PollLayout LayoutType { get; set; } + + [JsonProperty("results")] + public Optional PollResults { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/PollAnswer.cs b/src/Discord.Net.Rest/API/Common/PollAnswer.cs new file mode 100644 index 00000000..2999e5d2 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/PollAnswer.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class PollAnswer +{ + [JsonProperty("answer_id")] + public uint AnswerId { get; set; } + + [JsonProperty("poll_media")] + public PollMedia PollMedia { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/PollAnswerCount.cs b/src/Discord.Net.Rest/API/Common/PollAnswerCount.cs new file mode 100644 index 00000000..043c4024 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/PollAnswerCount.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class PollAnswerCount +{ + [JsonProperty("id")] + public ulong Id { get; set; } + + [JsonProperty("count")] + public uint Count { get; set; } + + [JsonProperty("me_voted")] + public bool MeVoted { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/PollAnswerVoters.cs b/src/Discord.Net.Rest/API/Common/PollAnswerVoters.cs new file mode 100644 index 00000000..041c0836 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/PollAnswerVoters.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class PollAnswerVoters +{ + [JsonProperty("users")] + public User[] Users { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/PollMedia.cs b/src/Discord.Net.Rest/API/Common/PollMedia.cs new file mode 100644 index 00000000..614f5617 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/PollMedia.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class PollMedia +{ + [JsonProperty("text")] + public string Text { get; set; } + + [JsonProperty("emoji")] + public Optional Emoji { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/PollResults.cs b/src/Discord.Net.Rest/API/Common/PollResults.cs new file mode 100644 index 00000000..8c5fd7b8 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/PollResults.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class PollResults +{ + [JsonProperty("is_finalized")] + public bool IsFinalized { get; set; } + + [JsonProperty("answer_counts")] + public PollAnswerCount[] AnswerCounts { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs index a79c7f70..e22f8fbd 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateMessageParams.cs @@ -31,5 +31,8 @@ namespace Discord.API.Rest [JsonProperty("flags")] public Optional Flags { get; set; } + + [JsonProperty("poll")] + public Optional Poll { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs index e1cd383a..85cffe13 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs @@ -28,6 +28,7 @@ namespace Discord.API.Rest public Optional Flags { get; set; } public Optional Stickers { get; set; } public Optional TagIds { get; set; } + public Optional Poll { get; set; } public CreateMultipartPostAsync(params FileAttachment[] attachments) { @@ -62,6 +63,8 @@ namespace Discord.API.Rest message["sticker_ids"] = Stickers.Value; if (Flags.IsSpecified) message["flags"] = Flags.Value; + if (Poll.IsSpecified) + message["poll"] = Poll.Value; List attachments = new(); diff --git a/src/Discord.Net.Rest/API/Rest/CreatePollParams.cs b/src/Discord.Net.Rest/API/Rest/CreatePollParams.cs new file mode 100644 index 00000000..da14716d --- /dev/null +++ b/src/Discord.Net.Rest/API/Rest/CreatePollParams.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rest; + +internal class CreatePollParams +{ + [JsonProperty("question")] + public PollMedia Question { get; set; } + + [JsonProperty("answers")] + public PollAnswer[] Answers { get; set; } + + [JsonProperty("duration")] + public uint Duration { get; set; } + + [JsonProperty("allow_multiselect")] + public bool AllowMultiselect { get; set; } + + [JsonProperty("layout_type")] + public Optional LayoutType { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs index aac5a21c..52dd1806 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs @@ -48,6 +48,9 @@ namespace Discord.API.Rest [JsonProperty("applied_tags")] public Optional AppliedTags { get; set; } + [JsonProperty("poll")] + public Optional Poll { get; set; } + public IReadOnlyDictionary ToDictionary() { var d = new Dictionary(); @@ -80,6 +83,11 @@ namespace Discord.API.Rest payload["thread_name"] = ThreadName.Value; if (AppliedTags.IsSpecified) payload["applied_tags"] = AppliedTags.Value; + if (Flags.IsSpecified) + payload["flags"] = Flags.Value; + if (Poll.IsSpecified) + payload["poll"] = Poll.Value; + var json = new StringBuilder(); using (var text = new StringWriter(json)) diff --git a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs index 82725c9a..49a8268d 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs @@ -23,6 +23,7 @@ namespace Discord.API.Rest public Optional MessageComponent { get; set; } public Optional Flags { get; set; } public Optional Stickers { get; set; } + public Optional Poll { get; set; } public UploadFileParams(params Discord.FileAttachment[] attachments) { @@ -52,6 +53,8 @@ namespace Discord.API.Rest payload["sticker_ids"] = Stickers.Value; if (Flags.IsSpecified) payload["flags"] = Flags.Value; + if (Poll.IsSpecified) + payload["poll"] = Poll.Value; List attachments = new(); diff --git a/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs index eda650cd..9ba10016 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadInteractionFileParams.cs @@ -23,6 +23,7 @@ namespace Discord.API.Rest public Optional AllowedMentions { get; set; } public Optional MessageComponents { get; set; } public Optional Flags { get; set; } + public Optional Poll { get; set; } public bool HasData => Content.IsSpecified || @@ -31,7 +32,8 @@ namespace Discord.API.Rest AllowedMentions.IsSpecified || MessageComponents.IsSpecified || Flags.IsSpecified || - Files.Any(); + Files.Any() + || Poll.IsSpecified; public UploadInteractionFileParams(params FileAttachment[] files) { @@ -59,6 +61,8 @@ namespace Discord.API.Rest data["allowed_mentions"] = AllowedMentions.Value; if (Flags.IsSpecified) data["flags"] = Flags.Value; + if (Poll.IsSpecified) + data["poll"] = Poll.Value; List attachments = new(); diff --git a/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs index 22d1d9ab..c6242667 100644 --- a/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs +++ b/src/Discord.Net.Rest/API/Rest/UploadWebhookFileParams.cs @@ -24,6 +24,7 @@ namespace Discord.API.Rest public Optional Flags { get; set; } public Optional ThreadName { get; set; } public Optional AppliedTags { get; set; } + public Optional Poll { get; set; } public UploadWebhookFileParams(params FileAttachment[] files) { @@ -57,6 +58,8 @@ namespace Discord.API.Rest payload["thread_name"] = ThreadName.Value; if (AppliedTags.IsSpecified) payload["applied_tags"] = AppliedTags.Value; + if (Poll.IsSpecified) + payload["poll"] = Poll.Value; List attachments = new(); diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index b10efa92..05ec5fdc 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -2832,5 +2832,18 @@ namespace Discord.API => SendAsync("POST", () => $"applications/{CurrentApplicationId}/entitlements/{entitlementId}/consume", new BucketIds(), options: options); #endregion + + #region Polls + + public Task GetPollAnswerVotersAsync(ulong channelId, ulong messageId, uint answerId, int limit = 100, ulong? afterId = null, RequestOptions options = null) + { + var urlParams = $"?limit={limit}{(afterId is not null ? $"&after={afterId}" : string.Empty)}"; + return SendAsync("GET", () => $"channels/{channelId}/polls/{messageId}/answers/{answerId}{urlParams}", new BucketIds(channelId: channelId), options: options); + } + + public Task ExpirePollAsync(ulong channelId, ulong messageId, RequestOptions options = null) + => SendAsync("POST", () => $"channels/{channelId}/polls/{messageId}/expire", new BucketIds(channelId: channelId), options: options); + + #endregion } } diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index f09616d3..6b1fa561 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -274,7 +274,7 @@ namespace Discord.Rest /// The only valid are and . public static async Task SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, RequestOptions options, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, RequestOptions options, Embed[] embeds, MessageFlags flags, PollProperties poll) { embeds ??= Array.Empty(); if (embed != null) @@ -284,7 +284,8 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed."); - Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers); + Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers, poll: poll); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -308,7 +309,9 @@ namespace Discord.Rest } if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification) - throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags)); + throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags)); + + var args = new CreateMessageParams { @@ -319,7 +322,8 @@ namespace Discord.Rest MessageReference = messageReference?.ToModel(), Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, - Flags = flags + Flags = flags, + Poll = poll?.ToModel() ?? Optional.Unspecified }; var model = await client.ApiClient.CreateMessageAsync(channel.Id, args, options).ConfigureAwait(false); return RestUserMessage.Create(client, channel, client.CurrentUser, model); @@ -353,12 +357,12 @@ namespace Discord.Rest public static async Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client, string filePath, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, - bool isSpoiler, Embed[] embeds, MessageFlags flags = MessageFlags.None) + bool isSpoiler, Embed[] embeds, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { string filename = Path.GetFileName(filePath); using (var file = File.OpenRead(filePath)) return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags).ConfigureAwait(false); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll).ConfigureAwait(false); } /// Message content is too long, length must be less or equal to . @@ -366,11 +370,11 @@ namespace Discord.Rest public static async Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client, Stream stream, string filename, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, - bool isSpoiler, Embed[] embeds, MessageFlags flags = MessageFlags.None) + bool isSpoiler, Embed[] embeds, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { using (var file = new FileAttachment(stream, filename, isSpoiler: isSpoiler)) return await SendFileAsync(channel, client, file, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags).ConfigureAwait(false); + components, stickers, options, embeds, flags, poll).ConfigureAwait(false); } /// Message content is too long, length must be less or equal to . @@ -378,15 +382,15 @@ namespace Discord.Rest public static Task SendFileAsync(IMessageChannel channel, BaseDiscordClient client, FileAttachment attachment, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, - Embed[] embeds, MessageFlags flags = MessageFlags.None) + Embed[] embeds, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => SendFilesAsync(channel, client, new[] { attachment }, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// The only valid are , and . public static async Task SendFilesAsync(IMessageChannel channel, BaseDiscordClient client, IEnumerable attachments, string text, bool isTTS, Embed embed, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, ISticker[] stickers, RequestOptions options, - Embed[] embeds, MessageFlags flags) + Embed[] embeds, MessageFlags flags, PollProperties poll = null) { embeds ??= Array.Empty(); if (embed != null) @@ -396,7 +400,8 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, DiscordConfig.MaxEmbedsPerMessage, nameof(embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed."); - Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers, attachments); + Preconditions.MessageAtLeastOneOf(text, components, embeds, stickers, attachments, poll); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -446,7 +451,8 @@ namespace Discord.Rest MessageReference = messageReference?.ToModel() ?? Optional.Unspecified, MessageComponent = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional.Unspecified, - Flags = flags + Flags = flags, + Poll = poll?.ToModel() ?? Optional.Unspecified }; var model = await client.ApiClient.UploadFileAsync(channel.Id, args, options).ConfigureAwait(false); diff --git a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs index 2f80546a..f1212de1 100644 --- a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs @@ -9,20 +9,20 @@ namespace Discord.Rest /// public interface IRestMessageChannel : IMessageChannel { - /// - new Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + /// + new Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// - new Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + /// + new Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// - new Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + /// + new Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// - new Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + /// + new Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// - new Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + /// + new Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); /// /// Gets a message from this message channel. diff --git a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs index 8d9af24c..d0fccbb3 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs @@ -100,9 +100,9 @@ namespace Discord.Rest /// The only valid are and . public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// @@ -133,35 +133,35 @@ namespace Discord.Rest public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) @@ -245,35 +245,35 @@ namespace Discord.Rest /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); #endregion diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs index c65cdfad..f7d5652c 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs @@ -107,9 +107,9 @@ namespace Discord.Rest /// The only valid are and . public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// @@ -140,36 +140,36 @@ namespace Discord.Rest public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// public Task TriggerTypingAsync(RequestOptions options = null) => ChannelHelper.TriggerTypingAsync(this, Discord, options); @@ -224,37 +224,37 @@ namespace Discord.Rest /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); #endregion diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index 6a39423c..88aabdab 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -117,9 +117,9 @@ namespace Discord.Rest /// The only valid are , and . public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// @@ -150,9 +150,9 @@ namespace Discord.Rest public virtual Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . @@ -160,9 +160,9 @@ namespace Discord.Rest public virtual Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . @@ -170,9 +170,9 @@ namespace Discord.Rest public virtual Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . @@ -180,8 +180,8 @@ namespace Discord.Rest public virtual Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) - => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, components, stickers, options, embeds, flags); + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) + => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, components, stickers, options, embeds, flags, poll); /// public virtual Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) @@ -376,35 +376,35 @@ namespace Discord.Rest /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); #endregion #region IGuildChannel diff --git a/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs b/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs index a36e0cc1..ab51adda 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/CommandBase/RestCommandBase.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Discord.Net.Rest; using System; using System.Collections.Generic; @@ -65,6 +66,7 @@ namespace Discord.Rest /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// Message content is too long, length must be less or equal to . /// The parameters provided were invalid or the token was invalid. /// @@ -78,7 +80,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -109,6 +112,7 @@ namespace Discord.Rest throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions)); } } + Preconditions.ValidatePoll(poll); var response = new API.InteractionResponse { @@ -120,7 +124,8 @@ namespace Discord.Rest Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -146,7 +151,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -158,6 +164,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -165,7 +172,8 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -185,7 +193,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -194,7 +203,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(fileStream, fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -208,7 +217,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist"); @@ -216,7 +226,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(File.OpenRead(filePath), fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -229,9 +239,10 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { - return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// @@ -244,7 +255,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -256,6 +268,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -283,7 +296,16 @@ namespace Discord.Rest if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs index 130f03f3..c3d0ded3 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/MessageComponents/RestMessageComponent.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Discord.Net.Rest; using System; using System.Collections.Generic; @@ -75,7 +76,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -90,6 +92,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -116,7 +119,8 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel(), Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -251,7 +255,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -263,6 +268,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -270,7 +276,9 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : MessageFlags.None, + Poll = poll.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -290,7 +298,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -299,7 +308,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(fileStream, fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -313,7 +322,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist"); @@ -321,7 +331,7 @@ namespace Discord.Rest Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); using (var file = new FileAttachment(File.OpenRead(filePath), fileName)) - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } /// @@ -334,9 +344,10 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { - return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// @@ -349,7 +360,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -361,6 +373,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -388,7 +401,16 @@ namespace Discord.Rest if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs index f4c8c2bf..182e9bc7 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/Modals/RestModal.cs @@ -136,7 +136,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent component = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -148,6 +149,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -155,7 +157,8 @@ namespace Discord.Rest AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ??Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -190,7 +193,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent component = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -204,6 +208,7 @@ namespace Discord.Rest Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); Preconditions.NotNull(fileStream, nameof(fileStream), "File Stream must have data"); Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -212,7 +217,8 @@ namespace Discord.Rest IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - File = fileStream is not null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified + File = fileStream is not null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified, }; if (ephemeral) @@ -247,7 +253,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent component = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -260,6 +267,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist"); + Preconditions.ValidatePoll(poll); fileName ??= Path.GetFileName(filePath); Preconditions.NotNullOrEmpty(fileName, nameof(fileName), "File Name must not be empty or null"); @@ -272,7 +280,8 @@ namespace Discord.Rest IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - File = fileStream != null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified + File = fileStream != null ? new MultipartFile(fileStream, fileName) : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -305,7 +314,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent component = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -320,6 +330,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -347,7 +358,8 @@ namespace Discord.Rest Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -377,7 +389,8 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -389,6 +402,7 @@ namespace Discord.Rest Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -416,7 +430,16 @@ namespace Discord.Rest if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } @@ -430,9 +453,10 @@ namespace Discord.Rest AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { - return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); } /// diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs index 0360df97..551eb9ab 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs @@ -336,7 +336,8 @@ namespace Discord.Rest public abstract string RespondWithModal(Modal modal, RequestOptions options = null); /// - public abstract string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + public abstract string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -349,12 +350,13 @@ namespace Discord.Rest /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -369,12 +371,13 @@ namespace Discord.Rest /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -389,12 +392,13 @@ namespace Discord.Rest /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -408,12 +412,13 @@ namespace Discord.Rest /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -427,12 +432,13 @@ namespace Discord.Rest /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// public Task DeleteOriginalResponseAsync(RequestOptions options = null) @@ -450,8 +456,9 @@ namespace Discord.Rest IUser IDiscordInteraction.User => User; /// - Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => Task.FromResult(Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options)); + Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => Task.FromResult(Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll)); /// Task IDiscordInteraction.DeferAsync(bool ephemeral, RequestOptions options) => Task.FromResult(Defer(ephemeral, options)); @@ -460,8 +467,8 @@ namespace Discord.Rest => Task.FromResult(RespondWithModal(modal, options)); /// async Task IDiscordInteraction.FollowupAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, - MessageComponent components, Embed embed, RequestOptions options) - => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.GetOriginalResponseAsync(RequestOptions options) => await GetOriginalResponseAsync(options).ConfigureAwait(false); @@ -470,27 +477,33 @@ namespace Discord.Rest => await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, - AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(filePath, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(filePath, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); + Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); #if NETCOREAPP3_0_OR_GREATER != true /// - Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); + Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); /// - Task IDiscordInteraction.RespondWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); + Task IDiscordInteraction.RespondWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); /// - Task IDiscordInteraction.RespondWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); + Task IDiscordInteraction.RespondWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, + AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) => throw new NotSupportedException("REST-Based interactions don't support files."); #endif #endregion } diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs index 47e1a3b0..82b44c25 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/RestPingInteraction.cs @@ -37,11 +37,11 @@ namespace Discord.Rest public override string Defer(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException(); public override string RespondWithModal(Modal modal, RequestOptions options = null) => throw new NotSupportedException(); - public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); - public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) => throw new NotSupportedException(); + public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException(); } } diff --git a/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs index ddcab2e6..9b9096a5 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/SlashCommands/RestAutocompleteInteraction.cs @@ -100,17 +100,17 @@ namespace Discord.Rest => Respond(result, options); public override string Defer(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override string Respond(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); public override string RespondWithModal(Modal modal, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); diff --git a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs index a9d5c1f9..ac1eeb11 100644 --- a/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs +++ b/src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs @@ -386,5 +386,31 @@ namespace Discord.Rest author = RestUser.Create(client, guild, model, webhookId); return author; } + + public static IAsyncEnumerable> GetPollAnswerVotersAsync(ulong channelId, ulong msgId, ulong? afterId, + uint answerId, int? limit, BaseDiscordClient client, RequestOptions options) + { + return new PagedAsyncEnumerable( + DiscordConfig.MaxPollVotersPerBatch, + async (info, ct) => + { + var model = await client.ApiClient.GetPollAnswerVotersAsync(channelId, msgId, answerId, info.PageSize, info.Position, options).ConfigureAwait(false); + return model.Users.Select(x => RestUser.Create(client, x)).ToImmutableArray(); + }, + nextPage: (info, lastPage) => + { + if (lastPage.Count != DiscordConfig.MaxPollVotersPerBatch) + return false; + + info.Position = lastPage.Max(x => x.Id); + return true; + }, + count: limit, + start: afterId + ); + } + + public static Task EndPollAsync(ulong channelId, ulong messageId, BaseDiscordClient client, RequestOptions options) + => client.ApiClient.ExpirePollAsync(channelId, messageId, options); } } diff --git a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs index 2312f92c..4144e2c3 100644 --- a/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs +++ b/src/Discord.Net.Rest/Entities/Messages/RestUserMessage.cs @@ -51,6 +51,9 @@ namespace Discord.Rest /// public IMessageInteractionMetadata InteractionMetadata { get; internal set; } + /// + public Poll? Poll { get; internal set; } + /// public MessageResolvedData ResolvedData { get; internal set; } @@ -167,6 +170,9 @@ namespace Discord.Rest } if (model.InteractionMetadata.IsSpecified) InteractionMetadata = model.InteractionMetadata.Value.ToInteractionMetadata(); + + if (model.Poll.IsSpecified) + Poll = model.Poll.Value.ToEntity(); } /// @@ -203,6 +209,15 @@ namespace Discord.Rest return MessageHelper.CrosspostAsync(this, Discord, options); } + /// + public Task EndPollAsync(RequestOptions options = null) + => MessageHelper.EndPollAsync(Channel.Id, Id, Discord, options); + + /// + public IAsyncEnumerable> GetPollAnswerVotersAsync(uint answerId, int? limit = null, ulong? afterId = null, + RequestOptions options = null) + => MessageHelper.GetPollAnswerVotersAsync(Channel.Id, Id, afterId, answerId, limit, Discord, options); + private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; } } diff --git a/src/Discord.Net.Rest/Extensions/PollExtensions.cs b/src/Discord.Net.Rest/Extensions/PollExtensions.cs new file mode 100644 index 00000000..d13f6df1 --- /dev/null +++ b/src/Discord.Net.Rest/Extensions/PollExtensions.cs @@ -0,0 +1,61 @@ +using System.Collections.Immutable; +using System.Linq; + +namespace Discord.Rest; + +internal static class PollExtensions +{ + public static API.Rest.CreatePollParams ToModel(this PollProperties poll) + => new() + { + AllowMultiselect = poll.AllowMultiselect, + Duration = poll.Duration, + LayoutType = poll.LayoutType, + Answers = poll.Answers.Select(x => new API.PollAnswer + { + PollMedia = new API.PollMedia + { + Emoji = x.Emoji is not null + ? new API.Emoji + { + Id = x.Emoji is Emote emote ? emote.Id : null, + Name = x.Emoji is Emoji emoji ? emoji.Name : null, + } : Optional.Unspecified, + Text = x.Text, + } + }).ToArray(), + Question = new API.PollMedia + { + Emoji = poll.Question.Emoji is not null + ? new API.Emoji + { + Id = poll.Question.Emoji is Emote emote ? emote.Id : null, + Name = poll.Question.Emoji is Emoji emoji ? emoji.Name : null, + } + : Optional.Unspecified, + Text = poll.Question.Text, + }, + }; + + public static Poll ToEntity(this API.Poll poll) + => new( + new PollMedia(poll.Question.Text, + poll.Question.Emoji.IsSpecified + ? poll.Question.Emoji.Value.ToIEmote() + : null), + poll.Answers.Select(x => + new PollAnswer( + x.AnswerId, + new PollMedia(x.PollMedia.Text, x.PollMedia.Emoji.IsSpecified + ? x.PollMedia.Emoji.Value.ToIEmote() + : null))).ToImmutableArray(), + poll.Expiry, + poll.AllowMultiselect, + poll.LayoutType, + poll.PollResults.IsSpecified + ? new PollResults( + poll.PollResults.Value.IsFinalized, + poll.PollResults.Value.AnswerCounts.Select(x => new PollAnswerCounts(x.Id, x.Count, x.MeVoted)).ToImmutableArray()) + : null + ); +} diff --git a/src/Discord.Net.WebSocket/API/Gateway/PollVote.cs b/src/Discord.Net.WebSocket/API/Gateway/PollVote.cs new file mode 100644 index 00000000..dec562b6 --- /dev/null +++ b/src/Discord.Net.WebSocket/API/Gateway/PollVote.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; + +namespace Discord.API.Gateway; + +internal class PollVote +{ + [JsonProperty("user_id")] + public ulong UserId { get; set; } + + [JsonProperty("channel_id")] + public ulong ChannelId { get; set; } + + [JsonProperty("message_id")] + public ulong MessageId { get; set; } + + [JsonProperty("guild_id")] + public Optional GuildId { get; set; } + + [JsonProperty("answer_id")] + public ulong AnswerId { get; set; } +} diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs index 2a7f7ae7..06154b0f 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.Events.cs @@ -286,6 +286,31 @@ namespace Discord.WebSocket internal readonly AsyncEvent, Cacheable, IEmote, Task>> _reactionsRemovedForEmoteEvent = new AsyncEvent, Cacheable, IEmote, Task>>(); #endregion + #region Polls + + /// + /// Fired when a vote is added to a poll. + /// + public event Func, Cacheable, Cacheable, Cacheable?, ulong, Task> PollVoteAdded + { + add { _pollVoteAdded.Add(value); } + remove { _pollVoteAdded.Remove(value); } + } + internal readonly AsyncEvent, Cacheable, Cacheable, Cacheable?, ulong, Task>> _pollVoteAdded = new (); + + /// + /// Fired when a vote is removed from a poll. + /// + public event Func, Cacheable, Cacheable, Cacheable?, ulong, Task> PollVoteRemoved + { + add { _pollVoteRemoved.Add(value); } + remove { _pollVoteRemoved.Remove(value); } + } + + internal readonly AsyncEvent, Cacheable, Cacheable, Cacheable?, ulong, Task>> _pollVoteRemoved = new (); + + #endregion + #region Roles /// Fired when a role is created. public event Func RoleCreated diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index 1c415cdd..1ed22869 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -523,6 +523,9 @@ namespace Discord.WebSocket client.EntitlementCreated += (arg1) => _entitlementCreated.InvokeAsync(arg1); client.EntitlementUpdated += (arg1, arg2) => _entitlementUpdated.InvokeAsync(arg1, arg2); client.EntitlementDeleted += (arg1) => _entitlementDeleted.InvokeAsync(arg1); + + client.PollVoteAdded += (arg1, arg2, arg3, arg4, arg5) => _pollVoteAdded.InvokeAsync(arg1, arg2, arg3, arg4, arg5); + client.PollVoteRemoved += (arg1, arg2, arg3, arg4, arg5) => _pollVoteRemoved.InvokeAsync(arg1, arg2, arg3, arg4, arg5); } public async Task CreateGlobalApplicationCommandAsync(ApplicationCommandProperties properties, RequestOptions options = null) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 0bb23a6d..06179e10 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -2029,6 +2029,116 @@ namespace Discord.WebSocket break; #endregion + #region Polls + + case "MESSAGE_POLL_VOTE_ADD": + { + await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_POLL_VOTE_ADD)").ConfigureAwait(false); + + var data = (payload as JToken).ToObject(_serializer); + + Cacheable? guildCacheable = null; + + Cacheable userCacheable; + Cacheable channelCacheable; + Cacheable messageCacheable; + + if (data.GuildId.IsSpecified) + { + var guild = State.GetGuild(data.GuildId.Value); + guildCacheable = new (guild, data.GuildId.Value, guild is not null, () => Rest.GetGuildAsync(data.GuildId.Value)); + + if (guild is not null) + { + var user = guild.GetUser(data.UserId); + userCacheable = new (user, data.UserId, user is not null, async () => await Rest.GetGuildUserAsync(data.GuildId.Value, data.UserId)); + + var channel = guild.GetTextChannel(data.ChannelId); + channelCacheable = new(channel, data.ChannelId, channel is not null, async () => (RestTextChannel)await Rest.GetChannelAsync(data.ChannelId)); + + var message = channel?.GetCachedMessage(data.MessageId) as IUserMessage; + messageCacheable = new (message, data.MessageId, message is not null, + async () => (channel ?? (ITextChannel)await Rest.GetChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + else + { + userCacheable = new (null, data.UserId, false, async () => await Rest.GetGuildUserAsync(data.GuildId.Value, data.UserId)); + channelCacheable = new(null, data.ChannelId, false, async () => (RestTextChannel)(await Rest.GetChannelAsync(data.ChannelId))); + messageCacheable = new(null, data.MessageId, false, + async () => await ((ITextChannel)await Rest.GetChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + } + else + { + var user = State.GetUser(data.UserId); + userCacheable = new(user, data.UserId, user is not null, async () => await GetUserAsync(data.UserId)); + + var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel; + channelCacheable = new(channel, data.ChannelId, channel is not null, async () => await Rest.GetDMChannelAsync(data.ChannelId) as IRestMessageChannel); + + var message = channel?.GetCachedMessage(data.MessageId) as IUserMessage; + messageCacheable = new(message, data.MessageId, message is not null, async () => await (channel ?? (IMessageChannel)await Rest.GetDMChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + + await TimedInvokeAsync(_pollVoteAdded, nameof(PollVoteAdded), userCacheable, channelCacheable, messageCacheable, guildCacheable, data.AnswerId); + } + break; + + case "MESSAGE_POLL_VOTE_REMOVE": + { + await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_POLL_VOTE_REMOVE)").ConfigureAwait(false); + + var data = (payload as JToken).ToObject(_serializer); + + Cacheable? guildCacheable = null; + + Cacheable userCacheable; + Cacheable channelCacheable; + Cacheable messageCacheable; + + if (data.GuildId.IsSpecified) + { + var guild = State.GetGuild(data.GuildId.Value); + guildCacheable = new(guild, data.GuildId.Value, guild is not null, () => Rest.GetGuildAsync(data.GuildId.Value)); + + if (guild is not null) + { + var user = guild.GetUser(data.UserId); + userCacheable = new(user, data.UserId, user is not null, async () => await Rest.GetGuildUserAsync(data.GuildId.Value, data.UserId)); + + var channel = guild.GetTextChannel(data.ChannelId); + channelCacheable = new(channel, data.ChannelId, channel is not null, async () => (RestTextChannel)await Rest.GetChannelAsync(data.ChannelId)); + + var message = channel?.GetCachedMessage(data.MessageId) as IUserMessage; + messageCacheable = new(message, data.MessageId, message is not null, + async () => (channel ?? (ITextChannel)await Rest.GetChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + else + { + userCacheable = new(null, data.UserId, false, async () => await Rest.GetGuildUserAsync(data.GuildId.Value, data.UserId)); + channelCacheable = new(null, data.ChannelId, false, async () => (RestTextChannel)(await Rest.GetChannelAsync(data.ChannelId))); + messageCacheable = new(null, data.MessageId, false, + async () => await ((ITextChannel)await Rest.GetChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + } + else + { + var user = State.GetUser(data.UserId); + userCacheable = new(user, data.UserId, user is not null, async () => await GetUserAsync(data.UserId)); + + var channel = State.GetChannel(data.ChannelId) as ISocketMessageChannel; + channelCacheable = new(channel, data.ChannelId, channel is not null, async () => await Rest.GetDMChannelAsync(data.ChannelId) as IRestMessageChannel); + + var message = channel?.GetCachedMessage(data.MessageId) as IUserMessage; + messageCacheable = new(message, data.MessageId, message is not null, async () => await (channel ?? (IMessageChannel)await Rest.GetDMChannelAsync(data.ChannelId)).GetMessageAsync(data.MessageId) as IUserMessage); + } + + await TimedInvokeAsync(_pollVoteRemoved, nameof(PollVoteRemoved), userCacheable, channelCacheable, messageCacheable, guildCacheable, data.AnswerId); + } + break; + + #endregion + #region Statuses case "PRESENCE_UPDATE": { diff --git a/src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs index 5fbd98a9..47e77ce4 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs @@ -18,35 +18,35 @@ namespace Discord.WebSocket /// IReadOnlyCollection CachedMessages { get; } - /// + /// new Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// + /// new Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// + /// new Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// + /// new Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None); + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null); - /// + /// new Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, - MessageFlags flags = MessageFlags.None); + MessageFlags flags = MessageFlags.None, PollProperties poll = null); /// /// Gets a cached message from this channel. diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs index a5dc2051..7f087b1b 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs @@ -142,45 +142,45 @@ namespace Discord.WebSocket /// The only valid are and . public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// The only valid are and . public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) @@ -282,35 +282,35 @@ namespace Discord.WebSocket /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); #endregion #region IChannel diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs index bc160e1b..3bba7e66 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs @@ -181,45 +181,45 @@ namespace Discord.WebSocket /// The only valid are and . public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// The only valid are and . public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are and . public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) @@ -353,35 +353,35 @@ namespace Discord.WebSocket /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); #endregion #region IAudioChannel diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index 06560aff..cba49835 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -225,45 +225,45 @@ namespace Discord.WebSocket /// The only valid are , and . public virtual Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, - MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, embeds, flags); + components, stickers, options, embeds, flags, poll); /// /// The only valid are , and . public virtual Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, allowedMentions, messageReference, - components, stickers, options, isSpoiler, embeds, flags); + components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are , and . public virtual Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, isSpoiler, embeds, flags); + messageReference, components, stickers, options, isSpoiler, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are , and . public virtual Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFileAsync(this, Discord, attachment, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// /// Message content is too long, length must be less or equal to . /// The only valid are , and . public virtual Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, - Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, - messageReference, components, stickers, options, embeds, flags); + messageReference, components, stickers, options, embeds, flags, poll); /// public virtual Task DeleteMessagesAsync(IEnumerable messages, RequestOptions options = null) @@ -436,35 +436,35 @@ namespace Discord.WebSocket /// async Task IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, - components, stickers, embeds, flags).ConfigureAwait(false); + components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFileAsync(FileAttachment attachment, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) => await SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, - stickers, embeds, flags).ConfigureAwait(false); + stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendFilesAsync(IEnumerable attachments, string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, - MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); /// async Task IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent components, - ISticker[] stickers, Embed[] embeds, MessageFlags flags) - => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); + ISticker[] stickers, Embed[] embeds, MessageFlags flags, PollProperties poll) + => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags, poll).ConfigureAwait(false); #endregion diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs index 25c48a79..82d6e8d0 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/MessageComponents/SocketMessageComponent.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Discord.Net.Rest; using Discord.Rest; using System; @@ -80,7 +81,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -95,6 +97,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -120,7 +123,8 @@ namespace Discord.WebSocket Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; lock (_lock) @@ -144,7 +148,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -159,6 +164,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -186,7 +192,8 @@ namespace Discord.WebSocket Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -313,7 +320,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -325,6 +333,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -332,7 +341,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -351,7 +361,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -363,6 +374,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -390,7 +402,16 @@ namespace Discord.WebSocket if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs index 9543b8af..8f87fae1 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/Modals/SocketModal.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Discord.Net.Rest; using Discord.Rest; @@ -77,7 +78,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -92,6 +94,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -117,7 +120,8 @@ namespace Discord.WebSocket Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; lock (_lock) @@ -141,7 +145,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -156,6 +161,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -183,7 +189,8 @@ namespace Discord.WebSocket Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -310,7 +317,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -322,6 +330,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -329,7 +338,9 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -348,7 +359,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -360,6 +372,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -387,7 +400,16 @@ namespace Discord.WebSocket if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs index 498eece9..0889d00c 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SlashCommands/SocketAutocompleteInteraction.cs @@ -91,15 +91,15 @@ namespace Discord.WebSocket /// public Task RespondAsync(RequestOptions options = null, params AutocompleteResult[] result) => RespondAsync(result, options); - public override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); public override Task DeferAsync(bool ephemeral = false, RequestOptions options = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); - public override Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + public override Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) => throw new NotSupportedException("Autocomplete interactions don't support this method!"); /// diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs index 2c6b27a0..1f3f4928 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketBaseCommand/SocketCommandBase.cs @@ -1,3 +1,4 @@ +using Discord.API.Rest; using Discord.Rest; using System; using System.Collections.Generic; @@ -75,7 +76,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -90,6 +92,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -117,7 +120,8 @@ namespace Discord.WebSocket Embeds = embeds.Select(x => x.ToModel()).ToArray(), TTS = isTTS, Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, - Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified + Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified } }; @@ -178,7 +182,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -193,6 +198,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); // check that user flag and user Id list are exclusive, same with role flag and role Id list if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue) @@ -218,7 +224,8 @@ namespace Discord.WebSocket Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, IsTTS = isTTS, Flags = ephemeral ? MessageFlags.Ephemeral : Optional.Unspecified, - MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; lock (_lock) @@ -242,7 +249,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -254,6 +262,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); var args = new API.Rest.CreateWebhookMessageParams { @@ -261,7 +270,8 @@ namespace Discord.WebSocket AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, IsTTS = isTTS, Embeds = embeds.Select(x => x.ToModel()).ToArray(), - Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified + Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified }; if (ephemeral) @@ -280,7 +290,8 @@ namespace Discord.WebSocket AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, - RequestOptions options = null) + RequestOptions options = null, + PollProperties poll = null) { if (!IsValidToken) throw new InvalidOperationException("Interaction token is no longer valid"); @@ -292,6 +303,7 @@ namespace Discord.WebSocket Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed."); + Preconditions.ValidatePoll(poll); foreach (var attachment in attachments) { @@ -319,7 +331,16 @@ namespace Discord.WebSocket if (ephemeral) flags |= MessageFlags.Ephemeral; - var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) { Flags = flags, Content = text, IsTTS = isTTS, Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified }; + var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray()) + { + Flags = flags, + Content = text, + IsTTS = isTTS, + Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional.Unspecified, + AllowedMentions = allowedMentions?.ToModel() ?? Optional.Unspecified, + MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, + Poll = poll?.ToModel() ?? Optional.Unspecified + }; return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options); } diff --git a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs index ae2ac198..24aecb47 100644 --- a/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs +++ b/src/Discord.Net.WebSocket/Entities/Interaction/SocketInteraction.cs @@ -207,10 +207,11 @@ namespace Discord.WebSocket /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// Message content is too long, length must be less or equal to . /// The parameters provided were invalid or the token was invalid. public abstract Task RespondAsync(string text = null, Embed[] embeds = null, bool isTTS = false, - bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Responds to this interaction with a file attachment. @@ -225,16 +226,17 @@ namespace Discord.WebSocket /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public async Task RespondWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -249,6 +251,7 @@ namespace Discord.WebSocket /// if the response should be hidden to everyone besides the invoker of the command, otherwise . /// The allowed mentions for this response. /// The request options for this response. + /// A poll to send with the message. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// @@ -256,11 +259,11 @@ namespace Discord.WebSocket /// contains the sent message. /// public async Task RespondWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -274,6 +277,7 @@ namespace Discord.WebSocket /// if the response should be hidden to everyone besides the invoker of the command, otherwise . /// The allowed mentions for this response. /// The request options for this response. + /// A poll to send with the message. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// @@ -281,8 +285,8 @@ namespace Discord.WebSocket /// contains the sent message. /// public Task RespondWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); /// /// Responds to this interaction with a collection of file attachments. @@ -294,6 +298,7 @@ namespace Discord.WebSocket /// if the response should be hidden to everyone besides the invoker of the command, otherwise . /// The allowed mentions for this response. /// The request options for this response. + /// A poll to send with the message. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// @@ -301,7 +306,7 @@ namespace Discord.WebSocket /// contains the sent message. /// public abstract Task RespondWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -314,11 +319,12 @@ namespace Discord.WebSocket /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// The sent message. /// public abstract Task FollowupAsync(string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Sends a followup message for this interaction. @@ -333,15 +339,16 @@ namespace Discord.WebSocket /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// The sent message. /// public async Task FollowupWithFileAsync(Stream fileStream, string fileName, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(fileStream, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -358,15 +365,16 @@ namespace Discord.WebSocket /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. /// The request options for this response. + /// A poll to send with the message. /// /// The sent message. /// public async Task FollowupWithFileAsync(string filePath, string fileName = null, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) { using (var file = new FileAttachment(filePath, fileName)) { - return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); } } @@ -382,13 +390,14 @@ namespace Discord.WebSocket /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public Task FollowupWithFileAsync(FileAttachment attachment, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null) - => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null) + => FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll); /// /// Sends a followup message for this interaction. @@ -402,12 +411,13 @@ namespace Discord.WebSocket /// The request options for this response. /// A to be sent with this response. /// A single embed to send with this response. If this is passed alongside an array of embeds, the single embed will be ignored. + /// A poll to send with the message. /// /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// public abstract Task FollowupWithFilesAsync(IEnumerable attachments, string text = null, Embed[] embeds = null, bool isTTS = false, bool ephemeral = false, - AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null); + AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null); /// /// Gets the original response for this interaction. @@ -493,24 +503,27 @@ namespace Discord.WebSocket async Task IDiscordInteraction.ModifyOriginalResponseAsync(Action func, RequestOptions options) => await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false); /// - async Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, + Embed embed, RequestOptions options, PollProperties poll) + => await RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, + MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFilesAsync(IEnumerable attachments, string text, Embed[] embeds, bool isTTS, + bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); #if NETCOREAPP3_0_OR_GREATER != true /// - async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); /// - async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) - => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); + async Task IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll) + => await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false); #endif #endregion } diff --git a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs index 74d82fdb..58026e70 100644 --- a/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs +++ b/src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs @@ -52,6 +52,9 @@ namespace Discord.WebSocket /// public IMessageInteractionMetadata InteractionMetadata { get; internal set; } + /// + public Poll? Poll { get; internal set; } + /// public MessageResolvedData ResolvedData { get; internal set; } @@ -209,6 +212,9 @@ namespace Discord.WebSocket if (model.InteractionMetadata.IsSpecified) InteractionMetadata = model.InteractionMetadata.Value.ToInteractionMetadata(); + + if (model.Poll.IsSpecified) + Poll = model.Poll.Value.ToEntity(); } /// @@ -244,6 +250,15 @@ namespace Discord.WebSocket return MessageHelper.CrosspostAsync(this, Discord, options); } + /// + public Task EndPollAsync(RequestOptions options = null) + => MessageHelper.EndPollAsync(Channel.Id, Id, Discord, options); + + /// + public IAsyncEnumerable> GetPollAnswerVotersAsync(uint answerId, int? limit = null, ulong? afterId = null, + RequestOptions options = null) + => MessageHelper.GetPollAnswerVotersAsync(Channel.Id, Id, afterId, answerId, limit, Discord, options); + private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; internal new SocketUserMessage Clone() => MemberwiseClone() as SocketUserMessage; } diff --git a/src/Discord.Net.Webhook/DiscordWebhookClient.cs b/src/Discord.Net.Webhook/DiscordWebhookClient.cs index 44beb64f..b064a756 100644 --- a/src/Discord.Net.Webhook/DiscordWebhookClient.cs +++ b/src/Discord.Net.Webhook/DiscordWebhookClient.cs @@ -115,8 +115,8 @@ public class DiscordWebhookClient : IDisposable public Task SendMessageAsync(string text = null, bool isTTS = false, IEnumerable embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, - ulong[] appliedTags = null) - => WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, components, flags, threadId, threadName, appliedTags); + ulong[] appliedTags = null, PollProperties poll = null) + => WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, components, flags, threadId, threadName, appliedTags, poll); /// /// Modifies a message posted using this webhook. @@ -157,9 +157,9 @@ public class DiscordWebhookClient : IDisposable IEnumerable embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageComponent components = null, MessageFlags flags = MessageFlags.None, ulong? threadId = null, - string threadName = null, ulong[] appliedTags = null) + string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) => WebhookClientHelper.SendFileAsync(this, filePath, text, isTTS, embeds, username, avatarUrl, - allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags); + allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags, poll); /// /// Sends a message to the channel for this webhook with an attachment. @@ -171,18 +171,18 @@ public class DiscordWebhookClient : IDisposable IEnumerable embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageComponent components = null, MessageFlags flags = MessageFlags.None, ulong? threadId = null, - string threadName = null, ulong[] appliedTags = null) + string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) => WebhookClientHelper.SendFileAsync(this, stream, filename, text, isTTS, embeds, username, - avatarUrl, allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags); + avatarUrl, allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags, poll); /// Sends a message to the channel for this webhook with an attachment. /// Returns the ID of the created message. public Task SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, IEnumerable embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, - MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null) + MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) => WebhookClientHelper.SendFileAsync(this, attachment, text, isTTS, embeds, username, - avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags); + avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags, poll); /// /// Sends a message to the channel for this webhook with an attachment. @@ -193,9 +193,9 @@ public class DiscordWebhookClient : IDisposable public Task SendFilesAsync(IEnumerable attachments, string text, bool isTTS = false, IEnumerable embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent components = null, - MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null) + MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) => WebhookClientHelper.SendFilesAsync(this, attachments, text, isTTS, embeds, username, avatarUrl, - allowedMentions, components, options, flags, threadId, threadName, appliedTags); + allowedMentions, components, options, flags, threadId, threadName, appliedTags, poll); /// /// Modifies the properties of this webhook. diff --git a/src/Discord.Net.Webhook/WebhookClientHelper.cs b/src/Discord.Net.Webhook/WebhookClientHelper.cs index ea04987d..0d3daeb7 100644 --- a/src/Discord.Net.Webhook/WebhookClientHelper.cs +++ b/src/Discord.Net.Webhook/WebhookClientHelper.cs @@ -26,7 +26,8 @@ namespace Discord.Webhook public static async Task SendMessageAsync(DiscordWebhookClient client, string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options, MessageComponent components, - MessageFlags flags, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null) + MessageFlags flags, ulong? threadId = null, string threadName = null, ulong[] appliedTags = null, + PollProperties poll = null) { var args = new CreateWebhookMessageParams { @@ -35,7 +36,8 @@ namespace Discord.Webhook Flags = flags }; - Preconditions.WebhookMessageAtLeastOneOf(text, components, embeds?.ToArray()); + Preconditions.WebhookMessageAtLeastOneOf(text, components, embeds?.ToArray(), poll: poll); + Preconditions.ValidatePoll(poll); if (embeds != null) args.Embeds = embeds.Select(x => x.ToModel()).ToArray(); @@ -51,6 +53,8 @@ namespace Discord.Webhook args.ThreadName = threadName; if (appliedTags != null) args.AppliedTags = appliedTags; + if (poll != null) + args.Poll = poll.ToModel(); if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds) throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds and none.", nameof(flags)); @@ -136,36 +140,37 @@ namespace Discord.Webhook public static async Task SendFileAsync(DiscordWebhookClient client, string filePath, string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options, bool isSpoiler, MessageComponent components, MessageFlags flags = MessageFlags.None, ulong? threadId = null, string threadName = null, - ulong[] appliedTags = null) + ulong[] appliedTags = null, PollProperties poll = null) { string filename = Path.GetFileName(filePath); using (var file = File.OpenRead(filePath)) - return await SendFileAsync(client, file, filename, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags).ConfigureAwait(false); + return await SendFileAsync(client, file, filename, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, isSpoiler, components, flags, threadId, threadName, appliedTags, poll).ConfigureAwait(false); } public static Task SendFileAsync(DiscordWebhookClient client, Stream stream, string filename, string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options, bool isSpoiler, - MessageComponent components, MessageFlags flags, ulong? threadId, string threadName = null, ulong[] appliedTags = null) - => SendFileAsync(client, new FileAttachment(stream, filename, isSpoiler: isSpoiler), text, isTTS, embeds, username, avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags); + MessageComponent components, MessageFlags flags, ulong? threadId, string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) + => SendFileAsync(client, new FileAttachment(stream, filename, isSpoiler: isSpoiler), text, isTTS, embeds, username, avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags, poll); public static Task SendFileAsync(DiscordWebhookClient client, FileAttachment attachment, string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, MessageComponent components, RequestOptions options, MessageFlags flags, ulong? threadId, string threadName = null, - ulong[] appliedTags = null) - => SendFilesAsync(client, new FileAttachment[] { attachment }, text, isTTS, embeds, username, avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags); + ulong[] appliedTags = null, PollProperties poll = null) + => SendFilesAsync(client, new FileAttachment[] { attachment }, text, isTTS, embeds, username, avatarUrl, allowedMentions, components, options, flags, threadId, threadName, appliedTags, poll); public static async Task SendFilesAsync(DiscordWebhookClient client, IEnumerable attachments, string text, bool isTTS, IEnumerable embeds, string username, string avatarUrl, AllowedMentions allowedMentions, MessageComponent components, RequestOptions options, - MessageFlags flags, ulong? threadId, string threadName = null, ulong[] appliedTags = null) + MessageFlags flags, ulong? threadId, string threadName = null, ulong[] appliedTags = null, PollProperties poll = null) { embeds ??= Array.Empty(); Preconditions.AtMost(allowedMentions?.RoleIds?.Count ?? 0, 100, nameof(allowedMentions.RoleIds), "A max of 100 role Ids are allowed."); Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed."); Preconditions.AtMost(embeds.Count(), DiscordConfig.MaxEmbedsPerMessage, nameof(embeds), $"A max of {DiscordConfig.MaxEmbedsPerMessage} Embeds are allowed."); + Preconditions.ValidatePoll(poll); - Preconditions.WebhookMessageAtLeastOneOf(text, components, embeds.ToArray(), attachments); + Preconditions.WebhookMessageAtLeastOneOf(text, components, embeds.ToArray(), attachments, poll: poll); foreach (var attachment in attachments) { @@ -202,7 +207,8 @@ namespace Discord.Webhook MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional.Unspecified, Flags = flags, ThreadName = threadName, - AppliedTags = appliedTags + AppliedTags = appliedTags, + Poll = poll?.ToModel() ?? Optional.Unspecified }; var msg = await client.ApiClient.UploadWebhookFileAsync(client.Webhook.Id, args, options, threadId).ConfigureAwait(false); return msg.Id; diff --git a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs index de7d0ae0..58cc4f8a 100644 --- a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs @@ -95,6 +95,7 @@ namespace Discord AssertFlag(() => new ChannelPermissions(sendVoiceMessages: true), ChannelPermission.SendVoiceMessages); AssertFlag(() => new ChannelPermissions(useClydeAI: true), ChannelPermission.UseClydeAI); AssertFlag(() => new ChannelPermissions(setVoiceChannelStatus: true), ChannelPermission.SetVoiceChannelStatus); + AssertFlag(() => new ChannelPermissions(sendPolls: true), ChannelPermission.SendPolls); } /// @@ -162,6 +163,7 @@ namespace Discord AssertUtil(ChannelPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable)); AssertUtil(ChannelPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable)); AssertUtil(ChannelPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable)); + AssertUtil(ChannelPermission.SendPolls, x => x.SendPolls, (p, enable) => p.Modify(sendPolls: enable)); } /// diff --git a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs index 102860c8..8085f1bf 100644 --- a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs @@ -106,6 +106,7 @@ namespace Discord AssertFlag(() => new GuildPermissions(useClydeAI: true), GuildPermission.UseClydeAI); AssertFlag(() => new GuildPermissions(createGuildExpressions: true), GuildPermission.CreateGuildExpressions); AssertFlag(() => new GuildPermissions(setVoiceChannelStatus: true), GuildPermission.SetVoiceChannelStatus); + AssertFlag(() => new GuildPermissions(sendPolls: true), GuildPermission.SendPolls); } /// @@ -190,6 +191,7 @@ namespace Discord AssertUtil(GuildPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable)); AssertUtil(GuildPermission.CreateGuildExpressions, x => x.CreateGuildExpressions, (p, enable) => p.Modify(createGuildExpressions: enable)); AssertUtil(GuildPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable)); + AssertUtil(GuildPermission.SendPolls, x => x.SendPolls, (p, enable) => p.Modify(sendPolls: enable)); } } } diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs index 2a7f8065..8f1469a1 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs @@ -83,10 +83,10 @@ namespace Discord throw new NotImplementedException(); } - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); + public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); } } diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs index 8d911727..423b4cc9 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs @@ -93,17 +93,17 @@ namespace Discord throw new NotImplementedException(); } - public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } - public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } @@ -113,7 +113,7 @@ namespace Discord throw new NotImplementedException(); } - public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); + public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); } } diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs index a9abe2e8..82c69d52 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs @@ -182,17 +182,17 @@ namespace Discord throw new NotImplementedException(); } - public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } - public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) + public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) { throw new NotImplementedException(); } @@ -217,8 +217,8 @@ namespace Discord throw new NotImplementedException(); } - public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); + public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); public Task CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); public Task CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException(); public Task CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null) => throw new NotImplementedException(); diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs index c2e34af6..f88bf484 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs @@ -82,11 +82,11 @@ namespace Discord public Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) => throw new NotImplementedException(); public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null) => throw new NotImplementedException(); public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null) => throw new NotImplementedException(); - public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); - public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) => throw new NotImplementedException(); + public Task SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); + public Task SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, PollProperties poll = null) => throw new NotImplementedException(); public Task SyncPermissionsAsync(RequestOptions options = null) => throw new NotImplementedException(); public Task TriggerTypingAsync(RequestOptions options = null) => throw new NotImplementedException(); Task IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => throw new NotImplementedException();