diff --git a/src/Discord.Net.Interactions/Builders/ModuleClassBuilder.cs b/src/Discord.Net.Interactions/Builders/ModuleClassBuilder.cs index 07e62b1f1..faf663304 100644 --- a/src/Discord.Net.Interactions/Builders/ModuleClassBuilder.cs +++ b/src/Discord.Net.Interactions/Builders/ModuleClassBuilder.cs @@ -309,8 +309,8 @@ namespace Discord.Interactions.Builders if (parameters.Count(x => typeof(IModal).IsAssignableFrom(x.ParameterType)) > 1) throw new InvalidOperationException($"A modal command can only have one {nameof(IModal)} parameter."); - if (!parameters.All(x => x.ParameterType == typeof(string) || typeof(IModal).IsAssignableFrom(x.ParameterType))) - throw new InvalidOperationException($"All parameters of a modal command must be either a string or an implementation of {nameof(IModal)}"); + if (!typeof(IModal).IsAssignableFrom(parameters.Last().ParameterType)) + throw new InvalidOperationException($"Last parameter of a modal command must be an implementation of {nameof(IModal)}"); var attributes = methodInfo.GetCustomAttributes(); diff --git a/src/Discord.Net.Interactions/Builders/Parameters/ModalCommandParameterBuilder.cs b/src/Discord.Net.Interactions/Builders/Parameters/ModalCommandParameterBuilder.cs index 276b2e717..8cb9b3ab9 100644 --- a/src/Discord.Net.Interactions/Builders/Parameters/ModalCommandParameterBuilder.cs +++ b/src/Discord.Net.Interactions/Builders/Parameters/ModalCommandParameterBuilder.cs @@ -20,6 +20,11 @@ namespace Discord.Interactions.Builders /// public bool IsModalParameter => Modal is not null; + /// + /// Gets the assigned to this parameter, if is . + /// + public TypeReader TypeReader { get; private set; } + internal ModalCommandParameterBuilder(ICommandBuilder command) : base(command) { } /// @@ -35,6 +40,8 @@ namespace Discord.Interactions.Builders { if (typeof(IModal).IsAssignableFrom(type)) Modal = ModalUtils.GetOrAdd(type, Command.Module.InteractionService); + else + TypeReader = Command.Module.InteractionService.GetTypeReader(type); return base.SetParameterType(type); } diff --git a/src/Discord.Net.Interactions/Info/Commands/ModalCommandInfo.cs b/src/Discord.Net.Interactions/Info/Commands/ModalCommandInfo.cs index 2b9306fda..1934b2293 100644 --- a/src/Discord.Net.Interactions/Info/Commands/ModalCommandInfo.cs +++ b/src/Discord.Net.Interactions/Info/Commands/ModalCommandInfo.cs @@ -47,24 +47,40 @@ namespace Discord.Interactions try { - var args = new List(); + var args = new object[Parameters.Count]; + var captureCount = additionalArgs.Length; - if (additionalArgs is not null) - args.AddRange(additionalArgs); + for(var i = 0; i < Parameters.Count; i++) + { + var parameter = Parameters.ElementAt(i); - var modalResult = await Modal.CreateModalAsync(context, services, Module.CommandService._exitOnMissingModalField).ConfigureAwait(false); + if(i < captureCount) + { + var readResult = await parameter.TypeReader.ReadAsync(context, additionalArgs[i], services).ConfigureAwait(false); - if(!modalResult.IsSuccess) - { - await InvokeModuleEvent(context, modalResult).ConfigureAwait(false); - return modalResult; - } + if(!readResult.IsSuccess) + { + await InvokeModuleEvent(context, readResult).ConfigureAwait(false); + return readResult; + } + args[i] = readResult.Value; + } + else + { + var modalResult = await Modal.CreateModalAsync(context, services, Module.CommandService._exitOnMissingModalField).ConfigureAwait(false); - if(modalResult is ParseResult parseResult) - args.Add(parseResult.Value); - else - return ExecuteResult.FromError(InteractionCommandError.BadArgs, "Command parameter parsing failed for an unknown reason."); + if (!modalResult.IsSuccess) + { + await InvokeModuleEvent(context, modalResult).ConfigureAwait(false); + return modalResult; + } + if (modalResult is ParseResult parseResult) + args[i] = parseResult.Value; + else + return ExecuteResult.FromError(InteractionCommandError.BadArgs, "Command parameter parsing failed for an unknown reason."); + } + } return await RunAsync(context, args.ToArray(), services); } catch (Exception ex) diff --git a/src/Discord.Net.Interactions/Info/Parameters/ModalCommandParameterInfo.cs b/src/Discord.Net.Interactions/Info/Parameters/ModalCommandParameterInfo.cs index 28162e109..cafb0b7f5 100644 --- a/src/Discord.Net.Interactions/Info/Parameters/ModalCommandParameterInfo.cs +++ b/src/Discord.Net.Interactions/Info/Parameters/ModalCommandParameterInfo.cs @@ -15,7 +15,12 @@ namespace Discord.Interactions /// /// Gets whether this parameter is an /// - public bool IsModalParameter => Modal is not null; + public bool IsModalParameter { get; } + + /// + /// Gets the assigned to this parameter, if is . + /// + public TypeReader TypeReader { get; } /// public new ModalCommandInfo Command => base.Command as ModalCommandInfo; @@ -23,6 +28,8 @@ namespace Discord.Interactions internal ModalCommandParameterInfo(ModalCommandParameterBuilder builder, ICommandInfo command) : base(builder, command) { Modal = builder.Modal; + IsModalParameter = builder.IsModalParameter; + TypeReader = builder.TypeReader; } } } diff --git a/src/Discord.Net.Interactions/TypeReaders/DefaultSnowflakeReader.cs b/src/Discord.Net.Interactions/TypeReaders/DefaultSnowflakeReader.cs index 3b4e01165..eebce8877 100644 --- a/src/Discord.Net.Interactions/TypeReaders/DefaultSnowflakeReader.cs +++ b/src/Discord.Net.Interactions/TypeReaders/DefaultSnowflakeReader.cs @@ -13,7 +13,7 @@ namespace Discord.Interactions if (!ulong.TryParse(option, out var snowflake)) return TypeConverterResult.FromError(InteractionCommandError.ConvertFailed, $"{option} isn't a valid snowflake thus cannot be converted into {typeof(T).Name}"); - var result = GetEntity(snowflake, context); + var result = await GetEntity(snowflake, context).ConfigureAwait(false); if (result is not null) return TypeConverterResult.FromSuccess(result); @@ -37,7 +37,7 @@ namespace Discord.Interactions } internal sealed class DefaultRoleReader : DefaultSnowflakeReader - where T : class, IUser + where T : class, IRole { protected override Task GetEntity(ulong id, IInteractionContext ctx) => Task.FromResult(ctx.Guild?.GetRole(id) as T); }