[Feature] Components V2 (#3065)
* oh well. at least it runs * well that's some breakings * all the models (i think) * barebones builder impl * commit * initial take on `WithX` component builder design * actually usable stuff now * few more changes * fixes, changes, syntax sugar * rework message flags + auto add `ComponentsV2` * apparently it's also nullable * fix build * webhook component supports + builder validations + some xmldoc * `ResolvedUnfurledMediaItem` + fix missing accessory on sections * missing xmldoc * fix modal + whatever change * yeet unused dep
This commit is contained in:
@@ -132,7 +132,7 @@ namespace Discord
|
||||
/// A task that represents an asynchronous send operation for delivering the message.
|
||||
/// </returns>
|
||||
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);
|
||||
MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a file attachment.
|
||||
@@ -154,7 +154,8 @@ namespace Discord
|
||||
/// </returns>
|
||||
#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, PollProperties poll = null)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(fileStream, fileName))
|
||||
{
|
||||
@@ -163,7 +164,8 @@ 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, PollProperties poll = null);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null
|
||||
, MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a file attachment.
|
||||
@@ -185,7 +187,8 @@ namespace Discord
|
||||
/// </returns>
|
||||
#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, PollProperties poll = null)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(filePath, fileName))
|
||||
{
|
||||
@@ -194,7 +197,8 @@ 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, PollProperties poll = null);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a file attachment.
|
||||
@@ -215,11 +219,13 @@ namespace Discord
|
||||
/// </returns>
|
||||
#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, PollProperties poll = null)
|
||||
=> RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
=> RespondWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
#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, PollProperties poll = null);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a collection of file attachments.
|
||||
@@ -239,7 +245,9 @@ namespace Discord
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task RespondWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
/// </summary>
|
||||
@@ -257,7 +265,9 @@ namespace Discord
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
/// </summary>
|
||||
@@ -278,17 +288,19 @@ namespace Discord
|
||||
/// </returns>
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
async Task<IUserMessage> 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)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(fileStream, fileName))
|
||||
{
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Task<IUserMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
/// </summary>
|
||||
@@ -309,16 +321,17 @@ namespace Discord
|
||||
/// </returns>
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
async Task<IUserMessage> 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)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(filePath, fileName))
|
||||
{
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Task<IUserMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -339,11 +352,11 @@ namespace Discord
|
||||
/// </returns>
|
||||
#if NETCOREAPP3_0_OR_GREATER
|
||||
Task<IUserMessage> 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)
|
||||
=> FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
#else
|
||||
Task<IUserMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -363,7 +376,7 @@ namespace Discord
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
Task<IUserMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
/// <summary>
|
||||
/// Gets the original response for this interaction.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> Row for child components to live in.
|
||||
/// </summary>
|
||||
public class ActionRowComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.ActionRow;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> Row for child components to live in.
|
||||
/// Gets the child components in this row.
|
||||
/// </summary>
|
||||
public class ActionRowComponent : IMessageComponent
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; internal set; }
|
||||
|
||||
internal ActionRowComponent() { }
|
||||
|
||||
internal ActionRowComponent(IReadOnlyCollection<IMessageComponent> components)
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.ActionRow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child components in this row.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; internal set; }
|
||||
|
||||
internal ActionRowComponent() { }
|
||||
|
||||
internal ActionRowComponent(List<IMessageComponent> components)
|
||||
{
|
||||
Components = components;
|
||||
}
|
||||
|
||||
string IMessageComponent.CustomId => null;
|
||||
Components = components;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ namespace Discord;
|
||||
/// <summary>
|
||||
/// Represents a class used to build Action rows.
|
||||
/// </summary>
|
||||
public class ActionRowBuilder
|
||||
public class ActionRowBuilder : IMessageComponentBuilder, IInteractableComponentContainer
|
||||
{
|
||||
public ComponentType Type => ComponentType.ActionRow;
|
||||
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The max amount of child components this row can hold.
|
||||
/// </summary>
|
||||
@@ -20,7 +24,7 @@ public class ActionRowBuilder
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentNullException" accessor="set"><see cref="Components"/> cannot be null.</exception>
|
||||
/// <exception cref="ArgumentException" accessor="set"><see cref="Components"/> count exceeds <see cref="MaxChildCount"/>.</exception>
|
||||
public List<IMessageComponent> Components
|
||||
public List<IMessageComponentBuilder> Components
|
||||
{
|
||||
get => _components;
|
||||
set
|
||||
@@ -37,7 +41,21 @@ public class ActionRowBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private List<IMessageComponent> _components = new List<IMessageComponent>();
|
||||
|
||||
public ActionRowBuilder AddComponents(params IMessageComponentBuilder[] components)
|
||||
{
|
||||
foreach (var component in components)
|
||||
AddComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionRowBuilder WithComponents(IEnumerable<IMessageComponentBuilder> components)
|
||||
{
|
||||
Components = components.ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
private List<IMessageComponentBuilder> _components = new ();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a list of components to the current row.
|
||||
@@ -45,7 +63,7 @@ public class ActionRowBuilder
|
||||
/// <param name="components">The list of components to add.</param>
|
||||
/// <inheritdoc cref="Components"/>
|
||||
/// <returns>The current builder.</returns>
|
||||
public ActionRowBuilder WithComponents(List<IMessageComponent> components)
|
||||
public ActionRowBuilder WithComponents(List<IMessageComponentBuilder> components)
|
||||
{
|
||||
Components = components;
|
||||
return this;
|
||||
@@ -57,7 +75,7 @@ public class ActionRowBuilder
|
||||
/// <param name="component">The component to add.</param>
|
||||
/// <exception cref="InvalidOperationException">Components count reached <see cref="MaxChildCount"/></exception>
|
||||
/// <returns>The current builder.</returns>
|
||||
public ActionRowBuilder AddComponent(IMessageComponent component)
|
||||
public ActionRowBuilder AddComponent(IMessageComponentBuilder component)
|
||||
{
|
||||
if (Components.Count >= MaxChildCount)
|
||||
throw new InvalidOperationException($"Components count reached {MaxChildCount}");
|
||||
@@ -103,13 +121,11 @@ public class ActionRowBuilder
|
||||
{
|
||||
if (menu.Options is not null && menu.Options.Distinct().Count() != menu.Options.Count)
|
||||
throw new InvalidOperationException("Please make sure that there is no duplicates values.");
|
||||
|
||||
var builtMenu = menu.Build();
|
||||
|
||||
|
||||
if (Components.Count != 0)
|
||||
throw new InvalidOperationException($"A Select Menu cannot exist in a pre-occupied ActionRow.");
|
||||
|
||||
AddComponent(builtMenu);
|
||||
AddComponent(menu);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -152,15 +168,13 @@ public class ActionRowBuilder
|
||||
/// <returns>The current builder.</returns>
|
||||
public ActionRowBuilder WithButton(ButtonBuilder button)
|
||||
{
|
||||
var builtButton = button.Build();
|
||||
|
||||
if (Components.Count >= 5)
|
||||
throw new InvalidOperationException($"Components count reached {MaxChildCount}");
|
||||
|
||||
if (Components.Any(x => x.Type.IsSelectType()))
|
||||
throw new InvalidOperationException($"A button cannot be added to a row with a SelectMenu");
|
||||
|
||||
AddComponent(builtButton);
|
||||
AddComponent(button);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -171,10 +185,11 @@ public class ActionRowBuilder
|
||||
/// <returns>A <see cref="ActionRowComponent"/> that can be used within a <see cref="ComponentBuilder"/></returns>
|
||||
public ActionRowComponent Build()
|
||||
{
|
||||
return new ActionRowComponent(_components);
|
||||
return new ActionRowComponent(_components.Select(x => x.Build()).ToList());
|
||||
}
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
|
||||
internal bool CanTakeComponent(IMessageComponent component)
|
||||
internal bool CanTakeComponent(IMessageComponentBuilder component)
|
||||
{
|
||||
switch (component.Type)
|
||||
{
|
||||
@@ -195,4 +210,11 @@ public class ActionRowBuilder
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component);
|
||||
|
||||
IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components);
|
||||
|
||||
IComponentContainer IComponentContainer.WithComponents(IEnumerable<IMessageComponentBuilder> components) => WithComponents(components);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ namespace Discord;
|
||||
/// <summary>
|
||||
/// Represents a class used to build <see cref="ButtonComponent"/>'s.
|
||||
/// </summary>
|
||||
public class ButtonBuilder
|
||||
public class ButtonBuilder : IInteractableComponentBuilder
|
||||
{
|
||||
public ComponentType Type => ComponentType.Button;
|
||||
|
||||
/// <summary>
|
||||
/// The max length of a <see cref="ButtonComponent.Label"/>.
|
||||
/// </summary>
|
||||
@@ -74,6 +76,8 @@ public class ButtonBuilder
|
||||
/// </remarks>
|
||||
public ulong? SkuId { get; set; }
|
||||
|
||||
public int? Id { get; set; }
|
||||
|
||||
private string _label;
|
||||
private string _customId;
|
||||
|
||||
@@ -92,7 +96,7 @@ public class ButtonBuilder
|
||||
/// <param name="emote">The emote of this button.</param>
|
||||
/// <param name="isDisabled">Disabled this button or not.</param>
|
||||
/// <param name="skuId">The sku id of this button.</param>
|
||||
public ButtonBuilder(string label = null, string customId = null, ButtonStyle style = ButtonStyle.Primary, string url = null, IEmote emote = null, bool isDisabled = false, ulong? skuId = null)
|
||||
public ButtonBuilder(string label = null, string customId = null, ButtonStyle style = ButtonStyle.Primary, string url = null, IEmote emote = null, bool isDisabled = false, ulong? skuId = null, int? id = null)
|
||||
{
|
||||
CustomId = customId;
|
||||
Style = style;
|
||||
@@ -101,6 +105,7 @@ public class ButtonBuilder
|
||||
IsDisabled = isDisabled;
|
||||
Emote = emote;
|
||||
SkuId = skuId;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,6 +120,7 @@ public class ButtonBuilder
|
||||
IsDisabled = button.IsDisabled;
|
||||
Emote = button.Emote;
|
||||
SkuId = button.SkuId;
|
||||
Id = button.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -315,6 +321,8 @@ public class ButtonBuilder
|
||||
break;
|
||||
}
|
||||
|
||||
return new ButtonComponent(Style, Label, Emote, CustomId, Url, IsDisabled, SkuId);
|
||||
return new ButtonComponent(Style, Label, Emote, CustomId, Url, IsDisabled, SkuId, Id);
|
||||
}
|
||||
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class ComponentBuilder
|
||||
/// <returns>The current builder.</returns>
|
||||
public ComponentBuilder RemoveComponent(string customId)
|
||||
{
|
||||
this.ActionRows.ForEach(ar => ar.Components.RemoveAll(c => c.CustomId == customId));
|
||||
this.ActionRows.ForEach(ar => ar.Components.RemoveAll(c => c is IInteractableComponent i && i.CustomId == customId));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -158,20 +158,15 @@ public class ComponentBuilder
|
||||
Preconditions.LessThan(row, MaxActionRowCount, nameof(row));
|
||||
if (menu.Options is not null && menu.Options.Distinct().Count() != menu.Options.Count)
|
||||
throw new InvalidOperationException("Please make sure that there is no duplicates values.");
|
||||
|
||||
var builtMenu = menu.Build();
|
||||
|
||||
|
||||
if (_actionRows == null)
|
||||
{
|
||||
_actionRows = new List<ActionRowBuilder>
|
||||
{
|
||||
new ActionRowBuilder().AddComponent(builtMenu)
|
||||
};
|
||||
_actionRows = [new ActionRowBuilder().AddComponent(menu)];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_actionRows.Count == row)
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(builtMenu));
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(menu));
|
||||
else
|
||||
{
|
||||
ActionRowBuilder actionRow;
|
||||
@@ -183,12 +178,12 @@ public class ComponentBuilder
|
||||
_actionRows.Add(actionRow);
|
||||
}
|
||||
|
||||
if (actionRow.CanTakeComponent(builtMenu))
|
||||
actionRow.AddComponent(builtMenu);
|
||||
if (actionRow.CanTakeComponent(menu))
|
||||
actionRow.AddComponent(menu);
|
||||
else if (row < MaxActionRowCount)
|
||||
WithSelectMenu(menu, row + 1);
|
||||
else
|
||||
throw new InvalidOperationException($"There is no more row to add a {nameof(builtMenu)}");
|
||||
throw new InvalidOperationException($"There is no more row to add a {nameof(menu)}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,19 +238,17 @@ public class ComponentBuilder
|
||||
{
|
||||
Preconditions.LessThan(row, MaxActionRowCount, nameof(row));
|
||||
|
||||
var builtButton = button.Build();
|
||||
|
||||
if (_actionRows == null)
|
||||
{
|
||||
_actionRows = new List<ActionRowBuilder>
|
||||
{
|
||||
new ActionRowBuilder().AddComponent(builtButton)
|
||||
new ActionRowBuilder().AddComponent(button)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_actionRows.Count == row)
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(builtButton));
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(button));
|
||||
else
|
||||
{
|
||||
ActionRowBuilder actionRow;
|
||||
@@ -267,8 +260,8 @@ public class ComponentBuilder
|
||||
_actionRows.Add(actionRow);
|
||||
}
|
||||
|
||||
if (actionRow.CanTakeComponent(builtButton))
|
||||
actionRow.AddComponent(builtButton);
|
||||
if (actionRow.CanTakeComponent(button))
|
||||
actionRow.AddComponent(button);
|
||||
else if (row < MaxActionRowCount)
|
||||
WithButton(button, row + 1);
|
||||
else
|
||||
@@ -326,7 +319,7 @@ public class ComponentBuilder
|
||||
_actionRows.RemoveAt(i);
|
||||
|
||||
return _actionRows != null
|
||||
? new MessageComponent(_actionRows.Select(x => x.Build()).ToList())
|
||||
? new MessageComponent(_actionRows.Select(x => x.Build()).OfType<IMessageComponent>().ToList())
|
||||
: MessageComponent.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Discord;
|
||||
|
||||
public static class ComponentBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the custom id for the component.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public static BuilderT WithId<BuilderT>(this BuilderT builder, int? id)
|
||||
where BuilderT : IMessageComponentBuilder
|
||||
{
|
||||
builder.Id = id;
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class ComponentBuilderV2 : IStaticComponentContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the maximum number of components that can be added to this container.
|
||||
/// </summary>
|
||||
public const int MaxComponents = 10;
|
||||
|
||||
private List<IMessageComponentBuilder> _components = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<IMessageComponentBuilder> Components
|
||||
{
|
||||
get => _components;
|
||||
set
|
||||
{
|
||||
_components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ComponentBuilderV2"/>.
|
||||
/// </summary>
|
||||
public ComponentBuilderV2() { }
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponent"/>
|
||||
public ComponentBuilderV2 AddComponent(IMessageComponentBuilder component)
|
||||
{
|
||||
Components.Add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponents"/>
|
||||
public ComponentBuilderV2 AddComponents(params IMessageComponentBuilder[] components)
|
||||
{
|
||||
foreach (var component in components)
|
||||
Components.Add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.WithComponents"/>
|
||||
public ComponentBuilderV2 WithComponents(IEnumerable<IMessageComponentBuilder> components)
|
||||
{
|
||||
Components = components.ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build" />
|
||||
public MessageComponent Build()
|
||||
{
|
||||
if (_components.Count is 0 or >MaxComponents)
|
||||
throw new InvalidOperationException($"The number of components must be between 1 and {MaxComponents}.");
|
||||
|
||||
if (_components.Any(x =>
|
||||
x is not ActionRowBuilder
|
||||
and not SectionBuilder
|
||||
and not TextDisplayBuilder
|
||||
and not MediaGalleryBuilder
|
||||
and not FileComponentBuilder
|
||||
and not SeparatorBuilder
|
||||
and not ContainerBuilder))
|
||||
throw new InvalidOperationException($"Only the following components can be at the top level: {nameof(ActionRowBuilder)}, {nameof(TextDisplayBuilder)}, {nameof(SectionBuilder)}, {nameof(MediaGalleryBuilder)}, {nameof(SeparatorBuilder)}, or {nameof(FileComponentBuilder)} components.");
|
||||
|
||||
return new MessageComponent(Components.Select(x => x.Build()).ToList());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component);
|
||||
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components);
|
||||
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.WithComponents(IEnumerable<IMessageComponentBuilder> components) => WithComponents(components);
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public static class ComponentContainerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a <see cref="TextDisplayBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithTextDisplay<BuilderT>(this BuilderT container, TextDisplayBuilder textDisplay)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(textDisplay);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="TextDisplayBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithTextDisplay<BuilderT>(this BuilderT container,
|
||||
string content,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithTextDisplay(new TextDisplayBuilder()
|
||||
.WithContent(content)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SectionBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSection<BuilderT>(this BuilderT container, SectionBuilder section)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(section);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SectionBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSection<BuilderT>(this BuilderT container,
|
||||
IEnumerable<TextDisplayBuilder> components,
|
||||
IMessageComponentBuilder accessory,
|
||||
bool isSpoiler = false,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithSection(new SectionBuilder()
|
||||
.WithComponents(components)
|
||||
.WithAccessory(accessory)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="MediaGalleryBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithMediaGallery<BuilderT>(this BuilderT container, MediaGalleryBuilder mediaGallery)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(mediaGallery);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="MediaGalleryBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithMediaGallery<BuilderT>(this BuilderT container,
|
||||
IEnumerable<MediaGalleryItemProperties> items,
|
||||
int? id = null) where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithMediaGallery(new MediaGalleryBuilder()
|
||||
.WithItems(items)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="MediaGalleryBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithMediaGallery<BuilderT>(this BuilderT container,
|
||||
IEnumerable<string> urls,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithMediaGallery(new MediaGalleryBuilder()
|
||||
.WithItems(urls.Select(x => new MediaGalleryItemProperties(new UnfurledMediaItemProperties(x))))
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SeparatorBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSeparator<BuilderT>(this BuilderT container, SeparatorBuilder separator)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(separator);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SeparatorBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSeparator<BuilderT>(this BuilderT container,
|
||||
SeparatorSpacingSize spacing = SeparatorSpacingSize.Small,
|
||||
bool isDivider = true,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithSeparator(new SeparatorBuilder()
|
||||
.WithSpacing(spacing)
|
||||
.WithIsDivider(isDivider)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="FileComponentBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithFile<BuilderT>(this BuilderT container, FileComponentBuilder file)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(file);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="FileComponentBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithFile<BuilderT>(this BuilderT container,
|
||||
UnfurledMediaItemProperties file,
|
||||
bool isSpoiler = false,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithFile(new FileComponentBuilder()
|
||||
.WithFile(file)
|
||||
.WithIsSpoiler(isSpoiler)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ContainerBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithContainer<BuilderT>(this BuilderT container, ContainerBuilder containerComponent)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(containerComponent);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ContainerBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithContainer<BuilderT>(this BuilderT container,
|
||||
IEnumerable<IMessageComponentBuilder> components,
|
||||
Color? accentColor = null,
|
||||
bool isSpoiler = false,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithContainer(new ContainerBuilder()
|
||||
.WithComponents(components)
|
||||
.WithAccentColor(accentColor)
|
||||
.WithSpoiler(isSpoiler)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ContainerBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithContainer<BuilderT>(this BuilderT container,
|
||||
params IMessageComponentBuilder[] components)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithContainer(new ContainerBuilder()
|
||||
.WithComponents(components));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ButtonBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithButton<BuilderT>(this BuilderT container, ButtonBuilder button)
|
||||
where BuilderT : class, IInteractableComponentContainer
|
||||
{
|
||||
container.AddComponent(button);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ButtonBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithButton<BuilderT>(this BuilderT container,
|
||||
string label = null,
|
||||
string customId = null,
|
||||
ButtonStyle style = ButtonStyle.Primary,
|
||||
IEmote emote = null,
|
||||
string url = null,
|
||||
bool disabled = false,
|
||||
ulong? skuId = null,
|
||||
int? id = null)
|
||||
where BuilderT : class, IInteractableComponentContainer
|
||||
=> container.WithButton(new ButtonBuilder()
|
||||
.WithLabel(label)
|
||||
.WithStyle(style)
|
||||
.WithEmote(emote)
|
||||
.WithCustomId(customId)
|
||||
.WithUrl(url)
|
||||
.WithDisabled(disabled)
|
||||
.WithSkuId(skuId)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SelectMenuBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSelectMenu<BuilderT>(this BuilderT container, SelectMenuBuilder selectMenu)
|
||||
where BuilderT : class, IInteractableComponentContainer
|
||||
{
|
||||
container.AddComponent(selectMenu);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="SelectMenuBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithSelectMenu<BuilderT>(this BuilderT container,
|
||||
string customId,
|
||||
List<SelectMenuOptionBuilder> options = null,
|
||||
string placeholder = null,
|
||||
int minValues = 1,
|
||||
int maxValues = 1,
|
||||
bool disabled = false,
|
||||
int row = 0,
|
||||
ComponentType type = ComponentType.SelectMenu,
|
||||
ChannelType[] channelTypes = null,
|
||||
SelectMenuDefaultValue[] defaultValues = null,
|
||||
int? id = null)
|
||||
where BuilderT : class, IInteractableComponentContainer
|
||||
=> container.WithSelectMenu(new SelectMenuBuilder()
|
||||
.WithCustomId(customId)
|
||||
.WithOptions(options)
|
||||
.WithPlaceholder(placeholder)
|
||||
.WithMaxValues(maxValues)
|
||||
.WithMinValues(minValues)
|
||||
.WithDisabled(disabled)
|
||||
.WithType(type)
|
||||
.WithChannelTypes(channelTypes)
|
||||
.WithDefaultValues(defaultValues)
|
||||
.WithId(id));
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ActionRowBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithActionRow<BuilderT>(this BuilderT container, ActionRowBuilder actionRow)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
{
|
||||
container.AddComponent(actionRow);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ActionRowBuilder"/> to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
public static BuilderT WithActionRow<BuilderT>(this BuilderT container,
|
||||
IEnumerable<IMessageComponentBuilder> components,
|
||||
int? id = null)
|
||||
where BuilderT : class, IStaticComponentContainer
|
||||
=> container.WithActionRow(new ActionRowBuilder()
|
||||
.WithComponents(components)
|
||||
.WithId(id));
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class ContainerBuilder : IMessageComponentBuilder, IStaticComponentContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum number of components allowed in a container.
|
||||
/// </summary>
|
||||
public const int MaxComponents = 10;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ComponentType Type => ComponentType.Container;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? Id { get; set; }
|
||||
|
||||
private List<IMessageComponentBuilder> _components = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<IMessageComponentBuilder> Components
|
||||
{
|
||||
get => _components;
|
||||
set => _components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accent color of this container.
|
||||
/// </summary>
|
||||
public uint? AccentColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this container is a spoiler.
|
||||
/// </summary>
|
||||
public bool? IsSpoiler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the accent color of this container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public ContainerBuilder WithAccentColor(Color? color)
|
||||
{
|
||||
AccentColor = color?.RawValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether this container is a spoiler.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public ContainerBuilder WithSpoiler(bool isSpoiler)
|
||||
{
|
||||
IsSpoiler = isSpoiler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponent"/>
|
||||
public ContainerBuilder AddComponent(IMessageComponentBuilder component)
|
||||
{
|
||||
Components.Add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponents"/>
|
||||
public ContainerBuilder AddComponents(params IMessageComponentBuilder[] components)
|
||||
{
|
||||
foreach (var component in components)
|
||||
Components.Add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.WithComponents"/>
|
||||
public ContainerBuilder WithComponents(IEnumerable<IMessageComponentBuilder> components)
|
||||
{
|
||||
Components = components.ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public ContainerComponent Build()
|
||||
{
|
||||
if (_components.Count is 0 or > MaxComponents)
|
||||
throw new InvalidOperationException($"A container must have between 1 and {MaxComponents} components.");
|
||||
|
||||
if (_components.Any(x => x
|
||||
is not ActionRowBuilder
|
||||
and not TextDisplayBuilder
|
||||
and not SectionBuilder
|
||||
and not MediaGalleryBuilder
|
||||
and not SeparatorBuilder
|
||||
and not FileComponentBuilder))
|
||||
throw new InvalidOperationException($"A container can only contain {nameof(ActionRowBuilder)}, {nameof(TextDisplayBuilder)}, {nameof(SectionBuilder)}, {nameof(MediaGalleryBuilder)}, {nameof(SeparatorBuilder)}, or {nameof(FileComponentBuilder)} components.");
|
||||
|
||||
return new(Components.ConvertAll(x => x.Build()).ToImmutableArray(), AccentColor, IsSpoiler, Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
/// <inheritdoc />
|
||||
IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component);
|
||||
/// <inheritdoc />
|
||||
IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components);
|
||||
/// <inheritdoc />
|
||||
IComponentContainer IComponentContainer.WithComponents(IEnumerable<IMessageComponentBuilder> components) => WithComponents(components);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class FileComponentBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ComponentType Type => ComponentType.File;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file for the component.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only attachment URLs are supported.
|
||||
/// </remarks>
|
||||
public UnfurledMediaItemProperties File { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the file is a spoiler.
|
||||
/// </summary>
|
||||
public bool? IsSpoiler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileComponentBuilder"/>.
|
||||
/// </summary>
|
||||
public FileComponentBuilder() {}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileComponentBuilder"/>.
|
||||
/// </summary>
|
||||
public FileComponentBuilder(UnfurledMediaItemProperties media, bool isSpoiler = false, int? id = null)
|
||||
{
|
||||
File = media;
|
||||
Id = id;
|
||||
IsSpoiler = isSpoiler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the file for the component.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public FileComponentBuilder WithFile(UnfurledMediaItemProperties file)
|
||||
{
|
||||
File = file;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether the file is a spoiler.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public FileComponentBuilder WithIsSpoiler(bool? isSpoiler)
|
||||
{
|
||||
IsSpoiler = isSpoiler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build" />
|
||||
public FileComponent Build()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(File.Url))
|
||||
throw new InvalidOperationException("File URL must be set.");
|
||||
|
||||
if (!File.Url.StartsWith("attachment://"))
|
||||
throw new InvalidOperationException("File URL must be an attachment URL.");
|
||||
|
||||
return new(new UnfurledMediaItem(File.Url), IsSpoiler, Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a container with child components.
|
||||
/// </summary>
|
||||
public interface IComponentContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the components in the container.
|
||||
/// </summary>
|
||||
List<IMessageComponentBuilder> Components { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a component to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
IComponentContainer AddComponent(IMessageComponentBuilder component);
|
||||
|
||||
/// <summary>
|
||||
/// Adds components to the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
IComponentContainer AddComponents(params IMessageComponentBuilder[] components);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the components in the container.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current container.
|
||||
/// </returns>
|
||||
IComponentContainer WithComponents(IEnumerable<IMessageComponentBuilder> components);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a builder for an interactable component.
|
||||
/// </summary>
|
||||
public interface IInteractableComponentBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the custom id for the component.
|
||||
/// </summary>
|
||||
string CustomId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a container for interactable components.
|
||||
/// </summary>
|
||||
public interface IInteractableComponentContainer : IComponentContainer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Discord;
|
||||
|
||||
public interface IMessageComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type of the component.
|
||||
/// </summary>
|
||||
ComponentType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the id for the component. An autoincremented id will be assigned if not set.
|
||||
/// </summary>
|
||||
int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Runs validation checks and builds the component.
|
||||
/// </summary>
|
||||
IMessageComponent Build();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a container for static components.
|
||||
/// </summary>
|
||||
public interface IStaticComponentContainer : IComponentContainer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class MediaGalleryBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the maximum number of items that can be added to a media gallery.
|
||||
/// </summary>
|
||||
public const int MaxItems = 10;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.MediaGallery;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
private List<MediaGalleryItemProperties> _items = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaGalleryBuilder"/>.
|
||||
/// </summary>
|
||||
public MediaGalleryBuilder() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaGalleryBuilder"/>.
|
||||
/// </summary>
|
||||
public MediaGalleryBuilder(IEnumerable<MediaGalleryItemProperties> items, int? id = null)
|
||||
{
|
||||
Items = items.ToList();
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the items in this media gallery.
|
||||
/// </summary>
|
||||
public List<MediaGalleryItemProperties> Items
|
||||
{
|
||||
get => _items;
|
||||
set => _items = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new item to the media gallery.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public MediaGalleryBuilder AddItem(MediaGalleryItemProperties item)
|
||||
{
|
||||
_items.Add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new item to the media gallery.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public MediaGalleryBuilder AddItem(string url, string description = null, bool isSpoiler = false)
|
||||
{
|
||||
_items.Add(new MediaGalleryItemProperties(new UnfurledMediaItemProperties(url), description, isSpoiler));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a list of items to the media gallery.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public MediaGalleryBuilder AddItems(params IEnumerable<MediaGalleryItemProperties> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
_items.Add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the items in the media gallery.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public MediaGalleryBuilder WithItems(IEnumerable<MediaGalleryItemProperties> items)
|
||||
{
|
||||
_items = items.ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public MediaGalleryComponent Build()
|
||||
{
|
||||
if (_items.Any(x => (x.Description?.Length ?? 0) > MediaGalleryItemProperties.MaxDescriptionLength))
|
||||
throw new ArgumentException($"{nameof(MediaGalleryItemProperties)} description length cannot exceed {MediaGalleryItemProperties.MaxDescriptionLength} characters.");
|
||||
|
||||
if (_items.Any(x => !(x.Media.Url?.StartsWith("http://") ?? false)
|
||||
&& !(x.Media.Url?.StartsWith("https://") ?? false)
|
||||
&& !(x.Media.Url?.StartsWith("attachment://") ?? false)))
|
||||
throw new ArgumentException($"{nameof(MediaGalleryItemProperties)} description must be a valid URL or attachment.");
|
||||
|
||||
if (_items.Count is 0 or > MaxItems)
|
||||
throw new ArgumentOutOfRangeException(nameof(Items), $"Media gallery items count must be in range [1, {MaxItems}]");
|
||||
|
||||
return new(_items.Select(x => new MediaGalleryItem(new UnfurledMediaItem(x.Media.Url), x.Description, x.IsSpoiler)).ToImmutableArray(), Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace Discord;
|
||||
|
||||
public struct MediaGalleryItemProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum length of the description.
|
||||
/// </summary>
|
||||
public const int MaxDescriptionLength = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the media item to display.
|
||||
/// </summary>
|
||||
public UnfurledMediaItemProperties Media { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of the media item.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the media item is a spoiler.
|
||||
/// </summary>
|
||||
public bool IsSpoiler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaGalleryItemProperties"/>.
|
||||
/// </summary>
|
||||
public MediaGalleryItemProperties() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaGalleryItemProperties"/>.
|
||||
/// </summary>
|
||||
public MediaGalleryItemProperties(UnfurledMediaItemProperties media, string description = null, bool isSpoiler = false)
|
||||
{
|
||||
Media = media;
|
||||
Description = description;
|
||||
IsSpoiler = isSpoiler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class SectionBuilder : IMessageComponentBuilder, IStaticComponentContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the maximum number of components allowed in this container.
|
||||
/// </summary>
|
||||
public const int MaxComponents = 3;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Section;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the accessory component.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only supports <see cref="ButtonBuilder"/> and <see cref="ThumbnailBuilder"/> currently.
|
||||
/// </remarks>
|
||||
public IMessageComponentBuilder Accessory { get; set; }
|
||||
|
||||
private List<IMessageComponentBuilder> _components = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>
|
||||
/// Only <see cref="TextDisplayBuilder"/> is supported.
|
||||
/// </remarks>
|
||||
public List<IMessageComponentBuilder> Components
|
||||
{
|
||||
get => _components;
|
||||
set => _components = value ?? throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null.");
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponent"/>
|
||||
/// <remarks>
|
||||
/// Only <see cref="TextDisplayBuilder"/> is supported.
|
||||
/// </remarks>
|
||||
public SectionBuilder AddComponent(IMessageComponentBuilder component)
|
||||
{
|
||||
Components.Add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.AddComponents"/>
|
||||
/// <remarks>
|
||||
/// Only <see cref="TextDisplayBuilder"/> is supported.
|
||||
/// </remarks>
|
||||
public SectionBuilder AddComponents(params IMessageComponentBuilder[] components)
|
||||
{
|
||||
foreach (var component in components)
|
||||
AddComponent(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IComponentContainer.WithComponents"/>
|
||||
/// <remarks>
|
||||
/// Only <see cref="TextDisplayBuilder"/> is supported.
|
||||
/// </remarks>
|
||||
public SectionBuilder WithComponents(IEnumerable<IMessageComponentBuilder> components)
|
||||
{
|
||||
Components = components.ToList();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the accessory component.
|
||||
/// </summary>
|
||||
public SectionBuilder WithAccessory(IMessageComponentBuilder accessory)
|
||||
{
|
||||
Accessory = accessory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public SectionComponent Build()
|
||||
{
|
||||
if (_components.Count is 0 or > MaxComponents)
|
||||
throw new InvalidOperationException($"Section component can only contain {MaxComponents} child components!");
|
||||
|
||||
if (_components.Any(x => x is not TextDisplayBuilder))
|
||||
throw new InvalidOperationException($"Section component can only contain {nameof(TextDisplayBuilder)}!");
|
||||
|
||||
if (Accessory is null)
|
||||
throw new ArgumentNullException(nameof(Accessory), "A section must have an accessory");
|
||||
|
||||
if (Accessory is not ButtonBuilder and not ThumbnailBuilder)
|
||||
throw new InvalidOperationException($"Accessory component can only be {nameof(ButtonBuilder)} or {nameof(ThumbnailBuilder)}!");
|
||||
|
||||
return new(Id, Components.Select(x => x.Build()).ToImmutableArray(), Accessory?.Build());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.AddComponent(IMessageComponentBuilder component) => AddComponent(component);
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.AddComponents(params IMessageComponentBuilder[] components) => AddComponents(components);
|
||||
/// <inheritdoc/>
|
||||
IComponentContainer IComponentContainer.WithComponents(IEnumerable<IMessageComponentBuilder> components) => WithComponents(components.ToList());
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Discord;
|
||||
/// <summary>
|
||||
/// Represents a class used to build <see cref="SelectMenuComponent"/>'s.
|
||||
/// </summary>
|
||||
public class SelectMenuBuilder
|
||||
public class SelectMenuBuilder : IInteractableComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The max length of a <see cref="SelectMenuComponent.Placeholder"/>.
|
||||
@@ -135,13 +135,16 @@ public class SelectMenuBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private List<SelectMenuOptionBuilder> _options = new List<SelectMenuOptionBuilder>();
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
private List<SelectMenuOptionBuilder> _options = [];
|
||||
private int _minValues = 1;
|
||||
private int _maxValues = 1;
|
||||
private string _placeholder;
|
||||
private string _customId;
|
||||
private ComponentType _type = ComponentType.SelectMenu;
|
||||
private List<SelectMenuDefaultValue> _defaultValues = new();
|
||||
private List<SelectMenuDefaultValue> _defaultValues = [];
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a <see cref="SelectMenuBuilder"/>.
|
||||
@@ -162,6 +165,7 @@ public class SelectMenuBuilder
|
||||
.Select(x => new SelectMenuOptionBuilder(x.Label, x.Value, x.Description, x.Emote, x.IsDefault))
|
||||
.ToList();
|
||||
DefaultValues = selectMenu.DefaultValues?.ToList();
|
||||
Id = selectMenu.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +180,7 @@ public class SelectMenuBuilder
|
||||
/// <param name="type">The <see cref="ComponentType"/> of this select menu.</param>
|
||||
/// <param name="channelTypes">The types of channels this menu can select (only valid on <see cref="ComponentType.ChannelSelect"/>s)</param>
|
||||
public SelectMenuBuilder(string customId, List<SelectMenuOptionBuilder> options = null, string placeholder = null, int maxValues = 1, int minValues = 1,
|
||||
bool isDisabled = false, ComponentType type = ComponentType.SelectMenu, List<ChannelType> channelTypes = null, List<SelectMenuDefaultValue> defaultValues = null)
|
||||
bool isDisabled = false, ComponentType type = ComponentType.SelectMenu, List<ChannelType> channelTypes = null, List<SelectMenuDefaultValue> defaultValues = null, int? id = null)
|
||||
{
|
||||
CustomId = customId;
|
||||
Options = options;
|
||||
@@ -187,6 +191,7 @@ public class SelectMenuBuilder
|
||||
Type = type;
|
||||
ChannelTypes = channelTypes ?? new();
|
||||
DefaultValues = defaultValues ?? new();
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -400,6 +405,9 @@ public class SelectMenuBuilder
|
||||
{
|
||||
var options = Options?.Select(x => x.Build()).ToList();
|
||||
|
||||
return new SelectMenuComponent(CustomId, options, Placeholder, MinValues, MaxValues, IsDisabled, Type, ChannelTypes, DefaultValues);
|
||||
return new SelectMenuComponent(CustomId, options, Placeholder, MinValues, MaxValues, IsDisabled, Type, Id, ChannelTypes, DefaultValues);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace Discord;
|
||||
|
||||
public class SeparatorBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Separator;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the component is a divider.
|
||||
/// </summary>
|
||||
public bool? IsDivider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the spacing of the separator.
|
||||
/// </summary>
|
||||
public SeparatorSpacingSize? Spacing { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether the component is a divider.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public SeparatorBuilder WithIsDivider(bool? isDivider)
|
||||
{
|
||||
IsDivider = isDivider;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the spacing of the separator.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public SeparatorBuilder WithSpacing(SeparatorSpacingSize? spacing)
|
||||
{
|
||||
Spacing = spacing;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public SeparatorComponent Build()
|
||||
{
|
||||
return new(IsDivider, Spacing, Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class TextDisplayBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum length of the content.
|
||||
/// </summary>
|
||||
public const int MaxContentLength = 4096;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.ActionRow;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content of the text display.
|
||||
/// </summary>
|
||||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="TextDisplayBuilder"/>.
|
||||
/// </summary>
|
||||
public TextDisplayBuilder() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="TextDisplayBuilder"/> with the specified content.
|
||||
/// </summary>
|
||||
public TextDisplayBuilder(string content, int? id = null)
|
||||
{
|
||||
Content = content;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content of the text display.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public TextDisplayBuilder WithContent(string content)
|
||||
{
|
||||
Content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public TextDisplayComponent Build()
|
||||
{
|
||||
if (Content.Length > MaxContentLength)
|
||||
throw new ArgumentException($"Content length must be less than or equal to {MaxContentLength}.", nameof(Content));
|
||||
|
||||
return new(Content, Id);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
@@ -6,8 +6,10 @@ namespace Discord;
|
||||
/// <summary>
|
||||
/// Represents a builder for creating a <see cref="TextInputComponent"/>.
|
||||
/// </summary>
|
||||
public class TextInputBuilder
|
||||
public class TextInputBuilder : IInteractableComponentBuilder
|
||||
{
|
||||
public ComponentType Type => ComponentType.TextInput;
|
||||
|
||||
/// <summary>
|
||||
/// The max length of a <see cref="TextInputComponent.Placeholder"/>.
|
||||
/// </summary>
|
||||
@@ -99,6 +101,8 @@ public class TextInputBuilder
|
||||
/// </summary>
|
||||
public bool? Required { get; set; }
|
||||
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default value of the text input.
|
||||
/// </summary>
|
||||
@@ -140,7 +144,7 @@ public class TextInputBuilder
|
||||
/// <param name="maxLength">The text input's maximum length.</param>
|
||||
/// <param name="required">The text input's required value.</param>
|
||||
public TextInputBuilder(string label, string customId, TextInputStyle style = TextInputStyle.Short, string placeholder = null,
|
||||
int? minLength = null, int? maxLength = null, bool? required = null, string value = null)
|
||||
int? minLength = null, int? maxLength = null, bool? required = null, string value = null, int? id = null)
|
||||
{
|
||||
Label = label;
|
||||
Style = style;
|
||||
@@ -150,6 +154,7 @@ public class TextInputBuilder
|
||||
MaxLength = maxLength;
|
||||
Required = required;
|
||||
Value = value;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -257,6 +262,8 @@ public class TextInputBuilder
|
||||
if (Style is TextInputStyle.Short && Value?.Any(x => x == '\n') is true)
|
||||
throw new ArgumentException($"Value must not contain new line characters when style is {TextInputStyle.Short}.", nameof(Value));
|
||||
|
||||
return new TextInputComponent(CustomId, Label, Placeholder, MinLength, MaxLength, Style, Required, Value);
|
||||
return new TextInputComponent(CustomId, Label, Placeholder, MinLength, MaxLength, Style, Required, Value, Id);
|
||||
}
|
||||
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
public class ThumbnailBuilder : IMessageComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the maximum length of the description.
|
||||
/// </summary>
|
||||
public const int MaxDescriptionLength = 1024;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Thumbnail;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the media of the thumbnail.
|
||||
/// </summary>
|
||||
public UnfurledMediaItemProperties Media { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description of the thumbnail.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the thumbnail is a spoiler.
|
||||
/// </summary>
|
||||
public bool IsSpoiler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ThumbnailBuilder"/>.
|
||||
/// </summary>
|
||||
public ThumbnailBuilder() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ThumbnailBuilder"/>.
|
||||
/// </summary>
|
||||
public ThumbnailBuilder(UnfurledMediaItemProperties media, string description = null, bool isSpoiler = false)
|
||||
{
|
||||
Media = media;
|
||||
Description = description;
|
||||
IsSpoiler = isSpoiler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the media of the thumbnail.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public ThumbnailBuilder WithMedia(UnfurledMediaItemProperties media)
|
||||
{
|
||||
Media = media;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the description of the thumbnail.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public ThumbnailBuilder WithDescription(string description)
|
||||
{
|
||||
Description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether the thumbnail is a spoiler.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The current builder.
|
||||
/// </returns>
|
||||
public ThumbnailBuilder WithSpoiler(bool isSpoiler)
|
||||
{
|
||||
IsSpoiler = isSpoiler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMessageComponentBuilder.Build"/>
|
||||
public ThumbnailComponent Build()
|
||||
{
|
||||
if (Description is not null && Description.Length > MaxDescriptionLength)
|
||||
throw new ArgumentException($"Description length must be less than or equal to {MaxDescriptionLength}.", nameof(Description));
|
||||
|
||||
return new(Id, new UnfurledMediaItem(Media.Url), Description, IsSpoiler);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IMessageComponent IMessageComponentBuilder.Build() => Build();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Discord;
|
||||
|
||||
public struct UnfurledMediaItemProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the URL of the media item.
|
||||
/// </summary>
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnfurledMediaItemProperties"/>.
|
||||
/// </summary>
|
||||
public UnfurledMediaItemProperties() {}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnfurledMediaItemProperties"/>.
|
||||
/// </summary>
|
||||
public UnfurledMediaItemProperties(string url)
|
||||
{
|
||||
Url = url;
|
||||
}
|
||||
|
||||
public static implicit operator UnfurledMediaItemProperties(string url) => new(url);
|
||||
}
|
||||
@@ -3,11 +3,14 @@ namespace Discord;
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> Button.
|
||||
/// </summary>
|
||||
public class ButtonComponent : IMessageComponent
|
||||
public class ButtonComponent : IInteractableComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Button;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ButtonStyle"/> of this button, example buttons with each style can be found <see href="https://discord.com/assets/7bb017ce52cfd6575e21c058feb3883b.png">Here</see>.
|
||||
/// </summary>
|
||||
@@ -56,9 +59,10 @@ public class ButtonComponent : IMessageComponent
|
||||
public ButtonBuilder ToBuilder()
|
||||
=> new (Label, CustomId, Style, Url, Emote, IsDisabled);
|
||||
|
||||
internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool isDisabled, ulong? skuId)
|
||||
internal ButtonComponent(ButtonStyle style, string label, IEmote emote, string customId, string url, bool isDisabled, ulong? skuId, int? id)
|
||||
{
|
||||
Style = style;
|
||||
Id = id;
|
||||
Label = label;
|
||||
Emote = emote;
|
||||
CustomId = customId;
|
||||
|
||||
@@ -44,5 +44,19 @@ namespace Discord
|
||||
/// A select menu for picking from channels.
|
||||
/// </summary>
|
||||
ChannelSelect = 8,
|
||||
|
||||
Section = 9,
|
||||
|
||||
TextDisplay = 10,
|
||||
|
||||
Thumbnail = 11,
|
||||
|
||||
MediaGallery = 12,
|
||||
|
||||
File = 13,
|
||||
|
||||
Separator = 14,
|
||||
|
||||
Container = 17,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a container component.
|
||||
/// </summary>
|
||||
public class ContainerComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Container;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the components in this container.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the accent color of this container.
|
||||
/// </summary>
|
||||
public uint? AccentColor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this container is a spoiler.
|
||||
/// </summary>
|
||||
public bool? IsSpoiler { get; }
|
||||
|
||||
internal ContainerComponent(IReadOnlyCollection<IMessageComponent> components, uint? accentColor, bool? isSpoiler, int? id = null)
|
||||
{
|
||||
Components = components;
|
||||
AccentColor = accentColor;
|
||||
IsSpoiler = isSpoiler;
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a file component.
|
||||
/// </summary>
|
||||
public class FileComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.File;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file of this component.
|
||||
/// </summary>
|
||||
public UnfurledMediaItem File { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this file is a spoiler.
|
||||
/// </summary>
|
||||
public bool? IsSpoiler { get; }
|
||||
|
||||
internal FileComponent(UnfurledMediaItem file, bool? isSpoiler, int? id = null)
|
||||
{
|
||||
File = file;
|
||||
IsSpoiler = isSpoiler;
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a message component that can be interacted with.
|
||||
/// </summary>
|
||||
public interface IInteractableComponent : IMessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the custom id of the component if possible; otherwise <see langword="null"/>.
|
||||
/// </summary>
|
||||
string CustomId { get; }
|
||||
}
|
||||
@@ -1,18 +1,14 @@
|
||||
namespace Discord
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a message component on a message.
|
||||
/// </summary>
|
||||
public interface IMessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a message component on a message.
|
||||
/// Gets the <see cref="ComponentType"/> of this Message Component.
|
||||
/// </summary>
|
||||
public interface IMessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ComponentType"/> of this Message Component.
|
||||
/// </summary>
|
||||
ComponentType Type { get; }
|
||||
ComponentType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the custom id of the component if possible; otherwise <see langword="null"/>.
|
||||
/// </summary>
|
||||
string CustomId { get; }
|
||||
}
|
||||
int? Id { get; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a media gallery component.
|
||||
/// </summary>
|
||||
public class MediaGalleryComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.MediaGallery;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the items in this media gallery.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<MediaGalleryItem> Items { get; }
|
||||
|
||||
internal MediaGalleryComponent(IReadOnlyCollection<MediaGalleryItem> items, int? id)
|
||||
{
|
||||
Items = items;
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a media gallery item.
|
||||
/// </summary>
|
||||
public readonly struct MediaGalleryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the media for this item.
|
||||
/// </summary>
|
||||
public UnfurledMediaItem Media { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description for this item.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this item is a spoiler.
|
||||
/// </summary>
|
||||
public bool IsSpoiler { get; }
|
||||
|
||||
internal MediaGalleryItem(UnfurledMediaItem media, string description, bool? isSpoiler)
|
||||
{
|
||||
Media = media;
|
||||
Description = description;
|
||||
IsSpoiler = isSpoiler ?? false;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a component object used to send components with messages.
|
||||
/// </summary>
|
||||
public class MessageComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a component object used to send components with messages.
|
||||
/// Gets the components to be used in a message.
|
||||
/// </summary>
|
||||
public class MessageComponent
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; }
|
||||
|
||||
internal MessageComponent(List<IMessageComponent> components)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the components to be used in a message.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<ActionRowComponent> Components { get; }
|
||||
|
||||
internal MessageComponent(List<ActionRowComponent> components)
|
||||
{
|
||||
Components = components;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a empty <see cref="MessageComponent"/>.
|
||||
/// </summary>
|
||||
internal static MessageComponent Empty
|
||||
=> new MessageComponent(new List<ActionRowComponent>());
|
||||
Components = components;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a empty <see cref="MessageComponent"/>.
|
||||
/// </summary>
|
||||
internal static MessageComponent Empty
|
||||
=> new([]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a media item that has been unfurled and resolved.
|
||||
/// </summary>
|
||||
public class ResolvedUnfurledMediaItem : UnfurledMediaItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the proxy URL for this media item.
|
||||
/// </summary>
|
||||
public string ProxyUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of this media item.
|
||||
/// </summary>
|
||||
public int Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of this media item.
|
||||
/// </summary>
|
||||
public int Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of this media item.
|
||||
/// </summary>
|
||||
public string ContentType { get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the loading state of this media item.
|
||||
/// </summary>
|
||||
public UnfurledMediaItemLoadingState LoadingState { get; }
|
||||
|
||||
internal ResolvedUnfurledMediaItem(string url, string proxyUrl, int height, int width, string contentType, UnfurledMediaItemLoadingState loadingState) : base(url)
|
||||
{
|
||||
ProxyUrl = proxyUrl;
|
||||
Height = height;
|
||||
Width = width;
|
||||
ContentType = contentType;
|
||||
LoadingState = loadingState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a section component.
|
||||
/// </summary>
|
||||
public class SectionComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Section;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the components in this section.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the accessory of this section.
|
||||
/// </summary>
|
||||
public IMessageComponent Accessory { get; }
|
||||
|
||||
internal SectionComponent(int? id, IReadOnlyCollection<IMessageComponent> components, IMessageComponent accessory)
|
||||
{
|
||||
Id = id;
|
||||
Components = components;
|
||||
Accessory = accessory;
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,14 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Represents a select menu component defined at <see href="https://discord.com/developers/docs/interactions/message-components#select-menu-object"/>
|
||||
/// </summary>
|
||||
public class SelectMenuComponent : IMessageComponent
|
||||
public class SelectMenuComponent : IInteractableComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CustomId { get; }
|
||||
|
||||
@@ -67,7 +70,7 @@ namespace Discord
|
||||
DefaultValues.ToList());
|
||||
|
||||
internal SelectMenuComponent(string customId, List<SelectMenuOption> options, string placeholder, int minValues, int maxValues,
|
||||
bool disabled, ComponentType type, IEnumerable<ChannelType> channelTypes = null, IEnumerable<SelectMenuDefaultValue> defaultValues = null)
|
||||
bool disabled, ComponentType type, int? id, IEnumerable<ChannelType> channelTypes = null, IEnumerable<SelectMenuDefaultValue> defaultValues = null)
|
||||
{
|
||||
CustomId = customId;
|
||||
Options = options;
|
||||
@@ -76,8 +79,9 @@ namespace Discord
|
||||
MaxValues = maxValues;
|
||||
IsDisabled = disabled;
|
||||
Type = type;
|
||||
ChannelTypes = channelTypes?.ToArray() ?? Array.Empty<ChannelType>();
|
||||
DefaultValues = defaultValues?.ToArray() ?? Array.Empty<SelectMenuDefaultValue>();
|
||||
Id = id;
|
||||
ChannelTypes = channelTypes?.ToArray() ?? [];
|
||||
DefaultValues = defaultValues?.ToArray() ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a separator component.
|
||||
/// </summary>
|
||||
public class SeparatorComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Separator;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this component is a divider.
|
||||
/// </summary>
|
||||
public bool? IsDivider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the spacing of this component.
|
||||
/// </summary>
|
||||
public SeparatorSpacingSize? Spacing { get; }
|
||||
|
||||
internal SeparatorComponent(bool? isDivider, SeparatorSpacingSize? spacing, int? id = null)
|
||||
{
|
||||
IsDivider = isDivider;
|
||||
Spacing = spacing;
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the spacing of a separator component.
|
||||
/// </summary>
|
||||
public enum SeparatorSpacingSize
|
||||
{
|
||||
/// <summary>
|
||||
/// The separator has a small spacing.
|
||||
/// </summary>
|
||||
Small = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The separator has a large spacing.
|
||||
/// </summary>
|
||||
Large = 2
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a text display component.
|
||||
/// </summary>
|
||||
public class TextDisplayComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.TextDisplay;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content of this component.
|
||||
/// </summary>
|
||||
public string Content { get; }
|
||||
|
||||
internal TextDisplayComponent(string content, int? id = null)
|
||||
{
|
||||
Id = id;
|
||||
Content = content;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Represents a <see cref="IMessageComponent"/> text input.
|
||||
/// </summary>
|
||||
public class TextInputComponent : IMessageComponent
|
||||
public class TextInputComponent : IInteractableComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.TextInput;
|
||||
@@ -11,6 +11,9 @@ namespace Discord
|
||||
/// <inheritdoc/>
|
||||
public string CustomId { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label of the component; this is the text shown above it.
|
||||
/// </summary>
|
||||
@@ -47,7 +50,7 @@ namespace Discord
|
||||
public string Value { get; }
|
||||
|
||||
internal TextInputComponent(string customId, string label, string placeholder, int? minLength, int? maxLength,
|
||||
TextInputStyle style, bool? required, string value)
|
||||
TextInputStyle style, bool? required, string value, int? id)
|
||||
{
|
||||
CustomId = customId;
|
||||
Label = label;
|
||||
@@ -57,6 +60,7 @@ namespace Discord
|
||||
Style = style;
|
||||
Required = required;
|
||||
Value = value;
|
||||
Id = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Discord
|
||||
/// Intended for short, single-line text.
|
||||
/// </summary>
|
||||
Short = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Intended for longer or multiline text.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a thumbnail component.
|
||||
/// </summary>
|
||||
public class ThumbnailComponent : IMessageComponent
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => ComponentType.Thumbnail;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media of the component.
|
||||
/// </summary>
|
||||
public UnfurledMediaItem Media { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the component.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the component is a spoiler.
|
||||
/// </summary>
|
||||
public bool IsSpoiler { get; }
|
||||
|
||||
internal ThumbnailComponent(int? id, UnfurledMediaItem media, string description, bool? isSpoiler)
|
||||
{
|
||||
Id = id;
|
||||
Media = media;
|
||||
Description = description;
|
||||
IsSpoiler = isSpoiler ?? false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a media item that has been unfurled.
|
||||
/// </summary>
|
||||
public class UnfurledMediaItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the URL of this media item.
|
||||
/// </summary>
|
||||
public string Url { get; }
|
||||
|
||||
internal UnfurledMediaItem(string url)
|
||||
{
|
||||
Url = url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Discord;
|
||||
|
||||
public enum UnfurledMediaItemLoadingState
|
||||
{
|
||||
/// <summary>
|
||||
/// The state of the media item is unknown.
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The media item is currently loading.
|
||||
/// </summary>
|
||||
Loading = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The media item was successfully loaded.
|
||||
/// </summary>
|
||||
LoadingSuccess = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The media item was not found.
|
||||
/// </summary>
|
||||
LoadingNotFound = 3
|
||||
}
|
||||
@@ -1,19 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a modal interaction.
|
||||
/// </summary>
|
||||
public class Modal : IMessageComponent
|
||||
public class Modal
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ComponentType Type => throw new NotSupportedException("Modals do not have a component type.");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the modal.
|
||||
/// </summary>
|
||||
|
||||
@@ -111,21 +111,20 @@ namespace Discord
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <typeparamref name="TMessageComponent"/> by the specified <paramref name="customId"/>.
|
||||
/// Gets a <typeparamref name="TMessageComponentBuilder"/> by the specified <paramref name="customId"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TMessageComponent">The type of the component to get.</typeparam>
|
||||
/// <param name="customId">The <see cref="IMessageComponent.CustomId"/> of the component to get.</param>
|
||||
/// <typeparam name="TMessageComponentBuilder">The type of the component to get.</typeparam>
|
||||
/// <param name="customId">The <see cref="IInteractableComponentBuilder.CustomId"/> of the component to get.</param>
|
||||
/// <returns>
|
||||
/// The component of type <typeparamref name="TMessageComponent"/> that was found, <see langword="null"/> otherwise.
|
||||
/// The component of type <typeparamref name="TMessageComponentBuilder"/> that was found, <see langword="null"/> otherwise.
|
||||
/// </returns>
|
||||
public TMessageComponent GetComponent<TMessageComponent>(string customId)
|
||||
where TMessageComponent : class, IMessageComponent
|
||||
public TMessageComponentBuilder GetComponent<TMessageComponentBuilder>(string customId)
|
||||
where TMessageComponentBuilder : class, IInteractableComponentBuilder
|
||||
{
|
||||
Preconditions.NotNull(customId, nameof(customId));
|
||||
|
||||
return Components.ActionRows
|
||||
?.SelectMany(r => r.Components.OfType<TMessageComponent>())
|
||||
.FirstOrDefault(c => c?.CustomId == customId);
|
||||
return Components.ActionRows?.SelectMany(r => r.Components.OfType<TMessageComponentBuilder>())
|
||||
.FirstOrDefault(c => c.CustomId == customId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,7 +140,7 @@ namespace Discord
|
||||
{
|
||||
Preconditions.NotNull(customId, nameof(customId));
|
||||
|
||||
var component = GetComponent<TextInputComponent>(customId) ?? throw new ArgumentException($"There is no component of type {nameof(TextInputComponent)} with the specified custom ID in this modal builder.", nameof(customId));
|
||||
var component = GetComponent<TextInputBuilder>(customId) ?? throw new ArgumentException($"There is no component of type {nameof(TextInputComponent)} with the specified custom ID in this modal builder.", nameof(customId));
|
||||
var row = Components.ActionRows.First(r => r.Components.Contains(component));
|
||||
|
||||
var builder = new TextInputBuilder
|
||||
@@ -159,7 +158,7 @@ namespace Discord
|
||||
updateTextInput(builder);
|
||||
|
||||
row.Components.Remove(component);
|
||||
row.AddComponent(builder.Build());
|
||||
row.AddComponent(builder);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -179,13 +178,13 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Removes a component from this builder by the specified <paramref name="customId"/>.
|
||||
/// </summary>
|
||||
/// <param name="customId">The <see cref="IMessageComponent.CustomId"/> of the component to remove.</param>
|
||||
/// <param name="customId">The <see cref="IInteractableComponent.CustomId"/> of the component to remove.</param>
|
||||
/// <returns>The current builder.</returns>
|
||||
public ModalBuilder RemoveComponent(string customId)
|
||||
{
|
||||
Preconditions.NotNull(customId, nameof(customId));
|
||||
|
||||
Components.ActionRows?.ForEach(r => r.Components.RemoveAll(c => c.CustomId == customId));
|
||||
Components.ActionRows?.ForEach(r => r.Components.RemoveAll(c => c is IInteractableComponentBuilder ic && ic.CustomId == customId));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -226,7 +225,7 @@ namespace Discord
|
||||
public class ModalComponentBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The max length of a <see cref="IMessageComponent.CustomId"/>.
|
||||
/// The max length of a <see cref="IInteractableComponent.CustomId"/>.
|
||||
/// </summary>
|
||||
public const int MaxCustomIdLength = 100;
|
||||
|
||||
@@ -314,19 +313,17 @@ namespace Discord
|
||||
{
|
||||
Preconditions.LessThan(row, MaxActionRowCount, nameof(row));
|
||||
|
||||
var builtButton = text.Build();
|
||||
|
||||
if (_actionRows == null)
|
||||
{
|
||||
_actionRows = new List<ActionRowBuilder>
|
||||
{
|
||||
new ActionRowBuilder().AddComponent(builtButton)
|
||||
new ActionRowBuilder().AddComponent(text)
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_actionRows.Count == row)
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(builtButton));
|
||||
_actionRows.Add(new ActionRowBuilder().AddComponent(text));
|
||||
else
|
||||
{
|
||||
ActionRowBuilder actionRow;
|
||||
@@ -338,8 +335,8 @@ namespace Discord
|
||||
_actionRows.Add(actionRow);
|
||||
}
|
||||
|
||||
if (actionRow.CanTakeComponent(builtButton))
|
||||
actionRow.AddComponent(builtButton);
|
||||
if (actionRow.CanTakeComponent(text))
|
||||
actionRow.AddComponent(text);
|
||||
else if (row < MaxActionRowCount)
|
||||
WithTextInput(text, row + 1);
|
||||
else
|
||||
|
||||
@@ -123,5 +123,16 @@ namespace Discord
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the url formatted with <c>attachment://</c> protocol.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The formatted url.
|
||||
/// </returns>
|
||||
public string GetAttachmentUrl()
|
||||
{
|
||||
return $"attachment://{FileName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,5 +57,10 @@ namespace Discord
|
||||
/// This message is a voice message.
|
||||
/// </summary>
|
||||
VoiceMessage = 1 << 13,
|
||||
|
||||
/// <summary>
|
||||
/// This message is using v2 components.
|
||||
/// </summary>
|
||||
ComponentsV2 = 1 << 15,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,5 +401,11 @@ namespace Discord
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static void ValidateMessageFlags(MessageFlags flags)
|
||||
{
|
||||
if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification and not MessageFlags.ComponentsV2 and not MessageFlags.Ephemeral)
|
||||
throw new ArgumentException("The only valid MessageFlags are Ephemeral, SuppressEmbeds, SuppressNotification, ComponentsV2 and None.", nameof(flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,55 +44,55 @@ namespace Discord.Interactions
|
||||
protected virtual Task DeferAsync(bool ephemeral = false, RequestOptions options = null)
|
||||
=> Context.Interaction.DeferAsync(ephemeral, options);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondAsync(string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondAsync(string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
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, PollProperties poll = null)
|
||||
=> Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(Stream, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(Stream, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
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, PollProperties poll = null)
|
||||
=> Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.RespondWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(string, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(string, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
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, PollProperties poll = null)
|
||||
=> Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.RespondWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(FileAttachment, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFileAsync(FileAttachment, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
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, PollProperties poll = null)
|
||||
=> Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.RespondWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFilesAsync(IEnumerable{FileAttachment}, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondWithFilesAsync(IEnumerable{FileAttachment}, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task RespondWithFilesAsync(IEnumerable<FileAttachment> 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)
|
||||
=> Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.RespondWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupAsync(string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupAsync(string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task<IUserMessage> 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, PollProperties poll = null)
|
||||
=> Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, Embed embed = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(Stream, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(Stream, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task<IUserMessage> 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)
|
||||
=> Context.Interaction.FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(string, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(string, string, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task<IUserMessage> 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)
|
||||
=> Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(FileAttachment, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFileAsync(FileAttachment, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task<IUserMessage> 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)
|
||||
=> Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFilesAsync(IEnumerable{FileAttachment}, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties)"/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.FollowupWithFilesAsync(IEnumerable{FileAttachment}, string, Embed[], bool, bool, AllowedMentions, MessageComponent, Embed, RequestOptions, PollProperties, MessageFlags)"/>
|
||||
protected virtual Task<IUserMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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)
|
||||
=> Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> Context.Interaction.FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <inheritdoc cref="IMessageChannel.SendMessageAsync(string, bool, Embed, RequestOptions, AllowedMentions, MessageReference, MessageComponent, ISticker[], Embed[], MessageFlags, PollProperties)"/>
|
||||
protected virtual Task<IUserMessage> ReplyAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null,
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace Discord.Interactions
|
||||
/// A Task representing the operation of creating the interaction response.
|
||||
/// </returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the interaction isn't a type of <see cref="RestInteraction"/>.</exception>
|
||||
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));
|
||||
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, MessageFlags flags = MessageFlags.None)
|
||||
=> HandleInteractionAsync(x => x.Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags));
|
||||
|
||||
/// <summary>
|
||||
/// Responds to the interaction with a modal.
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace Discord.API
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public IMessageComponent[] Components { get; set; }
|
||||
|
||||
@@ -29,9 +32,10 @@ namespace Discord.API
|
||||
_ => null
|
||||
};
|
||||
}).ToArray();
|
||||
Id = c.Id ?? Optional<int>.Unspecified;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
string IMessageComponent.CustomId => null;
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
internal class ButtonComponent : IMessageComponent
|
||||
internal class ButtonComponent : IInteractableComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("style")]
|
||||
public ButtonStyle Style { get; set; }
|
||||
|
||||
@@ -39,6 +42,7 @@ namespace Discord.API
|
||||
Url = c.Url;
|
||||
Disabled = c.IsDisabled;
|
||||
SkuId = c.SkuId ?? Optional<ulong>.Unspecified;
|
||||
Id = c.Id ?? Optional<int>.Unspecified;
|
||||
|
||||
if (c.Emote != null)
|
||||
{
|
||||
@@ -62,6 +66,9 @@ namespace Discord.API
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
string IMessageComponent.CustomId => CustomId.GetValueOrDefault();
|
||||
string IInteractableComponent.CustomId => CustomId.GetValueOrDefault();
|
||||
|
||||
[JsonIgnore]
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
}
|
||||
|
||||
36
src/Discord.Net.Rest/API/Common/ContainerComponent.cs
Normal file
36
src/Discord.Net.Rest/API/Common/ContainerComponent.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Discord.Rest;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class ContainerComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("accent_color")]
|
||||
public Optional<uint?> AccentColor { get; set; }
|
||||
|
||||
[JsonProperty("spoiler")]
|
||||
public Optional<bool> IsSpoiler { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public IMessageComponent[] Components { get; set; }
|
||||
|
||||
public ContainerComponent() { }
|
||||
|
||||
public ContainerComponent(Discord.ContainerComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
AccentColor = component.AccentColor ?? Optional<uint?>.Unspecified;
|
||||
IsSpoiler = component.IsSpoiler ?? Optional<bool>.Unspecified;
|
||||
Components = component.Components.Select(x => x.ToModel()).ToArray();
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
30
src/Discord.Net.Rest/API/Common/FileComponent.cs
Normal file
30
src/Discord.Net.Rest/API/Common/FileComponent.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Discord.Rest;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class FileComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("file")]
|
||||
public UnfurledMediaItem File { get; set; }
|
||||
|
||||
[JsonProperty("spoiler")]
|
||||
public Optional<bool> IsSpoiler { get; set; }
|
||||
|
||||
public FileComponent() { }
|
||||
|
||||
public FileComponent(Discord.FileComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
File = component.File.ToModel();
|
||||
IsSpoiler = component.IsSpoiler ?? Optional<bool>.Unspecified;
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
@@ -17,7 +17,7 @@ internal class ForumThreadMessage
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("sticker_ids")]
|
||||
public Optional<ulong[]> Stickers { get; set; }
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Discord.API
|
||||
public Optional<MessageFlags> Flags { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<ActionRowComponent[]> Components { get; set; }
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("choices")]
|
||||
public Optional<ApplicationCommandOptionChoice[]> Choices { get; set; }
|
||||
|
||||
33
src/Discord.Net.Rest/API/Common/MediaGalleryComponent.cs
Normal file
33
src/Discord.Net.Rest/API/Common/MediaGalleryComponent.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Discord.Rest;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class MediaGalleryComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("items")]
|
||||
public MediaGalleryItem[] Items { get; set; }
|
||||
|
||||
public MediaGalleryComponent() { }
|
||||
|
||||
public MediaGalleryComponent(Discord.MediaGalleryComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
Items = component.Items.Select(x => new MediaGalleryItem
|
||||
{
|
||||
Description = x.Description,
|
||||
IsSpoiler = x.IsSpoiler,
|
||||
Media = x.Media.ToModel()
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
15
src/Discord.Net.Rest/API/Common/MediaGalleryItem.cs
Normal file
15
src/Discord.Net.Rest/API/Common/MediaGalleryItem.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class MediaGalleryItem
|
||||
{
|
||||
[JsonProperty("media")]
|
||||
public UnfurledMediaItem Media { get; set; }
|
||||
|
||||
[JsonProperty("description")]
|
||||
public Optional<string> Description { get; set; }
|
||||
|
||||
[JsonProperty("spoiler")]
|
||||
public Optional<bool> IsSpoiler { get; set; }
|
||||
}
|
||||
32
src/Discord.Net.Rest/API/Common/SectionComponent.cs
Normal file
32
src/Discord.Net.Rest/API/Common/SectionComponent.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Discord.Rest;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class SectionComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public IMessageComponent[] Components { get; set; }
|
||||
|
||||
[JsonProperty("accessory")]
|
||||
public IMessageComponent Accessory { get; set; }
|
||||
|
||||
public SectionComponent() { }
|
||||
|
||||
public SectionComponent(Discord.SectionComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
Components = component.Components.Select(x => x.ToModel()).ToArray();
|
||||
Accessory = component.Accessory.ToModel();
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
@@ -3,11 +3,14 @@ using System.Linq;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
internal class SelectMenuComponent : IMessageComponent
|
||||
internal class SelectMenuComponent : IInteractableComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("custom_id")]
|
||||
public string CustomId { get; set; }
|
||||
|
||||
@@ -52,5 +55,8 @@ namespace Discord.API
|
||||
ChannelTypes = component.ChannelTypes.ToArray();
|
||||
DefaultValues = component.DefaultValues.Select(x => new SelectMenuDefaultValue {Id = x.Id, Type = x.Type}).ToArray();
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
}
|
||||
|
||||
30
src/Discord.Net.Rest/API/Common/SeparatorComponent.cs
Normal file
30
src/Discord.Net.Rest/API/Common/SeparatorComponent.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class SeparatorComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("divider")]
|
||||
public Optional<bool> IsDivider { get; set; }
|
||||
|
||||
[JsonProperty("spacing")]
|
||||
public Optional<SeparatorSpacingSize> Spacing { get; set; }
|
||||
|
||||
public SeparatorComponent() { }
|
||||
|
||||
public SeparatorComponent(Discord.SeparatorComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
IsDivider = component.IsDivider ?? Optional<bool>.Unspecified;
|
||||
Spacing = component.Spacing ?? Optional<SeparatorSpacingSize>.Unspecified;
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
26
src/Discord.Net.Rest/API/Common/TextDisplayComponent.cs
Normal file
26
src/Discord.Net.Rest/API/Common/TextDisplayComponent.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class TextDisplayComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("content")]
|
||||
public string Content { get; set; }
|
||||
|
||||
public TextDisplayComponent() { }
|
||||
|
||||
public TextDisplayComponent(Discord.TextDisplayComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
Content = component.Content;
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
@@ -2,11 +2,14 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API
|
||||
{
|
||||
internal class TextInputComponent : IMessageComponent
|
||||
internal class TextInputComponent : IInteractableComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("style")]
|
||||
public TextInputStyle Style { get; set; }
|
||||
|
||||
@@ -44,6 +47,10 @@ namespace Discord.API
|
||||
MaxLength = component.MaxLength ?? Optional<int>.Unspecified;
|
||||
Required = component.Required ?? Optional<bool>.Unspecified;
|
||||
Value = component.Value ?? Optional<string>.Unspecified;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
}
|
||||
|
||||
35
src/Discord.Net.Rest/API/Common/ThumbnailComponent.cs
Normal file
35
src/Discord.Net.Rest/API/Common/ThumbnailComponent.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Discord.Rest;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class ThumbnailComponent : IMessageComponent
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public ComponentType Type { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public Optional<int> Id { get; set; }
|
||||
|
||||
[JsonProperty("media")]
|
||||
public UnfurledMediaItem Media { get; set; }
|
||||
|
||||
[JsonProperty("description")]
|
||||
public Optional<string> Description { get; set; }
|
||||
|
||||
[JsonProperty("spoiler")]
|
||||
public Optional<bool> IsSpoiler { get; set; }
|
||||
|
||||
public ThumbnailComponent() { }
|
||||
|
||||
public ThumbnailComponent(Discord.ThumbnailComponent component)
|
||||
{
|
||||
Type = component.Type;
|
||||
Id = component.Id ?? Optional<int>.Unspecified;
|
||||
Media = component.Media.ToModel();
|
||||
Description = component.Description;
|
||||
IsSpoiler = component.IsSpoiler;
|
||||
}
|
||||
|
||||
int? IMessageComponent.Id => Id.ToNullable();
|
||||
}
|
||||
24
src/Discord.Net.Rest/API/Common/UnfurledMediaItem.cs
Normal file
24
src/Discord.Net.Rest/API/Common/UnfurledMediaItem.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API;
|
||||
|
||||
internal class UnfurledMediaItem
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("proxy_url")]
|
||||
public Optional<string> ProxyUrl { get; set; }
|
||||
|
||||
[JsonProperty("height")]
|
||||
public Optional<int?> Height { get; set; }
|
||||
|
||||
[JsonProperty("width")]
|
||||
public Optional<int?> Width { get; set; }
|
||||
|
||||
[JsonProperty("content_type")]
|
||||
public Optional<string> ContentType { get; set; }
|
||||
|
||||
[JsonProperty("loading_state")]
|
||||
public Optional<UnfurledMediaItemLoadingState> LoadingState { get; set; }
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Discord.API.Rest
|
||||
public Optional<MessageReference> MessageReference { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("sticker_ids")]
|
||||
public Optional<ulong[]> Stickers { get; set; }
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Discord.API.Rest
|
||||
public Optional<string> Content { get; set; }
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
public Optional<ActionRowComponent[]> MessageComponent { get; set; }
|
||||
public Optional<IMessageComponent[]> MessageComponent { get; set; }
|
||||
public Optional<MessageFlags?> Flags { get; set; }
|
||||
public Optional<ulong[]> Stickers { get; set; }
|
||||
public Optional<ulong[]> TagIds { get; set; }
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
namespace Discord.API.Rest;
|
||||
|
||||
internal class CreatePostParams
|
||||
{
|
||||
internal class CreatePostParams
|
||||
{
|
||||
// thread
|
||||
[JsonProperty("name")]
|
||||
public string Title { get; set; }
|
||||
// thread
|
||||
[JsonProperty("name")]
|
||||
public string Title { get; set; }
|
||||
|
||||
[JsonProperty("auto_archive_duration")]
|
||||
public ThreadArchiveDuration ArchiveDuration { get; set; }
|
||||
[JsonProperty("auto_archive_duration")]
|
||||
public ThreadArchiveDuration ArchiveDuration { get; set; }
|
||||
|
||||
[JsonProperty("rate_limit_per_user")]
|
||||
public Optional<int?> Slowmode { get; set; }
|
||||
[JsonProperty("rate_limit_per_user")]
|
||||
public Optional<int?> Slowmode { get; set; }
|
||||
|
||||
[JsonProperty("message")]
|
||||
public ForumThreadMessage Message { get; set; }
|
||||
[JsonProperty("message")]
|
||||
public ForumThreadMessage Message { get; set; }
|
||||
|
||||
[JsonProperty("applied_tags")]
|
||||
public Optional<ulong[]> Tags { get; set; }
|
||||
}
|
||||
[JsonProperty("applied_tags")]
|
||||
public Optional<ulong[]> Tags { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Discord.Net.Rest;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
@@ -37,7 +38,7 @@ namespace Discord.API.Rest
|
||||
public Optional<MessageFlags> Flags { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("file")]
|
||||
public Optional<MultipartFile> File { get; set; }
|
||||
@@ -55,6 +56,7 @@ namespace Discord.API.Rest
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
|
||||
var extraFlags = MessageFlags.None;
|
||||
if (File.IsSpecified)
|
||||
{
|
||||
d["file"] = File.Value;
|
||||
@@ -77,14 +79,21 @@ namespace Discord.API.Rest
|
||||
payload["embeds"] = Embeds.Value;
|
||||
if (AllowedMentions.IsSpecified)
|
||||
payload["allowed_mentions"] = AllowedMentions.Value;
|
||||
|
||||
|
||||
if (Components.IsSpecified)
|
||||
{
|
||||
payload["components"] = Components.Value;
|
||||
if (Components.Value.Any(x => x.Type is not ComponentType.ActionRow))
|
||||
extraFlags |= MessageFlags.ComponentsV2;
|
||||
}
|
||||
|
||||
payload["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags;
|
||||
|
||||
if (ThreadName.IsSpecified)
|
||||
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;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Discord.API.Rest
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<ActionRowComponent[]> Components { get; set; }
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("flags")]
|
||||
public Optional<MessageFlags?> Flags { get; set; }
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
namespace Discord.API.Rest;
|
||||
|
||||
internal class ModifyMessageParams
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
internal class ModifyMessageParams
|
||||
{
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
[JsonProperty("embeds")]
|
||||
public Optional<API.Embed[]> Embeds { get; set; }
|
||||
[JsonProperty("components")]
|
||||
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||
[JsonProperty("flags")]
|
||||
public Optional<MessageFlags?> Flags { get; set; }
|
||||
[JsonProperty("allowed_mentions")]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
}
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
|
||||
[JsonProperty("embeds")]
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
|
||||
[JsonProperty("flags")]
|
||||
public Optional<MessageFlags?> Flags { get; set; }
|
||||
|
||||
[JsonProperty("allowed_mentions")]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest
|
||||
namespace Discord.API.Rest;
|
||||
|
||||
internal class ModifyWebhookMessageParams
|
||||
{
|
||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
||||
internal class ModifyWebhookMessageParams
|
||||
{
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
[JsonProperty("embeds")]
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
[JsonProperty("allowed_mentions")]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
[JsonProperty("components")]
|
||||
public Optional<API.ActionRowComponent[]> Components { get; set; }
|
||||
}
|
||||
[JsonProperty("content")]
|
||||
public Optional<string> Content { get; set; }
|
||||
|
||||
[JsonProperty("embeds")]
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
|
||||
[JsonProperty("allowed_mentions")]
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
|
||||
[JsonProperty("components")]
|
||||
public Optional<IMessageComponent[]> Components { get; set; }
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Discord.API.Rest
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
public Optional<MessageReference> MessageReference { get; set; }
|
||||
public Optional<ActionRowComponent[]> MessageComponent { get; set; }
|
||||
public Optional<IMessageComponent[]> MessageComponent { get; set; }
|
||||
public Optional<MessageFlags?> Flags { get; set; }
|
||||
public Optional<ulong[]> Stickers { get; set; }
|
||||
public Optional<CreatePollParams> Poll { get; set; }
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Discord.API.Rest
|
||||
public Optional<bool> IsTTS { get; set; }
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
public Optional<ActionRowComponent[]> MessageComponents { get; set; }
|
||||
public Optional<IMessageComponent[]> MessageComponents { get; set; }
|
||||
public Optional<MessageFlags> Flags { get; set; }
|
||||
public Optional<CreatePollParams> Poll { get; set; }
|
||||
|
||||
@@ -44,8 +44,10 @@ namespace Discord.API.Rest
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
|
||||
var extraFlags = MessageFlags.None;
|
||||
|
||||
if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null))
|
||||
Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage;
|
||||
extraFlags |= MessageFlags.VoiceMessage;
|
||||
|
||||
var payload = new Dictionary<string, object>();
|
||||
payload["type"] = Type;
|
||||
@@ -55,20 +57,26 @@ namespace Discord.API.Rest
|
||||
data["content"] = Content.Value;
|
||||
if (IsTTS.IsSpecified)
|
||||
data["tts"] = IsTTS.Value;
|
||||
if (MessageComponents.IsSpecified)
|
||||
data["components"] = MessageComponents.Value;
|
||||
if (Embeds.IsSpecified)
|
||||
data["embeds"] = Embeds.Value;
|
||||
if (AllowedMentions.IsSpecified)
|
||||
data["allowed_mentions"] = AllowedMentions.Value;
|
||||
if (Flags.IsSpecified)
|
||||
data["flags"] = Flags.Value;
|
||||
|
||||
if (MessageComponents.IsSpecified)
|
||||
{
|
||||
data["components"] = MessageComponents.Value;
|
||||
if (MessageComponents.Value.Any(x => x.Type is not ComponentType.ActionRow))
|
||||
extraFlags |= MessageFlags.ComponentsV2;
|
||||
}
|
||||
|
||||
data["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags;
|
||||
|
||||
if (Poll.IsSpecified)
|
||||
data["poll"] = Poll.Value;
|
||||
|
||||
List<object> attachments = new();
|
||||
List<object> attachments = [];
|
||||
|
||||
for (int n = 0; n != Files.Length; n++)
|
||||
for (var n = 0; n != Files.Length; n++)
|
||||
{
|
||||
var attachment = Files[n];
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Discord.API.Rest
|
||||
public Optional<string> AvatarUrl { get; set; }
|
||||
public Optional<Embed[]> Embeds { get; set; }
|
||||
public Optional<AllowedMentions> AllowedMentions { get; set; }
|
||||
public Optional<ActionRowComponent[]> MessageComponents { get; set; }
|
||||
public Optional<IMessageComponent[]> MessageComponents { get; set; }
|
||||
public Optional<MessageFlags> Flags { get; set; }
|
||||
public Optional<string> ThreadName { get; set; }
|
||||
public Optional<ulong[]> AppliedTags { get; set; }
|
||||
@@ -37,8 +37,10 @@ namespace Discord.API.Rest
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
|
||||
var extraFlags = MessageFlags.None;
|
||||
|
||||
if (Files.Any(x => x.Waveform is not null && x.DurationSeconds is not null))
|
||||
Flags = Flags.GetValueOrDefault(MessageFlags.None) | MessageFlags.VoiceMessage;
|
||||
extraFlags |= MessageFlags.VoiceMessage;
|
||||
|
||||
var payload = new Dictionary<string, object>();
|
||||
if (Content.IsSpecified)
|
||||
@@ -51,14 +53,20 @@ namespace Discord.API.Rest
|
||||
payload["username"] = Username.Value;
|
||||
if (AvatarUrl.IsSpecified)
|
||||
payload["avatar_url"] = AvatarUrl.Value;
|
||||
if (MessageComponents.IsSpecified)
|
||||
payload["components"] = MessageComponents.Value;
|
||||
if (Embeds.IsSpecified)
|
||||
payload["embeds"] = Embeds.Value;
|
||||
if (AllowedMentions.IsSpecified)
|
||||
payload["allowed_mentions"] = AllowedMentions.Value;
|
||||
if (Flags.IsSpecified)
|
||||
payload["flags"] = Flags.Value;
|
||||
|
||||
if (MessageComponents.IsSpecified)
|
||||
{
|
||||
payload["components"] = MessageComponents.Value;
|
||||
if (MessageComponents.Value.Any(x => x.Type is not ComponentType.ActionRow))
|
||||
extraFlags |= MessageFlags.ComponentsV2;
|
||||
}
|
||||
|
||||
payload["flags"] = Flags.GetValueOrDefault(MessageFlags.None) | extraFlags;
|
||||
|
||||
if (ThreadName.IsSpecified)
|
||||
payload["thread_name"] = ThreadName.Value;
|
||||
if (AppliedTags.IsSpecified)
|
||||
|
||||
@@ -2779,6 +2779,8 @@ namespace Discord.API
|
||||
if (threadId.HasValue)
|
||||
querys.Add($"thread_id={threadId}");
|
||||
|
||||
querys.Add("with_components=true");
|
||||
|
||||
return $"{string.Join("&", querys)}";
|
||||
}
|
||||
|
||||
|
||||
@@ -308,10 +308,10 @@ namespace Discord.Rest
|
||||
Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed.");
|
||||
}
|
||||
|
||||
if (flags is not MessageFlags.None and not MessageFlags.SuppressEmbeds and not MessageFlags.SuppressNotification)
|
||||
throw new ArgumentException("The only valid MessageFlags are SuppressEmbeds, SuppressNotification and none.", nameof(flags));
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new CreateMessageParams
|
||||
{
|
||||
@@ -320,7 +320,7 @@ namespace Discord.Rest
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel(),
|
||||
MessageReference = messageReference?.ToModel(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
@@ -429,8 +429,10 @@ 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, SuppressNotification and none.", nameof(flags));
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
if (stickers != null)
|
||||
{
|
||||
@@ -444,7 +446,7 @@ namespace Discord.Rest
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageReference = messageReference?.ToModel() ?? Optional<API.MessageReference>.Unspecified,
|
||||
MessageComponent = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponent = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace Discord.Rest
|
||||
Content = text,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Components = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Components = components?.Components?.Any() ?? false ? components.Components.Select(x => x.ToModel()).ToArray() : Optional<IMessageComponent[]>.Unspecified,
|
||||
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||
},
|
||||
Tags = tagIds
|
||||
@@ -224,7 +224,7 @@ namespace Discord.Rest
|
||||
Content = text,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
Flags = flags,
|
||||
MessageComponent = components?.Components?.Any() ?? false ? components.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponent = components?.Components?.Any() ?? false ? components.Components.Select(x => x.ToModel()).ToArray() : Optional<IMessageComponent[]>.Unspecified,
|
||||
Slowmode = slowmode,
|
||||
Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified,
|
||||
Title = title,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Discord.API.Rest;
|
||||
using Discord.Net.Rest;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DataModel = Discord.API.ApplicationCommandInteractionData;
|
||||
|
||||
using Model = Discord.API.Interaction;
|
||||
|
||||
namespace Discord.Rest
|
||||
@@ -81,7 +80,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -89,7 +89,7 @@ namespace Discord.Rest
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -123,8 +123,12 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
TTS = isTTS,
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -152,12 +156,13 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -172,13 +177,15 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -194,7 +201,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -203,7 +211,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, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -218,7 +226,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist");
|
||||
|
||||
@@ -226,7 +235,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, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -240,9 +249,10 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -256,12 +266,13 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -289,23 +300,22 @@ namespace Discord.Rest
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
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<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
{
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Content = text,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -430,8 +430,8 @@ namespace Discord.Rest
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
};
|
||||
|
||||
return client.ApiClient.ModifyInteractionFollowupMessageAsync(apiArgs, message.Id, message.Token, options);
|
||||
@@ -478,8 +478,7 @@ namespace Discord.Rest
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags
|
||||
};
|
||||
|
||||
@@ -495,8 +494,7 @@ namespace Discord.Rest
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional<IMessageComponent[]>.Unspecified
|
||||
};
|
||||
|
||||
return client.ApiClient.ModifyInteractionResponseAsync(apiArgs, token, options);
|
||||
|
||||
@@ -77,7 +77,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -85,7 +86,7 @@ namespace Discord.Rest
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -119,14 +120,16 @@ 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<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
}
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
response.Data.Value.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (HasResponded)
|
||||
@@ -208,8 +211,8 @@ namespace Discord.Rest
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -227,8 +230,8 @@ namespace Discord.Rest
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
MessageComponents = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
};
|
||||
|
||||
@@ -256,12 +259,13 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -276,14 +280,15 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : MessageFlags.None,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -299,7 +304,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -308,7 +314,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, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -323,7 +329,8 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
Preconditions.NotNullOrEmpty(filePath, nameof(filePath), "Path must exist");
|
||||
|
||||
@@ -331,7 +338,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, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -345,9 +352,10 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -361,12 +369,13 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -396,19 +405,18 @@ namespace Discord.Rest
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray())
|
||||
{
|
||||
Flags = flags,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Content = text,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Discord.Rest
|
||||
}
|
||||
}
|
||||
|
||||
internal RestMessageComponentData(IMessageComponent component, BaseDiscordClient discord, IGuild guild)
|
||||
internal RestMessageComponentData(IInteractableComponent component, BaseDiscordClient discord, IGuild guild)
|
||||
{
|
||||
CustomId = component.CustomId;
|
||||
Type = component.Type;
|
||||
|
||||
@@ -3,6 +3,7 @@ using Discord.Rest;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -137,12 +138,13 @@ namespace Discord.Rest
|
||||
MessageComponent component = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -157,13 +159,15 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ??Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified
|
||||
Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -194,12 +198,13 @@ namespace Discord.Rest
|
||||
MessageComponent component = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -216,14 +221,16 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
File = fileStream is not null ? new MultipartFile(fileStream, fileName) : Optional<MultipartFile>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -254,12 +261,13 @@ namespace Discord.Rest
|
||||
MessageComponent component = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -279,14 +287,16 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
File = fileStream != null ? new MultipartFile(fileStream, fileName) : Optional<MultipartFile>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return await InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -315,7 +325,8 @@ namespace Discord.Rest
|
||||
MessageComponent component = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -323,7 +334,7 @@ namespace Discord.Rest
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -357,8 +368,12 @@ namespace Discord.Rest
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
TTS = isTTS,
|
||||
Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = component?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -390,12 +405,13 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -425,19 +441,18 @@ namespace Discord.Rest
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray())
|
||||
{
|
||||
Flags = flags,
|
||||
Flags = ephemeral
|
||||
? flags | MessageFlags.Ephemeral
|
||||
: flags == MessageFlags.None
|
||||
? Optional<MessageFlags>.Unspecified
|
||||
: flags,
|
||||
Content = text,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<API.Rest.CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
@@ -454,9 +469,10 @@ namespace Discord.Rest
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
return FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
return FollowupWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -541,8 +557,8 @@ namespace Discord.Rest
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -551,7 +567,7 @@ namespace Discord.Rest
|
||||
}
|
||||
else
|
||||
{
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty<FileAttachment>();
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? [];
|
||||
|
||||
var response = new API.Rest.UploadInteractionFileParams(attachments)
|
||||
{
|
||||
@@ -560,8 +576,8 @@ namespace Discord.Rest
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
MessageComponents = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DataModel = Discord.API.MessageComponentInteractionData;
|
||||
using InterationModel = Discord.API.Interaction;
|
||||
using Model = Discord.API.ModalInteractionData;
|
||||
|
||||
namespace Discord.Rest
|
||||
@@ -26,7 +23,7 @@ namespace Discord.Rest
|
||||
{
|
||||
CustomId = model.CustomId;
|
||||
Components = model.Components
|
||||
.SelectMany(x => x.Components)
|
||||
.SelectMany(x => x.Components.OfType<IInteractableComponent>())
|
||||
.Select(x => new RestMessageComponentData(x, discord, guild))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ namespace Discord.Rest
|
||||
|
||||
/// <inheritdoc/>
|
||||
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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -361,7 +361,7 @@ namespace Discord.Rest
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -382,7 +382,7 @@ namespace Discord.Rest
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -403,7 +403,7 @@ namespace Discord.Rest
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -423,7 +423,7 @@ namespace Discord.Rest
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -443,7 +443,7 @@ namespace Discord.Rest
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task DeleteOriginalResponseAsync(RequestOptions options = null)
|
||||
@@ -462,7 +462,7 @@ namespace Discord.Rest
|
||||
|
||||
/// <inheritdoc/>
|
||||
Task IDiscordInteraction.RespondAsync(string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions,
|
||||
MessageComponent components, Embed embed, RequestOptions options, PollProperties poll)
|
||||
MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> Task.FromResult(Respond(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll));
|
||||
/// <inheritdoc/>
|
||||
Task IDiscordInteraction.DeferAsync(bool ephemeral, RequestOptions options)
|
||||
@@ -470,45 +470,48 @@ namespace Discord.Rest
|
||||
/// <inheritdoc/>
|
||||
Task IDiscordInteraction.RespondWithModalAsync(Modal modal, RequestOptions options)
|
||||
=> Task.FromResult(RespondWithModal(modal, options));
|
||||
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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);
|
||||
MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> IDiscordInteraction.GetOriginalResponseAsync(RequestOptions options)
|
||||
=> await GetOriginalResponseAsync(options).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> IDiscordInteraction.ModifyOriginalResponseAsync(Action<MessageProperties> func, RequestOptions options)
|
||||
=> await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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);
|
||||
AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(filePath, text, fileName, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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);
|
||||
bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> IDiscordInteraction.FollowupWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable<FileAttachment> 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.");
|
||||
AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files.");
|
||||
#if NETCOREAPP3_0_OR_GREATER != true
|
||||
/// <inheritdoc/>
|
||||
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.");
|
||||
AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files.");
|
||||
/// <inheritdoc/>
|
||||
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.");
|
||||
bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files.");
|
||||
/// <inheritdoc/>
|
||||
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.");
|
||||
AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags) => throw new NotSupportedException("REST-Based interactions don't support files.");
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -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, PollProperties poll = null) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> 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<RestFollowupMessage> 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<RestFollowupMessage> 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<RestFollowupMessage> 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<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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();
|
||||
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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
public override Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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, MessageFlags flags = MessageFlags.None) => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, PollProperties poll = 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> 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)
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> 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)
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> 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)
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> 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)
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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)
|
||||
public override Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> 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!");
|
||||
|
||||
@@ -55,16 +55,16 @@ namespace Discord.Rest
|
||||
Preconditions.AtMost(allowedMentions?.UserIds?.Count ?? 0, 100, nameof(allowedMentions.UserIds), "A max of 100 user Ids are allowed.");
|
||||
|
||||
// check that user flag and user Id list are exclusive, same with role flag and role Id list
|
||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue)
|
||||
if (allowedMentions is { AllowedTypes: not null })
|
||||
{
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||
allowedMentions.UserIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||
}
|
||||
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||
allowedMentions.RoleIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
@@ -93,13 +93,13 @@ namespace Discord.Rest
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value : Optional.Create<MessageFlags?>(),
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create<API.AllowedMentions>(),
|
||||
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>() : Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional<IMessageComponent[]>.Unspecified,
|
||||
};
|
||||
return client.ApiClient.ModifyMessageAsync(channelId, msgId, apiArgs, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty<FileAttachment>();
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? [];
|
||||
|
||||
var apiArgs = new UploadFileParams(attachments)
|
||||
{
|
||||
@@ -107,7 +107,7 @@ namespace Discord.Rest
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value : Optional.Create<MessageFlags?>(),
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value.ToModel() : Optional.Create<API.AllowedMentions>(),
|
||||
MessageComponent = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>() : Optional<API.ActionRowComponent[]>.Unspecified
|
||||
MessageComponent = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? [] : Optional<IMessageComponent[]>.Unspecified
|
||||
};
|
||||
|
||||
return client.ApiClient.ModifyMessageAsync(channelId, msgId, apiArgs, options);
|
||||
|
||||
@@ -95,12 +95,12 @@ namespace Discord.Rest
|
||||
|
||||
/// <inheritdoc />
|
||||
public PurchaseNotification PurchaseNotification { get; private set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public MessageCallData? CallData { get; private set; }
|
||||
|
||||
/// <inheritdoc cref="IMessage.Components"/>
|
||||
public IReadOnlyCollection<ActionRowComponent> Components { get; private set; }
|
||||
public IReadOnlyCollection<IMessageComponent> Components { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets a collection of the mentioned users in the message.
|
||||
/// </summary>
|
||||
@@ -150,7 +150,7 @@ namespace Discord.Rest
|
||||
if (model.Activity.IsSpecified)
|
||||
{
|
||||
// create a new Activity from the API model
|
||||
Activity = new MessageActivity()
|
||||
Activity = new MessageActivity
|
||||
{
|
||||
Type = model.Activity.Value.Type.Value,
|
||||
PartyId = model.Activity.Value.PartyId.GetValueOrDefault()
|
||||
@@ -170,62 +170,9 @@ namespace Discord.Rest
|
||||
};
|
||||
}
|
||||
|
||||
if (model.Components.IsSpecified)
|
||||
{
|
||||
Components = model.Components.Value.Where(x => x.Type is ComponentType.ActionRow)
|
||||
.Select(x => new ActionRowComponent(((API.ActionRowComponent)x).Components.Select<IMessageComponent, IMessageComponent>(y =>
|
||||
{
|
||||
switch (y.Type)
|
||||
{
|
||||
case ComponentType.Button:
|
||||
{
|
||||
var parsed = (API.ButtonComponent)y;
|
||||
return new Discord.ButtonComponent(
|
||||
parsed.Style,
|
||||
parsed.Label.GetValueOrDefault(),
|
||||
parsed.Emote.IsSpecified
|
||||
? parsed.Emote.Value.Id.HasValue
|
||||
? new Emote(parsed.Emote.Value.Id.Value, parsed.Emote.Value.Name, parsed.Emote.Value.Animated.GetValueOrDefault())
|
||||
: new Emoji(parsed.Emote.Value.Name)
|
||||
: null,
|
||||
parsed.CustomId.GetValueOrDefault(),
|
||||
parsed.Url.GetValueOrDefault(),
|
||||
parsed.Disabled.GetValueOrDefault(),
|
||||
parsed.SkuId.ToNullable());
|
||||
}
|
||||
case ComponentType.SelectMenu or ComponentType.ChannelSelect or ComponentType.RoleSelect or ComponentType.MentionableSelect or ComponentType.UserSelect:
|
||||
{
|
||||
var parsed = (API.SelectMenuComponent)y;
|
||||
return new SelectMenuComponent(
|
||||
parsed.CustomId,
|
||||
parsed.Options?.Select(z => new SelectMenuOption(
|
||||
z.Label,
|
||||
z.Value,
|
||||
z.Description.GetValueOrDefault(),
|
||||
z.Emoji.IsSpecified
|
||||
? z.Emoji.Value.Id.HasValue
|
||||
? new Emote(z.Emoji.Value.Id.Value, z.Emoji.Value.Name, z.Emoji.Value.Animated.GetValueOrDefault())
|
||||
: new Emoji(z.Emoji.Value.Name)
|
||||
: null,
|
||||
z.Default.ToNullable())).ToList(),
|
||||
parsed.Placeholder.GetValueOrDefault(),
|
||||
parsed.MinValues,
|
||||
parsed.MaxValues,
|
||||
parsed.Disabled,
|
||||
parsed.Type,
|
||||
parsed.ChannelTypes.GetValueOrDefault(),
|
||||
parsed.DefaultValues.IsSpecified
|
||||
? parsed.DefaultValues.Value.Select(x => new SelectMenuDefaultValue(x.Id, x.Type))
|
||||
: Array.Empty<SelectMenuDefaultValue>()
|
||||
);
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}).ToList())).ToImmutableArray();
|
||||
}
|
||||
else
|
||||
Components = new List<ActionRowComponent>();
|
||||
Components = model.Components.IsSpecified
|
||||
? model.Components.Value.Select(x => x.ToEntity()).ToImmutableArray()
|
||||
: [];
|
||||
|
||||
if (model.Flags.IsSpecified)
|
||||
Flags = model.Flags.Value;
|
||||
@@ -236,15 +183,16 @@ namespace Discord.Rest
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var reactions = ImmutableArray.CreateBuilder<RestReaction>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
reactions.Add(RestReaction.Create(value[i]));
|
||||
foreach (var t in value)
|
||||
reactions.Add(RestReaction.Create(t));
|
||||
|
||||
_reactions = reactions.ToImmutable();
|
||||
}
|
||||
else
|
||||
_reactions = ImmutableArray.Create<RestReaction>();
|
||||
_reactions = [];
|
||||
}
|
||||
else
|
||||
_reactions = ImmutableArray.Create<RestReaction>();
|
||||
_reactions = [];
|
||||
|
||||
if (model.Interaction.IsSpecified)
|
||||
{
|
||||
@@ -289,11 +237,11 @@ namespace Discord.Rest
|
||||
? new GuildProductPurchase(model.PurchaseNotification.Value.ProductPurchase.Value.ListingId, model.PurchaseNotification.Value.ProductPurchase.Value.ProductName)
|
||||
: null);
|
||||
}
|
||||
|
||||
|
||||
if (model.Call.IsSpecified)
|
||||
CallData = new MessageCallData(model.Call.Value.Participants, model.Call.Value.EndedTimestamp.ToNullable());
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task UpdateAsync(RequestOptions options = null)
|
||||
{
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Discord.Rest
|
||||
if (model.MentionEveryone.IsSpecified)
|
||||
_isMentioningEveryone = model.MentionEveryone.Value;
|
||||
if (model.RoleMentions.IsSpecified)
|
||||
_roleMentionIds = model.RoleMentions.Value.ToImmutableArray();
|
||||
_roleMentionIds = [..model.RoleMentions.Value];
|
||||
|
||||
if (model.Attachments.IsSpecified)
|
||||
{
|
||||
@@ -92,12 +92,13 @@ namespace Discord.Rest
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var attachments = ImmutableArray.CreateBuilder<Attachment>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
attachments.Add(Attachment.Create(value[i], Discord));
|
||||
foreach (var t in value)
|
||||
attachments.Add(Attachment.Create(t, Discord));
|
||||
|
||||
_attachments = attachments.ToImmutable();
|
||||
}
|
||||
else
|
||||
_attachments = ImmutableArray.Create<Attachment>();
|
||||
_attachments = [];
|
||||
}
|
||||
|
||||
if (model.Embeds.IsSpecified)
|
||||
@@ -106,12 +107,13 @@ namespace Discord.Rest
|
||||
if (value.Length > 0)
|
||||
{
|
||||
var embeds = ImmutableArray.CreateBuilder<Embed>(value.Length);
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
embeds.Add(value[i].ToEntity());
|
||||
foreach (var t in value)
|
||||
embeds.Add(t.ToEntity());
|
||||
|
||||
_embeds = embeds.ToImmutable();
|
||||
}
|
||||
else
|
||||
_embeds = ImmutableArray.Create<Embed>();
|
||||
_embeds = [];
|
||||
}
|
||||
|
||||
var guildId = (Channel as IGuildChannel)?.GuildId;
|
||||
@@ -123,7 +125,7 @@ namespace Discord.Rest
|
||||
model.Content = text;
|
||||
}
|
||||
|
||||
if (model.ReferencedMessage.IsSpecified && model.ReferencedMessage.Value != null)
|
||||
if (model.ReferencedMessage is { IsSpecified: true, Value: not null })
|
||||
{
|
||||
var refMsg = model.ReferencedMessage.Value;
|
||||
IUser refMsgAuthor = MessageHelper.GetAuthor(Discord, guild, refMsg.Author.Value, refMsg.WebhookId.ToNullable());
|
||||
@@ -141,7 +143,7 @@ namespace Discord.Rest
|
||||
_stickers = stickers.ToImmutable();
|
||||
}
|
||||
else
|
||||
_stickers = ImmutableArray.Create<StickerItem>();
|
||||
_stickers = [];
|
||||
}
|
||||
|
||||
if (model.Resolved.IsSpecified)
|
||||
|
||||
198
src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs
Normal file
198
src/Discord.Net.Rest/Extensions/MessageComponentExtension.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Discord.Rest;
|
||||
|
||||
internal static class MessageComponentExtension
|
||||
{
|
||||
internal static IMessageComponent ToModel(this IMessageComponent component)
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
case ActionRowComponent actionRow:
|
||||
return new API.ActionRowComponent(actionRow);
|
||||
|
||||
case ButtonComponent btn:
|
||||
return new API.ButtonComponent(btn);
|
||||
|
||||
case SelectMenuComponent select:
|
||||
return new API.SelectMenuComponent(select);
|
||||
|
||||
case TextInputComponent textInput:
|
||||
return new API.TextInputComponent(textInput);
|
||||
|
||||
case TextDisplayComponent textDisplay:
|
||||
return new API.TextDisplayComponent(textDisplay);
|
||||
|
||||
case SectionComponent section:
|
||||
return new API.SectionComponent(section);
|
||||
|
||||
case ThumbnailComponent thumbnail:
|
||||
return new API.ThumbnailComponent(thumbnail);
|
||||
|
||||
case MediaGalleryComponent mediaGallery:
|
||||
return new API.MediaGalleryComponent(mediaGallery);
|
||||
|
||||
case SeparatorComponent separator:
|
||||
return new API.SeparatorComponent(separator);
|
||||
|
||||
case FileComponent file:
|
||||
return new API.FileComponent(file);
|
||||
|
||||
case ContainerComponent container:
|
||||
return new API.ContainerComponent(container);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static IMessageComponent ToEntity(this IMessageComponent component)
|
||||
{
|
||||
switch (component.Type)
|
||||
{
|
||||
case ComponentType.ActionRow:
|
||||
{
|
||||
var parsed = (API.ActionRowComponent)component;
|
||||
return new ActionRowComponent
|
||||
{
|
||||
Id = component.Id,
|
||||
Components = parsed.Components.Select(x => x.ToEntity()).ToImmutableArray()
|
||||
};
|
||||
}
|
||||
|
||||
case ComponentType.Button:
|
||||
{
|
||||
var parsed = (API.ButtonComponent)component;
|
||||
return new ButtonComponent(
|
||||
parsed.Style,
|
||||
parsed.Label.GetValueOrDefault(),
|
||||
parsed.Emote.IsSpecified
|
||||
? parsed.Emote.Value.Id.HasValue
|
||||
? new Emote(parsed.Emote.Value.Id.Value, parsed.Emote.Value.Name, parsed.Emote.Value.Animated.GetValueOrDefault())
|
||||
: new Emoji(parsed.Emote.Value.Name)
|
||||
: null,
|
||||
parsed.CustomId.GetValueOrDefault(),
|
||||
parsed.Url.GetValueOrDefault(),
|
||||
parsed.Disabled.GetValueOrDefault(),
|
||||
parsed.SkuId.ToNullable(),
|
||||
parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.SelectMenu or ComponentType.ChannelSelect or ComponentType.RoleSelect or ComponentType.MentionableSelect or ComponentType.UserSelect:
|
||||
{
|
||||
var parsed = (API.SelectMenuComponent)component;
|
||||
return new SelectMenuComponent(
|
||||
parsed.CustomId,
|
||||
parsed.Options?.Select(z => new SelectMenuOption(
|
||||
z.Label,
|
||||
z.Value,
|
||||
z.Description.GetValueOrDefault(),
|
||||
z.Emoji.IsSpecified
|
||||
? z.Emoji.Value.Id.HasValue
|
||||
? new Emote(z.Emoji.Value.Id.Value, z.Emoji.Value.Name, z.Emoji.Value.Animated.GetValueOrDefault())
|
||||
: new Emoji(z.Emoji.Value.Name)
|
||||
: null,
|
||||
z.Default.ToNullable())).ToList(),
|
||||
parsed.Placeholder.GetValueOrDefault(),
|
||||
parsed.MinValues,
|
||||
parsed.MaxValues,
|
||||
parsed.Disabled,
|
||||
parsed.Type,
|
||||
parsed.Id.ToNullable(),
|
||||
parsed.ChannelTypes.GetValueOrDefault(),
|
||||
parsed.DefaultValues.IsSpecified
|
||||
? parsed.DefaultValues.Value.Select(x => new SelectMenuDefaultValue(x.Id, x.Type))
|
||||
: []
|
||||
);
|
||||
}
|
||||
|
||||
case ComponentType.TextInput:
|
||||
{
|
||||
var parsed = (API.TextInputComponent)component;
|
||||
return new TextInputComponent(parsed.CustomId,
|
||||
parsed.Label,
|
||||
parsed.Placeholder.GetValueOrDefault(null),
|
||||
parsed.MinLength.ToNullable(),
|
||||
parsed.MaxLength.ToNullable(),
|
||||
parsed.Style,
|
||||
parsed.Required.ToNullable(),
|
||||
parsed.Value.GetValueOrDefault(null),
|
||||
parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.TextDisplay:
|
||||
{
|
||||
var parsed = (API.TextDisplayComponent)component;
|
||||
return new TextDisplayComponent(parsed.Content, parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.Section:
|
||||
{
|
||||
var parsed = (API.SectionComponent)component;
|
||||
return new SectionComponent(parsed.Id.ToNullable(),
|
||||
parsed.Components.Select(x => x.ToEntity()).ToImmutableArray(),
|
||||
parsed.Accessory.ToEntity());
|
||||
}
|
||||
|
||||
case ComponentType.Thumbnail:
|
||||
{
|
||||
var parsed = (API.ThumbnailComponent)component;
|
||||
return new ThumbnailComponent(parsed.Id.ToNullable(),
|
||||
parsed.Media.ToEntity(),
|
||||
parsed.Description.GetValueOrDefault(null),
|
||||
parsed.IsSpoiler.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.MediaGallery:
|
||||
{
|
||||
var parsed = (API.MediaGalleryComponent)component;
|
||||
|
||||
return new MediaGalleryComponent(
|
||||
parsed.Items.Select(x => new MediaGalleryItem(x.Media.ToEntity(), x.Description.GetValueOrDefault(null), x.IsSpoiler.GetValueOrDefault(false))).ToList(),
|
||||
parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.Separator:
|
||||
{
|
||||
var parsed = (API.SeparatorComponent)component;
|
||||
return new SeparatorComponent(parsed.IsDivider.ToNullable(), parsed.Spacing.ToNullable(), parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.File:
|
||||
{
|
||||
var parsed = (API.FileComponent)component;
|
||||
return new FileComponent(parsed.File.ToEntity(), parsed.IsSpoiler.ToNullable(), parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
case ComponentType.Container:
|
||||
{
|
||||
var parsed = (API.ContainerComponent)component;
|
||||
return new ContainerComponent(parsed.Components.Select(x => x.ToEntity()).ToImmutableArray(),
|
||||
parsed.AccentColor.GetValueOrDefault(null),
|
||||
parsed.IsSpoiler.ToNullable(),
|
||||
parsed.Id.ToNullable());
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static UnfurledMediaItem ToEntity(this API.UnfurledMediaItem mediaItem)
|
||||
{
|
||||
return new ResolvedUnfurledMediaItem(mediaItem.Url,
|
||||
mediaItem.ProxyUrl.GetValueOrDefault(null),
|
||||
mediaItem.Height.GetValueOrDefault(0).GetValueOrDefault(0),
|
||||
mediaItem.Width.GetValueOrDefault(0).GetValueOrDefault(0),
|
||||
mediaItem.ContentType.GetValueOrDefault(null),
|
||||
mediaItem.LoadingState.GetValueOrDefault(UnfurledMediaItemLoadingState.Unknown));
|
||||
}
|
||||
|
||||
internal static API.UnfurledMediaItem ToModel(this UnfurledMediaItem mediaItem)
|
||||
{
|
||||
return new API.UnfurledMediaItem
|
||||
{
|
||||
Url = mediaItem.Url
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Discord.Net.Converters
|
||||
{
|
||||
internal class MessageComponentConverter : JsonConverter
|
||||
{
|
||||
public static MessageComponentConverter Instance => new MessageComponentConverter();
|
||||
public static MessageComponentConverter Instance => new ();
|
||||
|
||||
public override bool CanRead => true;
|
||||
public override bool CanWrite => false;
|
||||
@@ -39,6 +40,27 @@ namespace Discord.Net.Converters
|
||||
case ComponentType.TextInput:
|
||||
messageComponent = new API.TextInputComponent();
|
||||
break;
|
||||
case ComponentType.TextDisplay:
|
||||
messageComponent = new API.TextDisplayComponent();
|
||||
break;
|
||||
case ComponentType.Thumbnail:
|
||||
messageComponent = new API.ThumbnailComponent();
|
||||
break;
|
||||
case ComponentType.Section:
|
||||
messageComponent = new API.SectionComponent();
|
||||
break;
|
||||
case ComponentType.MediaGallery:
|
||||
messageComponent = new API.MediaGalleryComponent();
|
||||
break;
|
||||
case ComponentType.Separator:
|
||||
messageComponent = new API.SeparatorComponent();
|
||||
break;
|
||||
case ComponentType.File:
|
||||
messageComponent = new API.FileComponent();
|
||||
break;
|
||||
case ComponentType.Container:
|
||||
messageComponent = new API.ContainerComponent();
|
||||
break;
|
||||
}
|
||||
serializer.Populate(jsonObject.CreateReader(), messageComponent);
|
||||
return messageComponent;
|
||||
|
||||
@@ -82,7 +82,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -90,7 +91,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -115,6 +116,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray())
|
||||
{
|
||||
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||
@@ -122,8 +130,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
|
||||
@@ -149,7 +157,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -157,7 +166,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -167,21 +176,28 @@ namespace Discord.WebSocket
|
||||
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)
|
||||
if (allowedMentions is { AllowedTypes: not null })
|
||||
{
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||
allowedMentions.UserIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||
}
|
||||
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||
allowedMentions.RoleIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
}
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.InteractionResponse
|
||||
{
|
||||
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||
@@ -191,8 +207,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions?.ToModel(),
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
TTS = isTTS,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -250,13 +266,13 @@ namespace Discord.WebSocket
|
||||
{
|
||||
var allowedMentions = args.AllowedMentions.Value;
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users)
|
||||
&& allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||
&& allowedMentions.UserIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(args.AllowedMentions));
|
||||
}
|
||||
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles)
|
||||
&& allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||
&& allowedMentions.RoleIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(args.AllowedMentions));
|
||||
}
|
||||
@@ -273,8 +289,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -283,7 +299,7 @@ namespace Discord.WebSocket
|
||||
}
|
||||
else
|
||||
{
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? Array.Empty<FileAttachment>();
|
||||
var attachments = args.Attachments.Value?.ToArray() ?? [];
|
||||
|
||||
var response = new API.Rest.UploadInteractionFileParams(attachments)
|
||||
{
|
||||
@@ -292,8 +308,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
MessageComponents = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
};
|
||||
|
||||
@@ -321,12 +337,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -335,19 +352,25 @@ namespace Discord.WebSocket
|
||||
Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
|
||||
Preconditions.ValidatePoll(poll);
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
|
||||
var args = new API.Rest.CreateWebhookMessageParams
|
||||
{
|
||||
Content = text,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified,
|
||||
Flags = flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -362,12 +385,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -385,23 +409,24 @@ namespace Discord.WebSocket
|
||||
if (allowedMentions != null && allowedMentions.AllowedTypes.HasValue)
|
||||
{
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||
allowedMentions.UserIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||
}
|
||||
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||
allowedMentions.RoleIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray())
|
||||
{
|
||||
Flags = flags,
|
||||
@@ -409,7 +434,7 @@ namespace Discord.WebSocket
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
|
||||
@@ -90,13 +90,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
internal SocketMessageComponentData(IMessageComponent component, DiscordSocketClient discord, ClientState state, SocketGuild guild, API.User dmUser)
|
||||
internal SocketMessageComponentData(IInteractableComponent component, DiscordSocketClient discord, ClientState state, SocketGuild guild, API.User dmUser)
|
||||
{
|
||||
CustomId = component.CustomId;
|
||||
Type = component.Type;
|
||||
|
||||
Value = component.Type == ComponentType.TextInput
|
||||
? (component as API.TextInputComponent).Value.Value
|
||||
? ((TextInputComponent)component).Value
|
||||
: null;
|
||||
|
||||
if (component is API.SelectMenuComponent select)
|
||||
|
||||
@@ -79,7 +79,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -87,7 +88,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -111,6 +112,12 @@ namespace Discord.WebSocket
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
}
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray())
|
||||
{
|
||||
@@ -119,8 +126,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
|
||||
@@ -136,7 +143,7 @@ namespace Discord.WebSocket
|
||||
HasResponded = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc cref="IDiscordInteraction.RespondAsync"/>
|
||||
public override async Task RespondAsync(
|
||||
string text = null,
|
||||
Embed[] embeds = null,
|
||||
@@ -146,7 +153,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -154,7 +162,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -164,21 +172,28 @@ namespace Discord.WebSocket
|
||||
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)
|
||||
if (allowedMentions is { AllowedTypes: not null })
|
||||
{
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Users) &&
|
||||
allowedMentions.UserIds != null && allowedMentions.UserIds.Count > 0)
|
||||
allowedMentions.UserIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Users flag is mutually exclusive with the list of User Ids.", nameof(allowedMentions));
|
||||
}
|
||||
|
||||
if (allowedMentions.AllowedTypes.Value.HasFlag(AllowedMentionTypes.Roles) &&
|
||||
allowedMentions.RoleIds != null && allowedMentions.RoleIds.Count > 0)
|
||||
allowedMentions.RoleIds is { Count: > 0 })
|
||||
{
|
||||
throw new ArgumentException("The Roles flag is mutually exclusive with the list of Role Ids.", nameof(allowedMentions));
|
||||
}
|
||||
}
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.InteractionResponse
|
||||
{
|
||||
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||
@@ -188,8 +203,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions?.ToModel(),
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
TTS = isTTS,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -270,9 +285,11 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
Components = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified
|
||||
? args.Flags.Value ?? Optional<MessageFlags>.Unspecified
|
||||
: Optional<MessageFlags>.Unspecified
|
||||
}
|
||||
};
|
||||
|
||||
@@ -289,8 +306,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = args.AllowedMentions.IsSpecified ? args.AllowedMentions.Value?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = apiEmbeds?.ToArray() ?? Optional<API.Embed[]>.Unspecified,
|
||||
MessageComponents = args.Components.IsSpecified
|
||||
? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Array.Empty<API.ActionRowComponent>()
|
||||
: Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
? args.Components.Value?.Components.Select(x => x.ToModel()).ToArray() ?? []
|
||||
: Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = args.Flags.IsSpecified ? args.Flags.Value ?? Optional<MessageFlags>.Unspecified : Optional<MessageFlags>.Unspecified
|
||||
};
|
||||
|
||||
@@ -318,12 +335,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -332,20 +350,24 @@ namespace Discord.WebSocket
|
||||
Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
|
||||
Preconditions.ValidatePoll(poll);
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new API.Rest.CreateWebhookMessageParams
|
||||
{
|
||||
Content = text,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -360,12 +382,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -395,11 +418,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray())
|
||||
{
|
||||
Flags = flags,
|
||||
@@ -407,7 +432,7 @@ namespace Discord.WebSocket
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using Discord.Rest;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DataModel = Discord.API.MessageComponentInteractionData;
|
||||
using InterationModel = Discord.API.Interaction;
|
||||
using Model = Discord.API.ModalInteractionData;
|
||||
|
||||
namespace Discord.WebSocket
|
||||
@@ -26,7 +24,7 @@ namespace Discord.WebSocket
|
||||
{
|
||||
CustomId = model.CustomId;
|
||||
Components = model.Components
|
||||
.SelectMany(x => x.Components)
|
||||
.SelectMany(x => x.Components.Select(y => y.ToEntity()).OfType<IInteractableComponent>())
|
||||
.Select(x => new SocketMessageComponentData(x, discord, state, guild, dmUser))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
@@ -91,15 +91,15 @@ namespace Discord.WebSocket
|
||||
/// </returns>
|
||||
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, PollProperties poll = 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> 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)
|
||||
public override Task<RestFollowupMessage> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
public override Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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)
|
||||
public override Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> 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<FileAttachment> 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)
|
||||
public override Task RespondWithFilesAsync(IEnumerable<FileAttachment> 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, MessageFlags flags = MessageFlags.None)
|
||||
=> throw new NotSupportedException("Autocomplete interactions don't support this method!");
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -77,7 +77,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -85,7 +86,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -110,6 +111,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.InteractionResponse
|
||||
{
|
||||
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||
@@ -119,8 +127,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
TTS = isTTS,
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
}
|
||||
};
|
||||
@@ -183,7 +191,8 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
@@ -191,7 +200,7 @@ namespace Discord.WebSocket
|
||||
if (!InteractionHelper.CanSendResponse(this) && Discord.ResponseInternalTimeCheck)
|
||||
throw new TimeoutException($"Cannot respond to an interaction after {InteractionHelper.ResponseTimeLimit} seconds!");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -216,6 +225,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var response = new API.Rest.UploadInteractionFileParams(attachments?.ToArray())
|
||||
{
|
||||
Type = InteractionResponseType.ChannelMessageWithSource,
|
||||
@@ -223,8 +239,8 @@ namespace Discord.WebSocket
|
||||
AllowedMentions = allowedMentions != null ? allowedMentions?.ToModel() : Optional<API.AllowedMentions>.Unspecified,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Flags = ephemeral ? MessageFlags.Ephemeral : Optional<MessageFlags>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Flags = flags,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
|
||||
@@ -250,12 +266,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -264,19 +281,24 @@ namespace Discord.WebSocket
|
||||
Preconditions.AtMost(embeds.Length, 10, nameof(embeds), "A max of 10 embeds are allowed.");
|
||||
Preconditions.ValidatePoll(poll);
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new API.Rest.CreateWebhookMessageParams
|
||||
{
|
||||
Content = text ?? Optional<string>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Select(x => x.ToModel()).ToArray(),
|
||||
Components = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
Components = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified,
|
||||
Flags = flags,
|
||||
};
|
||||
|
||||
if (ephemeral)
|
||||
args.Flags = MessageFlags.Ephemeral;
|
||||
|
||||
return InteractionHelper.SendFollowupAsync(Discord.Rest, args, Token, Channel, options);
|
||||
}
|
||||
|
||||
@@ -291,12 +313,13 @@ namespace Discord.WebSocket
|
||||
MessageComponent components = null,
|
||||
Embed embed = null,
|
||||
RequestOptions options = null,
|
||||
PollProperties poll = null)
|
||||
PollProperties poll = null,
|
||||
MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
if (!IsValidToken)
|
||||
throw new InvalidOperationException("Interaction token is no longer valid");
|
||||
|
||||
embeds ??= Array.Empty<Embed>();
|
||||
embeds ??= [];
|
||||
if (embed != null)
|
||||
embeds = new[] { embed }.Concat(embeds).ToArray();
|
||||
|
||||
@@ -326,11 +349,13 @@ namespace Discord.WebSocket
|
||||
}
|
||||
}
|
||||
|
||||
var flags = MessageFlags.None;
|
||||
|
||||
if (components?.Components?.Any(x => x.Type != ComponentType.ActionRow) ?? false)
|
||||
flags |= MessageFlags.ComponentsV2;
|
||||
if (ephemeral)
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
|
||||
Preconditions.ValidateMessageFlags(flags);
|
||||
|
||||
var args = new API.Rest.UploadWebhookFileParams(attachments.ToArray())
|
||||
{
|
||||
Flags = flags,
|
||||
@@ -338,7 +363,7 @@ namespace Discord.WebSocket
|
||||
IsTTS = isTTS,
|
||||
Embeds = embeds.Any() ? embeds.Select(x => x.ToModel()).ToArray() : Optional<API.Embed[]>.Unspecified,
|
||||
AllowedMentions = allowedMentions?.ToModel() ?? Optional<API.AllowedMentions>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified,
|
||||
MessageComponents = components?.Components.Select(x => x.ToModel()).ToArray() ?? Optional<IMessageComponent[]>.Unspecified,
|
||||
Poll = poll?.ToModel() ?? Optional<CreatePollParams>.Unspecified
|
||||
};
|
||||
return InteractionHelper.SendFollowupAsync(Discord, args, Token, Channel, options);
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace Discord.WebSocket
|
||||
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
|
||||
/// <exception cref="InvalidOperationException">The parameters provided were invalid or the token was invalid.</exception>
|
||||
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, PollProperties poll = null);
|
||||
bool ephemeral = false, AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a file attachment.
|
||||
@@ -237,11 +237,11 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
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, PollProperties poll = null)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(fileStream, fileName))
|
||||
{
|
||||
await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,11 +264,11 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
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, PollProperties poll = null)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(filePath, fileName))
|
||||
{
|
||||
await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
await RespondWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,8 +290,8 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
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, PollProperties poll = null)
|
||||
=> RespondWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> RespondWithFilesAsync([attachment], text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <summary>
|
||||
/// Responds to this interaction with a collection of file attachments.
|
||||
@@ -311,7 +311,7 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task RespondWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -329,7 +329,7 @@ namespace Discord.WebSocket
|
||||
/// The sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -349,11 +349,11 @@ namespace Discord.WebSocket
|
||||
/// The sent message.
|
||||
/// </returns>
|
||||
public async Task<RestFollowupMessage> 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)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(fileStream, fileName))
|
||||
{
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,11 +375,11 @@ namespace Discord.WebSocket
|
||||
/// The sent message.
|
||||
/// </returns>
|
||||
public async Task<RestFollowupMessage> 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)
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
{
|
||||
using (var file = new FileAttachment(filePath, fileName))
|
||||
{
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll).ConfigureAwait(false);
|
||||
return await FollowupWithFileAsync(file, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,8 +401,8 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public Task<RestFollowupMessage> 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)
|
||||
=> FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None)
|
||||
=> FollowupWithFilesAsync(new FileAttachment[] { attachment }, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a followup message for this interaction.
|
||||
@@ -422,7 +422,7 @@ namespace Discord.WebSocket
|
||||
/// contains the sent message.
|
||||
/// </returns>
|
||||
public abstract Task<RestFollowupMessage> FollowupWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
AllowedMentions allowedMentions = null, MessageComponent components = null, Embed embed = null, RequestOptions options = null, PollProperties poll = null, MessageFlags flags = MessageFlags.None);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original response for this interaction.
|
||||
@@ -509,26 +509,26 @@ namespace Discord.WebSocket
|
||||
=> await ModifyOriginalResponseAsync(func, options).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
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);
|
||||
Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await RespondAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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);
|
||||
MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupAsync(text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> IDiscordInteraction.FollowupWithFilesAsync(IEnumerable<FileAttachment> 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);
|
||||
bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
#if NETCOREAPP3_0_OR_GREATER != true
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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<IUserMessage> IDiscordInteraction.FollowupWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(fileStream, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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<IUserMessage> IDiscordInteraction.FollowupWithFileAsync(string filePath, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(filePath, fileName, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
/// <inheritdoc/>
|
||||
async Task<IUserMessage> 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<IUserMessage> IDiscordInteraction.FollowupWithFileAsync(FileAttachment attachment, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options, PollProperties poll, MessageFlags flags)
|
||||
=> await FollowupWithFileAsync(attachment, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options, poll, flags).ConfigureAwait(false);
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user