| @@ -132,6 +132,21 @@ namespace Discord | |||
| /// </returns> | |||
| public const int MaxAuditLogEntriesPerBatch = 100; | |||
| /// <summary> | |||
| /// Returns the max number of stickers that can be sent on a message. | |||
| /// </summary> | |||
| public const int MaxStickersPerMessage = 3; | |||
| /// <summary> | |||
| /// Returns the max numbe of files that can be sent on a message. | |||
| /// </summary> | |||
| public const int MaxFilesPerMessage = 10; | |||
| /// <summary> | |||
| /// Returns the max number of embeds that can be sent on a message. | |||
| /// </summary> | |||
| public const int MaxEmbedsPerMessage = 10; | |||
| /// <summary> | |||
| /// Gets or sets how a request should act in the case of an error, by default. | |||
| /// </summary> | |||
| @@ -165,23 +180,23 @@ namespace Discord | |||
| /// </remarks> | |||
| internal bool DisplayInitialLog { get; set; } = true; | |||
| /// <summary> | |||
| /// Gets or sets whether or not rate-limits should use the system clock. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// If set to <c>false</c>, 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. | |||
| /// </remarks> | |||
| public bool UseSystemClock { get; set; } = true; | |||
| /// <summary> | |||
| /// Gets or sets whether or not rate-limits should use the system clock. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// If set to <c>false</c>, 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. | |||
| /// </remarks> | |||
| public bool UseSystemClock { get; set; } = true; | |||
| /// <summary> | |||
| /// Gets or sets whether or not the internal experation check uses the system date | |||
| @@ -38,6 +38,16 @@ namespace Discord | |||
| /// </returns> | |||
| Task<IUserMessage> 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); | |||
| /// <summary> | |||
| /// Sends a message to this message channel. | |||
| /// </summary> | |||
| /// <param name="message">The <see cref="Message"/> created from a <see cref="MessageBuilder"/>.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents an asynchronous send operation for delivering the message. The task result | |||
| /// contains the sent message. | |||
| /// </returns> | |||
| Task<IUserMessage> SendMessageAsync(Message message, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Sends a file to this message channel with an optional caption. | |||
| /// </summary> | |||
| /// <example> | |||
| @@ -92,7 +92,7 @@ namespace Discord | |||
| /// <param name="maxValues">The max values of the placeholder.</param> | |||
| /// <param name="disabled">Whether or not the menu is disabled.</param> | |||
| /// <param name="row">The row to add the menu to.</param> | |||
| /// <returns></returns> | |||
| /// <returns>The current builder.</returns> | |||
| public ComponentBuilder WithSelectMenu(string customId, List<SelectMenuOptionBuilder> options, | |||
| string placeholder = null, int minValues = 1, int maxValues = 1, bool disabled = false, int row = 0) | |||
| { | |||
| @@ -0,0 +1,77 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| /// <summary> | |||
| /// Represents a message created by a <see cref="MessageBuilder"/> that can be sent to a channel. | |||
| /// </summary> | |||
| public sealed class Message | |||
| { | |||
| /// <summary> | |||
| /// Gets the content of the message. | |||
| /// </summary> | |||
| public string Content { get; internal set; } | |||
| /// <summary> | |||
| /// Gets whether or not this message should be read by a text-to-speech engine. | |||
| /// </summary> | |||
| public bool IsTTS { get; internal set; } | |||
| /// <summary> | |||
| /// Gets a collection of embeds sent along with this message. | |||
| /// </summary> | |||
| public IReadOnlyCollection<Embed> Embeds { get; internal set; } | |||
| /// <summary> | |||
| /// Gets the allowed mentions for this message. | |||
| /// </summary> | |||
| public AllowedMentions AllowedMentions { get; internal set; } | |||
| /// <summary> | |||
| /// Gets the message reference (reply to) for this message. | |||
| /// </summary> | |||
| public MessageReference MessageReference { get; internal set; } | |||
| /// <summary> | |||
| /// Gets the components of this message. | |||
| /// </summary> | |||
| public MessageComponent Components { get; internal set; } | |||
| /// <summary> | |||
| /// Gets a collection of sticker ids that will be sent with this message. | |||
| /// </summary> | |||
| public IReadOnlyCollection<ISticker> Stickers { get; internal set; } | |||
| /// <summary> | |||
| /// Gets a collection of files sent with this message. | |||
| /// </summary> | |||
| public IReadOnlyCollection<FileAttachment> Attachments { get; internal set; } | |||
| /// <summary> | |||
| /// Gets the message flags for this message. | |||
| /// </summary> | |||
| public MessageFlags Flags { get; internal set; } | |||
| public bool HasFiles | |||
| => Attachments?.Any() ?? false; | |||
| internal Message(string content, bool istts, IReadOnlyCollection<Embed> embeds, AllowedMentions allowedMentions, | |||
| MessageReference messagereference, MessageComponent components, IReadOnlyCollection<ISticker> stickers, | |||
| IReadOnlyCollection<FileAttachment> attachments, MessageFlags flags) | |||
| { | |||
| Content = content; | |||
| IsTTS = istts; | |||
| Embeds = embeds; | |||
| AllowedMentions = allowedMentions; | |||
| MessageReference = messagereference; | |||
| Components = components; | |||
| Stickers = stickers; | |||
| Attachments = attachments; | |||
| Flags = flags; | |||
| } | |||
| } | |||
| } | |||
| @@ -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 | |||
| { | |||
| /// <summary> | |||
| /// Represents a generic message builder that can build <see cref="Message"/>s. | |||
| /// </summary> | |||
| public class MessageBuilder | |||
| { | |||
| private string _content; | |||
| private List<ISticker> _stickers = new(); | |||
| private List<EmbedBuilder> _embeds = new(); | |||
| private List<FileAttachment> _files = new(); | |||
| /// <summary> | |||
| /// Gets or sets the content of this message | |||
| /// </summary> | |||
| /// <exception cref="ArgumentOutOfRangeException">The content is bigger than the <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| 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; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets whether or not this message is TTS. | |||
| /// </summary> | |||
| public bool IsTTS { get; set; } | |||
| /// <summary> | |||
| /// Gets or sets the embeds of this message. | |||
| /// </summary> | |||
| public List<EmbedBuilder> 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; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the allowed mentions of this message. | |||
| /// </summary> | |||
| public AllowedMentions AllowedMentions { get; set; } | |||
| /// <summary> | |||
| /// Gets or sets the message reference (reply to) of this message. | |||
| /// </summary> | |||
| public MessageReference MessageReference { get; set; } | |||
| /// <summary> | |||
| /// Gets or sets the components of this message. | |||
| /// </summary> | |||
| public ComponentBuilder Components { get; set; } = new(); | |||
| /// <summary> | |||
| /// Gets or sets the stickers sent with this message. | |||
| /// </summary> | |||
| public List<ISticker> 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; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the files sent with this message. | |||
| /// </summary> | |||
| public List<FileAttachment> 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}"); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Gets or sets the message flags. | |||
| /// </summary> | |||
| public MessageFlags Flags { get; set; } | |||
| /// <summary> | |||
| /// Sets the <see cref="Content"/> of this message. | |||
| /// </summary> | |||
| /// <param name="content">The content of the message.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithContent(string content) | |||
| { | |||
| Content = content; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="IsTTS"/> of this message. | |||
| /// </summary> | |||
| /// <param name="isTTS">whether or not this message is tts.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithTTS(bool isTTS) | |||
| { | |||
| IsTTS = isTTS; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="Embeds"/> of this message. | |||
| /// </summary> | |||
| /// <param name="embeds">The embeds to be put in this message.</param> | |||
| /// <returns>The current builder.</returns> | |||
| /// <exception cref="ArgumentOutOfRangeException">A message can only contain a maximum of <see cref="DiscordConfig.MaxEmbedsPerMessage"/> embeds.</exception> | |||
| public MessageBuilder WithEmbeds(params EmbedBuilder[] embeds) | |||
| { | |||
| Embeds = new(embeds); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Adds an embed builder to the current <see cref="Embeds"/>. | |||
| /// </summary> | |||
| /// <param name="embed">The embed builder to add</param> | |||
| /// <returns>The current builder.</returns> | |||
| /// <exception cref="ArgumentOutOfRangeException">A message can only contain a maximum of <see cref="DiscordConfig.MaxEmbedsPerMessage"/> embeds.</exception> | |||
| 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; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="AllowedMentions"/> for this message. | |||
| /// </summary> | |||
| /// <param name="allowedMentions">The allowed mentions for this message.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithAllowedMentions(AllowedMentions allowedMentions) | |||
| { | |||
| AllowedMentions = allowedMentions; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="MessageReference"/> for this message. | |||
| /// </summary> | |||
| /// <param name="reference">The message reference (reply-to) for this message.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithMessageReference(MessageReference reference) | |||
| { | |||
| MessageReference = reference; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="MessageReference"/> for this current message. | |||
| /// </summary> | |||
| /// <param name="message">The message to set as a reference.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithMessageReference(IMessage message) | |||
| { | |||
| if (message != null) | |||
| MessageReference = new MessageReference(message.Id, message.Channel?.Id, ((IGuildChannel)message.Channel)?.GuildId); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="Components"/> for this message. | |||
| /// </summary> | |||
| /// <param name="builder">The component builder to set.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithComponentBuilder(ComponentBuilder builder) | |||
| { | |||
| Components = builder; | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Adds a button to the current <see cref="Components"/>. | |||
| /// </summary> | |||
| /// <param name="button">The button builder to add.</param> | |||
| /// <param name="row">The optional row to place the button on.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithButton(ButtonBuilder button, int row = 0) | |||
| { | |||
| Components ??= new(); | |||
| Components.WithButton(button, row); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Adds a button to the current <see cref="Components"/>. | |||
| /// </summary> | |||
| /// <param name="label">The label text for the newly added button.</param> | |||
| /// <param name="style">The style of this newly added button.</param> | |||
| /// <param name="emote">A <see cref="IEmote"/> to be used with this button.</param> | |||
| /// <param name="customId">The custom id of the newly added button.</param> | |||
| /// <param name="url">A URL to be used only if the <see cref="ButtonStyle"/> is a Link.</param> | |||
| /// <param name="disabled">Whether or not the newly created button is disabled.</param> | |||
| /// <param name="row">The row the button should be placed on.</param> | |||
| /// <returns>The current builder.</returns> | |||
| 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; | |||
| } | |||
| /// <summary> | |||
| /// Adds a select menu to the current <see cref="Components"/>. | |||
| /// </summary> | |||
| /// <param name="menu">The select menu builder to add.</param> | |||
| /// <param name="row">The optional row to place the select menu on.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithSelectMenu(SelectMenuBuilder menu, int row = 0) | |||
| { | |||
| Components ??= new(); | |||
| Components.WithSelectMenu(menu, row); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Adds a select menu to the current <see cref="Components"/>. | |||
| /// </summary> | |||
| /// <param name="customId">The custom id of the menu.</param> | |||
| /// <param name="options">The options of the menu.</param> | |||
| /// <param name="placeholder">The placeholder of the menu.</param> | |||
| /// <param name="minValues">The min values of the placeholder.</param> | |||
| /// <param name="maxValues">The max values of the placeholder.</param> | |||
| /// <param name="disabled">Whether or not the menu is disabled.</param> | |||
| /// <param name="row">The row to add the menu to.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithSelectMenu(string customId, List<SelectMenuOptionBuilder> 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; | |||
| } | |||
| /// <summary> | |||
| /// Sets the <see cref="Files"/> of this message. | |||
| /// </summary> | |||
| /// <param name="files">The file collection to set.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder WithFiles(IEnumerable<FileAttachment> files) | |||
| { | |||
| Files = new List<FileAttachment>(files); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Adds a file to the current collection <see cref="Files"/>. | |||
| /// </summary> | |||
| /// <param name="file">The file to add.</param> | |||
| /// <returns>The current builder.</returns> | |||
| public MessageBuilder AddFile(FileAttachment file) | |||
| { | |||
| Files.Add(file); | |||
| return this; | |||
| } | |||
| /// <summary> | |||
| /// Builds this message builder to a <see cref="Message"/> that can be sent across the discord api. | |||
| /// </summary> | |||
| /// <returns>A <see cref="Message"/> that can be sent to the discord api.</returns> | |||
| public Message Build() | |||
| { | |||
| var embeds = _embeds != null && _embeds.Count > 0 | |||
| ? _embeds.Select(x => x.Build()).ToImmutableArray() | |||
| : ImmutableArray<Embed>.Empty; | |||
| return new Message( | |||
| _content, | |||
| IsTTS, | |||
| embeds, | |||
| AllowedMentions, | |||
| MessageReference, | |||
| Components?.Build(), | |||
| _stickers, | |||
| Files?.ToImmutableArray() ?? ImmutableArray<FileAttachment>.Empty, | |||
| Flags | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| @@ -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. | |||
| /// </returns> | |||
| public static async Task<IUserMessage> 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<IUserMessage> 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); | |||
| } | |||
| /// <summary> | |||
| /// Sends an inline reply that references a message. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Any feild set with the <see cref="MessageBuilder.WithMessageReference(IMessage)"/> will be | |||
| /// overwritten by this function. | |||
| /// </remarks> | |||
| /// <param name="msg">The message that is being replied on.</param> | |||
| /// <param name="message">The <see cref="Message"/> created from a <see cref="MessageBuilder"/>.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents an asynchronous send operation for delivering the message. The task result | |||
| /// contains the sent message. | |||
| /// </returns> | |||
| public static Task<IUserMessage> ReplyAsync(this IUserMessage msg, Message message, RequestOptions options = null) | |||
| { | |||
| message.MessageReference = new MessageReference(messageId: msg.Id); | |||
| return msg.Channel.SendMessageAsync(message, options); | |||
| } | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| /// <summary> | |||
| /// Sends a message via DM. | |||
| /// </summary> | |||
| /// <param name="user">The user to send the DM to.</param> | |||
| /// <param name="message">The <see cref="Message"/> created from a <see cref="MessageBuilder"/>.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents an asynchronous send operation for delivering the message. The task result | |||
| /// contains the sent message. | |||
| /// </returns> | |||
| public static async Task<IUserMessage> SendMessageAsync(this IUser user, Message message, RequestOptions options = null) | |||
| { | |||
| return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, options).ConfigureAwait(false); | |||
| } | |||
| /// <summary> | |||
| /// Sends a file to this message channel with an optional caption. | |||
| /// </summary> | |||
| @@ -265,6 +265,20 @@ namespace Discord.Rest | |||
| return builder.ToImmutable(); | |||
| } | |||
| public static Task<RestUserMessage> 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); | |||
| } | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| public static async Task<RestUserMessage> SendMessageAsync(IMessageChannel channel, BaseDiscordClient client, | |||
| @@ -11,7 +11,10 @@ namespace Discord.Rest | |||
| { | |||
| /// <inheritdoc cref="IMessageChannel.SendMessageAsync(string, bool, Embed, RequestOptions, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/> | |||
| new Task<RestUserMessage> 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); | |||
| /// <inheritdoc cref="IMessageChannel.SendMessageAsync(Message, RequestOptions)"/> | |||
| new Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null); | |||
| /// <inheritdoc cref="IMessageChannel.SendFileAsync(string, string, bool, Embed, RequestOptions, bool, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags)"/> | |||
| new Task<RestUserMessage> 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); | |||
| @@ -92,6 +92,10 @@ namespace Discord.Rest | |||
| public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| @@ -102,6 +102,10 @@ namespace Discord.Rest | |||
| public async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null) | |||
| => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| #region IAudioChannel | |||
| @@ -101,6 +101,10 @@ namespace Discord.Rest | |||
| public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -386,6 +390,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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| #region IGuildChannel | |||
| @@ -352,7 +352,7 @@ namespace Discord.Rest | |||
| #endregion | |||
| #region Responses | |||
| public static async Task<Message> ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func, | |||
| public static async Task<API.Message> ModifyFollowupMessageAsync(BaseDiscordClient client, RestFollowupMessage message, Action<MessageProperties> func, | |||
| RequestOptions options = null) | |||
| { | |||
| var args = new MessageProperties(); | |||
| @@ -394,7 +394,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<Message> ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action<MessageProperties> func, | |||
| public static async Task<API.Message> ModifyInteractionResponseAsync(BaseDiscordClient client, string token, Action<MessageProperties> func, | |||
| RequestOptions options = null) | |||
| { | |||
| var args = new MessageProperties(); | |||
| @@ -137,6 +137,10 @@ namespace Discord.WebSocket | |||
| public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| #region IChannel | |||
| @@ -176,6 +176,10 @@ namespace Discord.WebSocket | |||
| public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| #region IAudioChannel | |||
| @@ -210,6 +210,10 @@ namespace Discord.WebSocket | |||
| public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null) | |||
| => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); | |||
| /// <inheritdoc/> | |||
| public Task<RestUserMessage> SendMessageAsync(Message message, RequestOptions options = null) | |||
| => ChannelHelper.SendMessageAsync(this, Discord, message, options); | |||
| /// <inheritdoc /> | |||
| /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> | |||
| /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> | |||
| @@ -448,7 +452,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); | |||
| /// <inheritdoc /> | |||
| async Task<IUserMessage> IMessageChannel.SendMessageAsync(Message message, RequestOptions options) | |||
| => await SendMessageAsync(message, options).ConfigureAwait(false); | |||
| #endregion | |||
| #region INestedChannel | |||
| @@ -88,5 +88,6 @@ namespace Discord | |||
| public Task<IUserMessage> 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<IUserMessage> 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<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> 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<IUserMessage> SendMessageAsync(Message message, RequestOptions options = null) => throw new NotImplementedException(); | |||
| } | |||
| } | |||
| @@ -115,5 +115,6 @@ namespace Discord | |||
| public Task<IUserMessage> 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<IUserMessage> SendFilesAsync(IEnumerable<FileAttachment> 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<IUserMessage> SendMessageAsync(Message message, RequestOptions options = null) => throw new NotImplementedException(); | |||
| } | |||
| } | |||
| @@ -216,5 +216,6 @@ namespace Discord | |||
| public Task<IThreadChannel> 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<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null) => throw new NotImplementedException(); | |||
| public Task<IThreadChannel> 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<IUserMessage> SendMessageAsync(Message message, RequestOptions options = null) => throw new NotImplementedException(); | |||
| } | |||
| } | |||