140 lines
5.7 KiB
C#
140 lines
5.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Discord.Interactions
|
|
{
|
|
/// <summary>
|
|
/// Represents a cached object initialization delegate.
|
|
/// </summary>
|
|
/// <param name="args">Property arguments array.</param>
|
|
/// <returns>
|
|
/// Returns the constructed object.
|
|
/// </returns>
|
|
public delegate IModal ModalInitializer(object[] args);
|
|
|
|
/// <summary>
|
|
/// Represents the info class of an <see cref="IModal"/> form.
|
|
/// </summary>
|
|
public class ModalInfo
|
|
{
|
|
internal readonly InteractionService _interactionService;
|
|
internal readonly ModalInitializer _initializer;
|
|
|
|
/// <summary>
|
|
/// Gets the title of this modal.
|
|
/// </summary>
|
|
public string Title { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="IModal"/> implementation used to initialize this object.
|
|
/// </summary>
|
|
public Type Type { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a collection of the components of this modal.
|
|
/// </summary>
|
|
public IReadOnlyCollection<InputComponentInfo> Components { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a collection of the text components of this modal.
|
|
/// </summary>
|
|
public IReadOnlyCollection<TextInputComponentInfo> TextComponents { get; }
|
|
|
|
internal ModalInfo(Builders.ModalBuilder builder)
|
|
{
|
|
Title = builder.Title;
|
|
Type = builder.Type;
|
|
Components = builder.Components.Select(x => x switch
|
|
{
|
|
Builders.TextInputComponentBuilder textComponent => textComponent.Build(this),
|
|
_ => throw new InvalidOperationException($"{x.GetType().FullName} isn't a supported modal input component builder type.")
|
|
}).ToImmutableArray();
|
|
|
|
TextComponents = Components.OfType<TextInputComponentInfo>().ToImmutableArray();
|
|
|
|
_interactionService = builder._interactionService;
|
|
_initializer = builder.ModalInitializer;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an <see cref="IModal"/> and fills it with provided message components.
|
|
/// </summary>
|
|
/// <param name="modalInteraction"><see cref="IModalInteraction"/> that will be injected into the modal.</param>
|
|
/// <returns>
|
|
/// A <see cref="IModal"/> filled with the provided components.
|
|
/// </returns>
|
|
[Obsolete("This method is no longer supported with the introduction of Component TypeConverters, please use the CreateModalAsync method.")]
|
|
public IModal CreateModal(IModalInteraction modalInteraction, bool throwOnMissingField = false)
|
|
{
|
|
var args = new object[Components.Count];
|
|
var components = modalInteraction.Data.Components.ToList();
|
|
|
|
for (var i = 0; i < Components.Count; i++)
|
|
{
|
|
var input = Components.ElementAt(i);
|
|
var component = components.Find(x => x.CustomId == input.CustomId);
|
|
|
|
if (component is null)
|
|
{
|
|
if (!throwOnMissingField)
|
|
args[i] = input.DefaultValue;
|
|
else
|
|
throw new InvalidOperationException($"Modal interaction is missing the required field: {input.CustomId}");
|
|
}
|
|
else
|
|
args[i] = component.Value;
|
|
}
|
|
|
|
return _initializer(args);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an <see cref="IModal"/> and fills it with provided message components.
|
|
/// </summary>
|
|
/// <param name="context">Context of the <see cref="IModalInteraction"/> that will be injected into the modal.</param>
|
|
/// <param name="services">Services to be passed onto the <see cref="ComponentTypeConverter"/>s of the modal fields.</param>
|
|
/// <param name="throwOnMissingField">Whether or not this method should exit on encountering a missing modal field.</param>
|
|
/// <returns>
|
|
/// A <see cref="TypeConverterResult"/> if a type conversion has failed, else a <see cref="ParseResult"/>.
|
|
/// </returns>
|
|
public async Task<IResult> CreateModalAsync(IInteractionContext context, IServiceProvider services = null, bool throwOnMissingField = false)
|
|
{
|
|
if (context.Interaction is not IModalInteraction modalInteraction)
|
|
return TypeConverterResult.FromError(InteractionCommandError.Unsuccessful, "Provided context doesn't belong to a Modal Interaction.");
|
|
|
|
services ??= EmptyServiceProvider.Instance;
|
|
|
|
var args = new object[Components.Count];
|
|
var components = modalInteraction.Data.Components.ToList();
|
|
|
|
for (var i = 0; i < Components.Count; i++)
|
|
{
|
|
var input = Components.ElementAt(i);
|
|
var component = components.Find(x => x.CustomId == input.CustomId);
|
|
|
|
if (component is null)
|
|
{
|
|
if (!throwOnMissingField)
|
|
args[i] = input.DefaultValue;
|
|
else
|
|
return TypeConverterResult.FromError(InteractionCommandError.BadArgs, $"Modal interaction is missing the required field: {input.CustomId}");
|
|
}
|
|
else
|
|
{
|
|
var readResult = await input.TypeConverter.ReadAsync(context, component, services).ConfigureAwait(false);
|
|
|
|
if (!readResult.IsSuccess)
|
|
return readResult;
|
|
|
|
args[i] = readResult.Value;
|
|
}
|
|
}
|
|
|
|
return TypeConverterResult.FromSuccess(_initializer(args));
|
|
}
|
|
}
|
|
}
|