diff --git a/src/Discord.Net.Core/DiscordConfig.cs b/src/Discord.Net.Core/DiscordConfig.cs index 067c55225..4e9ac1f8a 100644 --- a/src/Discord.Net.Core/DiscordConfig.cs +++ b/src/Discord.Net.Core/DiscordConfig.cs @@ -132,6 +132,21 @@ namespace Discord /// public const int MaxAuditLogEntriesPerBatch = 100; + /// + /// Returns the max number of stickers that can be sent on a message. + /// + public const int MaxStickersPerMessage = 3; + + /// + /// Returns the max numbe of files that can be sent on a message. + /// + public const int MaxFilesPerMessage = 10; + + /// + /// Returns the max number of embeds that can be sent on a message. + /// + public const int MaxEmbedsPerMessage = 10; + /// /// Gets or sets how a request should act in the case of an error, by default. /// @@ -165,23 +180,23 @@ namespace Discord /// internal bool DisplayInitialLog { get; set; } = true; - /// - /// Gets or sets whether or not rate-limits should use the system clock. - /// - /// - /// If set to false, we will use the X-RateLimit-Reset-After header - /// to determine when a rate-limit expires, rather than comparing the - /// X-RateLimit-Reset timestamp to the system time. - /// - /// This should only be changed to false if the system is known to have - /// a clock that is out of sync. Relying on the Reset-After header will - /// incur network lag. - /// - /// Regardless of this property, we still rely on the system's wall-clock - /// to determine if a bucket is rate-limited; we do not use any monotonic - /// clock. Your system will still need a stable clock. - /// - public bool UseSystemClock { get; set; } = true; + /// + /// Gets or sets whether or not rate-limits should use the system clock. + /// + /// + /// If set to false, we will use the X-RateLimit-Reset-After header + /// to determine when a rate-limit expires, rather than comparing the + /// X-RateLimit-Reset timestamp to the system time. + /// + /// This should only be changed to false if the system is known to have + /// a clock that is out of sync. Relying on the Reset-After header will + /// incur network lag. + /// + /// Regardless of this property, we still rely on the system's wall-clock + /// to determine if a bucket is rate-limited; we do not use any monotonic + /// clock. Your system will still need a stable clock. + /// + public bool UseSystemClock { get; set; } = true; /// /// Gets or sets whether or not the internal experation check uses the system date diff --git a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs index 60a7c7575..ed1fb264d 100644 --- a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs +++ b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs @@ -38,6 +38,16 @@ namespace Discord /// 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); /// + /// Sends a message to this message channel. + /// + /// The created from a . + /// The options to be used when sending the request. + /// + /// A task that represents an asynchronous send operation for delivering the message. The task result + /// contains the sent message. + /// + Task SendMessageAsync(Message message, RequestOptions options = null); + /// /// Sends a file to this message channel with an optional caption. /// /// diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs index 37342b039..c56c5c3f8 100644 --- a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs +++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs @@ -92,7 +92,7 @@ namespace Discord /// The max values of the placeholder. /// Whether or not the menu is disabled. /// The row to add the menu to. - /// + /// The current builder. public ComponentBuilder WithSelectMenu(string customId, List options, string placeholder = null, int minValues = 1, int maxValues = 1, bool disabled = false, int row = 0) { diff --git a/src/Discord.Net.Core/Entities/Messages/Message.cs b/src/Discord.Net.Core/Entities/Messages/Message.cs new file mode 100644 index 000000000..6341c54be --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/Message.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// Represents a message created by a that can be sent to a channel. + /// + public sealed class Message + { + /// + /// Gets the content of the message. + /// + public string Content { get; internal set; } + + /// + /// Gets whether or not this message should be read by a text-to-speech engine. + /// + public bool IsTTS { get; internal set; } + + /// + /// Gets a collection of embeds sent along with this message. + /// + public IReadOnlyCollection Embeds { get; internal set; } + + /// + /// Gets the allowed mentions for this message. + /// + public AllowedMentions AllowedMentions { get; internal set; } + + /// + /// Gets the message reference (reply to) for this message. + /// + public MessageReference MessageReference { get; internal set; } + + /// + /// Gets the components of this message. + /// + public MessageComponent Components { get; internal set; } + + /// + /// Gets a collection of sticker ids that will be sent with this message. + /// + public IReadOnlyCollection Stickers { get; internal set; } + + /// + /// Gets a collection of files sent with this message. + /// + public IReadOnlyCollection Attachments { get; internal set; } + + /// + /// Gets the message flags for this message. + /// + public MessageFlags Flags { get; internal set; } + + public bool HasFiles + => Attachments?.Any() ?? false; + + internal Message(string content, bool istts, IReadOnlyCollection embeds, AllowedMentions allowedMentions, + MessageReference messagereference, MessageComponent components, IReadOnlyCollection stickers, + IReadOnlyCollection attachments, MessageFlags flags) + { + Content = content; + IsTTS = istts; + Embeds = embeds; + AllowedMentions = allowedMentions; + MessageReference = messagereference; + Components = components; + Stickers = stickers; + Attachments = attachments; + Flags = flags; + } + } +} diff --git a/src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs b/src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs new file mode 100644 index 000000000..c03f38029 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Messages/MessageBuilder.cs @@ -0,0 +1,315 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Discord +{ + /// + /// Represents a generic message builder that can build s. + /// + public class MessageBuilder + { + private string _content; + private List _stickers = new(); + private List _embeds = new(); + private List _files = new(); + /// + /// Gets or sets the content of this message + /// + /// The content is bigger than the . + public string Content + { + get => _content; + set + { + if (_content?.Length > DiscordConfig.MaxMessageSize) + throw new ArgumentOutOfRangeException(nameof(value), $"Message size must be less than or equal to {DiscordConfig.MaxMessageSize} characters"); + + _content = value; + } + } + + /// + /// Gets or sets whether or not this message is TTS. + /// + public bool IsTTS { get; set; } + + /// + /// Gets or sets the embeds of this message. + /// + public List Embeds + { + get => _embeds; + set + { + if (value?.Count > DiscordConfig.MaxEmbedsPerMessage) + throw new ArgumentOutOfRangeException(nameof(value), $"Embed count must be less than or equal to {DiscordConfig.MaxEmbedsPerMessage}"); + + _embeds = value; + } + } + + /// + /// Gets or sets the allowed mentions of this message. + /// + public AllowedMentions AllowedMentions { get; set; } + + /// + /// Gets or sets the message reference (reply to) of this message. + /// + public MessageReference MessageReference { get; set; } + + /// + /// Gets or sets the components of this message. + /// + public ComponentBuilder Components { get; set; } = new(); + + /// + /// Gets or sets the stickers sent with this message. + /// + public List Stickers + { + get => _stickers; + set + { + if (value?.Count > DiscordConfig.MaxStickersPerMessage) + throw new ArgumentOutOfRangeException(nameof(value), $"Sticker count must be less than or equal to {DiscordConfig.MaxStickersPerMessage}"); + + _stickers = value; + } + } + + /// + /// Gets or sets the files sent with this message. + /// + public List Files + { + get => _files; + set + { + if(value?.Count > DiscordConfig.MaxFilesPerMessage) + throw new ArgumentOutOfRangeException(nameof(value), $"File count must be less than or equal to {DiscordConfig.MaxFilesPerMessage}"); + } + } + + /// + /// Gets or sets the message flags. + /// + public MessageFlags Flags { get; set; } + + /// + /// Sets the of this message. + /// + /// The content of the message. + /// The current builder. + public MessageBuilder WithContent(string content) + { + Content = content; + return this; + } + + /// + /// Sets the of this message. + /// + /// whether or not this message is tts. + /// The current builder. + public MessageBuilder WithTTS(bool isTTS) + { + IsTTS = isTTS; + return this; + } + + /// + /// Sets the of this message. + /// + /// The embeds to be put in this message. + /// The current builder. + /// A message can only contain a maximum of embeds. + public MessageBuilder WithEmbeds(params EmbedBuilder[] embeds) + { + Embeds = new(embeds); + return this; + } + + /// + /// Adds an embed builder to the current . + /// + /// The embed builder to add + /// The current builder. + /// A message can only contain a maximum of embeds. + public MessageBuilder AddEmbed(EmbedBuilder embed) + { + if (_embeds?.Count >= DiscordConfig.MaxEmbedsPerMessage) + throw new ArgumentOutOfRangeException(nameof(embed.Length), $"A message can only contain a maximum of {DiscordConfig.MaxEmbedsPerMessage} embeds"); + + _embeds ??= new(); + + _embeds.Add(embed); + + return this; + } + + /// + /// Sets the for this message. + /// + /// The allowed mentions for this message. + /// The current builder. + public MessageBuilder WithAllowedMentions(AllowedMentions allowedMentions) + { + AllowedMentions = allowedMentions; + return this; + } + + /// + /// Sets the for this message. + /// + /// The message reference (reply-to) for this message. + /// The current builder. + public MessageBuilder WithMessageReference(MessageReference reference) + { + MessageReference = reference; + return this; + } + + /// + /// Sets the for this current message. + /// + /// The message to set as a reference. + /// The current builder. + public MessageBuilder WithMessageReference(IMessage message) + { + if (message != null) + MessageReference = new MessageReference(message.Id, message.Channel?.Id, ((IGuildChannel)message.Channel)?.GuildId); + return this; + } + + /// + /// Sets the for this message. + /// + /// The component builder to set. + /// The current builder. + public MessageBuilder WithComponentBuilder(ComponentBuilder builder) + { + Components = builder; + return this; + } + + /// + /// Adds a button to the current . + /// + /// The button builder to add. + /// The optional row to place the button on. + /// The current builder. + public MessageBuilder WithButton(ButtonBuilder button, int row = 0) + { + Components ??= new(); + Components.WithButton(button, row); + return this; + } + + /// + /// Adds a button to the current . + /// + /// The label text for the newly added button. + /// The style of this newly added button. + /// A to be used with this button. + /// The custom id of the newly added button. + /// A URL to be used only if the is a Link. + /// Whether or not the newly created button is disabled. + /// The row the button should be placed on. + /// The current builder. + public MessageBuilder WithButton( + string label = null, + string customId = null, + ButtonStyle style = ButtonStyle.Primary, + IEmote emote = null, + string url = null, + bool disabled = false, + int row = 0) + { + Components ??= new(); + Components.WithButton(label, customId, style, emote, url, disabled, row); + return this; + } + + /// + /// Adds a select menu to the current . + /// + /// The select menu builder to add. + /// The optional row to place the select menu on. + /// The current builder. + public MessageBuilder WithSelectMenu(SelectMenuBuilder menu, int row = 0) + { + Components ??= new(); + Components.WithSelectMenu(menu, row); + return this; + } + + /// + /// Adds a select menu to the current . + /// + /// The custom id of the menu. + /// The options of the menu. + /// The placeholder of the menu. + /// The min values of the placeholder. + /// The max values of the placeholder. + /// Whether or not the menu is disabled. + /// The row to add the menu to. + /// The current builder. + public MessageBuilder WithSelectMenu(string customId, List options, + string placeholder = null, int minValues = 1, int maxValues = 1, bool disabled = false, int row = 0) + { + Components ??= new(); + Components.WithSelectMenu(customId, options, placeholder, minValues, maxValues, disabled, row); + return this; + } + + /// + /// Sets the of this message. + /// + /// The file collection to set. + /// The current builder. + public MessageBuilder WithFiles(IEnumerable files) + { + Files = new List(files); + return this; + } + + /// + /// Adds a file to the current collection . + /// + /// The file to add. + /// The current builder. + public MessageBuilder AddFile(FileAttachment file) + { + Files.Add(file); + return this; + } + + /// + /// Builds this message builder to a that can be sent across the discord api. + /// + /// A that can be sent to the discord api. + public Message Build() + { + var embeds = _embeds != null && _embeds.Count > 0 + ? _embeds.Select(x => x.Build()).ToImmutableArray() + : ImmutableArray.Empty; + + return new Message( + _content, + IsTTS, + embeds, + AllowedMentions, + MessageReference, + Components?.Build(), + _stickers, + Files?.ToImmutableArray() ?? ImmutableArray.Empty, + Flags + ); + } + } +} diff --git a/src/Discord.Net.Core/Extensions/MessageExtensions.cs b/src/Discord.Net.Core/Extensions/MessageExtensions.cs index cf330c44d..9441f280d 100644 --- a/src/Discord.Net.Core/Extensions/MessageExtensions.cs +++ b/src/Discord.Net.Core/Extensions/MessageExtensions.cs @@ -93,9 +93,29 @@ namespace Discord /// A task that represents an asynchronous send operation for delivering the message. The task result /// contains the sent message. /// - public static async Task ReplyAsync(this IUserMessage msg, string text = null, bool isTTS = false, Embed embed = null, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null) + public static Task ReplyAsync(this IUserMessage msg, string text = null, bool isTTS = false, Embed embed = null, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null) { - return await msg.Channel.SendMessageAsync(text, isTTS, embed, options, allowedMentions, new MessageReference(messageId: msg.Id), components, stickers, embeds).ConfigureAwait(false); + return msg.Channel.SendMessageAsync(text, isTTS, embed, options, allowedMentions, new MessageReference(messageId: msg.Id), components, stickers, embeds); + } + + /// + /// Sends an inline reply that references a message. + /// + /// + /// Any feild set with the will be + /// overwritten by this function. + /// + /// The message that is being replied on. + /// The created from a . + /// The options to be used when sending the request. + /// + /// A task that represents an asynchronous send operation for delivering the message. The task result + /// contains the sent message. + /// + public static Task ReplyAsync(this IUserMessage msg, Message message, RequestOptions options = null) + { + message.MessageReference = new MessageReference(messageId: msg.Id); + return msg.Channel.SendMessageAsync(message, options); } } } diff --git a/src/Discord.Net.Core/Extensions/UserExtensions.cs b/src/Discord.Net.Core/Extensions/UserExtensions.cs index ce914170d..f20f35ba4 100644 --- a/src/Discord.Net.Core/Extensions/UserExtensions.cs +++ b/src/Discord.Net.Core/Extensions/UserExtensions.cs @@ -49,6 +49,21 @@ namespace Discord return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(text, isTTS, embed, options, allowedMentions, components: components, embeds: embeds).ConfigureAwait(false); } + /// + /// Sends a message via DM. + /// + /// The user to send the DM to. + /// The created from a . + /// The options to be used when sending the request. + /// + /// A task that represents an asynchronous send operation for delivering the message. The task result + /// contains the sent message. + /// + public static async Task SendMessageAsync(this IUser user, Message message, RequestOptions options = null) + { + return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, options).ConfigureAwait(false); + } + /// /// Sends a file to this message channel with an optional caption. /// diff --git a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs index d66fd5e51..3899d82aa 100644 --- a/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs +++ b/src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs @@ -265,6 +265,20 @@ namespace Discord.Rest return builder.ToImmutable(); } + public static Task SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, Message message, RequestOptions options = null) + { + Preconditions.NotNull(message, nameof(message)); + + if (message.HasFiles) + { + return SendFilesAsync(channel, client, message.Attachments, message.Content, message.IsTTS, null, message.AllowedMentions, + message.MessageReference, message.Components, message.Stickers?.ToArray(), options, message.Embeds?.ToArray(), message.Flags); + } + else + return SendMessageAsync(channel, client, message.Content, message.IsTTS, null, message.AllowedMentions, message.MessageReference, + message.Components, message.Stickers?.ToArray(), options, message.Embeds?.ToArray(), message.Flags); + } + /// Message content is too long, length must be less or equal to . /// The only valid are and . public static async Task SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, diff --git a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs index 0cf92bb04..e68937e5a 100644 --- a/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs @@ -11,7 +11,10 @@ namespace Discord.Rest { /// 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(Message message, RequestOptions options = 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); diff --git a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs index 3bf43a594..7000645b4 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs @@ -92,6 +92,10 @@ namespace Discord.Rest public Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -271,6 +275,10 @@ namespace Discord.Rest 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); + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).ConfigureAwait(false); #endregion diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs index d21852f93..139c7d06f 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs @@ -102,6 +102,10 @@ namespace Discord.Rest public async Task ModifyMessageAsync(ulong messageId, Action func, RequestOptions options = null) => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -255,7 +259,11 @@ namespace Discord.Rest ISticker[] stickers, Embed[] embeds, MessageFlags flags) => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags).ConfigureAwait(false); - + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).ConfigureAwait(false); + #endregion #region IAudioChannel diff --git a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs index 81f21bcd7..2e2339ae6 100644 --- a/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs +++ b/src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs @@ -108,6 +108,10 @@ namespace Discord.Rest public virtual Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -393,6 +397,10 @@ namespace Discord.Rest 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); + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).ConfigureAwait(false); #endregion #region IGuildChannel diff --git a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs index 74d7953ad..f2818e5ac 100644 --- a/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs +++ b/src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs @@ -369,7 +369,7 @@ namespace Discord.Rest #endregion #region Responses - public static async Task ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action func, + public static async Task ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action func, RequestOptions options = null) { var args = new MessageProperties(); @@ -411,7 +411,7 @@ namespace Discord.Rest } public static async Task DeleteFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, RequestOptions options = null) => await client.ApiClient.DeleteInteractionFollowupMessageAsync(message.Id, message.Token, options); - public static async Task ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action func, + public static async Task ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action func, RequestOptions options = null) { var args = new MessageProperties(); diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs index 17ab4ebe3..1f0f417c8 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs @@ -137,6 +137,10 @@ namespace Discord.WebSocket public Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -310,6 +314,10 @@ namespace Discord.WebSocket 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); + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).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 4f068cf81..bf85fb27f 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs @@ -176,6 +176,10 @@ namespace Discord.WebSocket public Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -382,6 +386,10 @@ namespace Discord.WebSocket 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); + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).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 6aece7d78..f6d7adc2b 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -216,6 +216,10 @@ namespace Discord.WebSocket public virtual Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); + /// + public Task SendMessageAsync(Message message, RequestOptions options = null) + => ChannelHelper.SendMessageAsync(this, Discord, message, options); + /// /// Message content is too long, length must be less or equal to . /// The only valid are and . @@ -454,7 +458,10 @@ namespace Discord.WebSocket 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); - + + /// + async Task IMessageChannel.SendMessageAsync(Message message, RequestOptions options) + => await SendMessageAsync(message, options).ConfigureAwait(false); #endregion #region INestedChannel diff --git a/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs b/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs index 2a7f8065a..9ff0178db 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs @@ -88,5 +88,6 @@ namespace Discord 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(Message message, RequestOptions options = 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 b7f98f572..49663f071 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs @@ -115,5 +115,6 @@ namespace Discord 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(Message message, RequestOptions options = 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 ab1d3e534..b1489a8f3 100644 --- a/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs +++ b/test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs @@ -218,5 +218,6 @@ namespace Discord 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(); + public Task SendMessageAsync(Message message, RequestOptions options = null) => throw new NotImplementedException(); } }