using Discord.Interactions.Builders; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; namespace Discord.Interactions { /// /// Represents the info class of an attribute based method for handling Component Interaction events. /// public class ComponentCommandInfo : CommandInfo { /// public override IReadOnlyCollection Parameters { get; } /// public override bool SupportsWildCards => true; internal ComponentCommandInfo(ComponentCommandBuilder builder, ModuleInfo module, InteractionService commandService) : base(builder, module, commandService) { Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray(); } /// public override async Task ExecuteAsync(IInteractionContext context, IServiceProvider services) => await ExecuteAsync(context, services, null).ConfigureAwait(false); /// /// Execute this command using dependency injection. /// /// Context that will be injected to the . /// Services that will be used while initializing the . /// Provide additional string parameters to the method along with the auto generated parameters. /// /// A task representing the asynchronous command execution process. /// public async Task ExecuteAsync(IInteractionContext context, IServiceProvider services, params string[] additionalArgs) { if (context.Interaction is not IComponentInteraction componentInteraction) return ExecuteResult.FromError(InteractionCommandError.ParseFailed, $"Provided {nameof(IInteractionContext)} doesn't belong to a Message Component Interaction"); return await ExecuteAsync(context, Parameters, additionalArgs, componentInteraction.Data, services); } /// public async Task ExecuteAsync(IInteractionContext context, IEnumerable paramList, IEnumerable wildcardCaptures, IComponentInteractionData data, IServiceProvider services) { var paramCount = paramList.Count(); var captureCount = wildcardCaptures?.Count() ?? 0; if (context.Interaction is not IComponentInteraction messageComponent) return ExecuteResult.FromError(InteractionCommandError.ParseFailed, $"Provided {nameof(IInteractionContext)} doesn't belong to a Component Command Interaction"); try { var args = new object[paramCount]; for (var i = 0; i < paramCount; i++) { var parameter = Parameters.ElementAt(i); var isCapture = i < captureCount; if (isCapture ^ parameter.IsRouteSegmentParameter) return await InvokeEventAndReturn(context, ExecuteResult.FromError(InteractionCommandError.BadArgs, "Argument type and parameter type didn't match (Wild Card capture/Component value)")).ConfigureAwait(false); var readResult = isCapture ? await parameter.TypeReader.ReadAsync(context, wildcardCaptures.ElementAt(i), services).ConfigureAwait(false) : await parameter.TypeConverter.ReadAsync(context, data, services).ConfigureAwait(false); if (!readResult.IsSuccess) return await InvokeEventAndReturn(context, readResult).ConfigureAwait(false); args[i] = readResult.Value; } return await RunAsync(context, args, services).ConfigureAwait(false); } catch (Exception ex) { return await InvokeEventAndReturn(context, ExecuteResult.FromError(ex)).ConfigureAwait(false); } } protected override Task InvokeModuleEvent(IInteractionContext context, IResult result) => CommandService._componentCommandExecutedEvent.InvokeAsync(this, context, result); protected override string GetLogString(IInteractionContext context) { if (context.Guild != null) return $"Component Interaction: \"{base.ToString()}\" for {context.User} in {context.Guild}/{context.Channel}"; else return $"Component Interaction: \"{base.ToString()}\" for {context.User} in {context.Channel}"; } } }