private async Task AcknowledgeInteraction(DiscordInteraction interaction, bool ephemeral) { var builder = new DiscordInteractionResponseBuilder() .AsEphemeral(ephemeral); await interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder); }
public DiscordMovieUserInterface( DiscordInteraction interactionContext, IMovieSearcher movieSearcher) { _interactionContext = interactionContext; _movieSearcher = movieSearcher; }
private void Handle(string cmdName, DiscordInteraction interaction, List <SlashCommandArgument> arguments) { var localCommand = _handlerDict[cmdName]; var handler = (SlashCommand)Activator.CreateInstance(localCommand.HandlerType); handler.Prepare(interaction); if (arguments != null) { foreach (var suppliedArg in arguments) { var property = localCommand.Parameters[suppliedArg.Name]; object value = suppliedArg.Value; switch (suppliedArg.Type) { case CommandOptionType.Channel: value = interaction.Data.Resolved.Channels[ulong.Parse(suppliedArg.Value)]; break; case CommandOptionType.Role: value = interaction.Data.Resolved.Roles[ulong.Parse(suppliedArg.Value)]; break; case CommandOptionType.User: if (property.PropertyType == typeof(DiscordUser)) { value = interaction.Data.Resolved.Users[ulong.Parse(suppliedArg.Value)]; } else { value = interaction.Data.Resolved.Members[ulong.Parse(suppliedArg.Value)]; } break; case CommandOptionType.Mentionable: value = ResolveObject(interaction.Data.Resolved, ulong.Parse(suppliedArg.Value)); break; default: value = Convert.ChangeType(value, property.PropertyType); break; } property.SetValue(handler, value); } } if (localCommand.Delayed) { interaction.Respond(InteractionCallbackType.DelayedMessage); interaction.ModifyResponse(handler.Handle()); } else { interaction.Respond(InteractionCallbackType.RespondWithMessage, handler.Handle()); } }
internal void Prepare(DiscordInteraction interaction) { Client = (DiscordSocketClient)interaction.Client; Caller = interaction.User; CallerMember = interaction.Member; Channel = interaction.Channel; Guild = interaction.Guild; }
public MovieRequestingWorkflow CreateRequestingWorkflow(DiscordInteraction interaction, int categoryId) { var settings = _settingsProvider.Provide(); return(new MovieRequestingWorkflow(new MovieUserRequester(interaction.User.Id.ToString(), interaction.User.Username), categoryId, GetMovieClient <IMovieSearcher>(settings), GetMovieClient <IMovieRequester>(settings), new DiscordMovieUserInterface(interaction, GetMovieClient <IMovieSearcher>(settings)), CreateMovieNotificationWorkflow(interaction, settings))); }
public CommandContext(DiscordClient client, DiscordInteraction interaction, bool isEphemeral) { if (interaction.Guild is null) { throw new ArgumentException("Only guild interactions are supported.", nameof(interaction)); } Client = client; Interaction = interaction; IsEphemeral = isEphemeral; }
public TvShowRequestingWorkflow CreateRequestingWorkflow(DiscordInteraction interaction, int categoryId) { var settings = _settingsProvider.Provide(); return(new TvShowRequestingWorkflow(new TvShowUserRequester(interaction.User.Id.ToString(), interaction.User.Username), categoryId, GetTvShowClient <ITvShowSearcher>(settings), GetTvShowClient <ITvShowRequester>(settings), new DiscordTvShowUserInterface(interaction), CreateMovieNotificationWorkflow(interaction, settings, GetTvShowClient <ITvShowSearcher>(settings)), _tvShowsSettingsProvider.Provide())); }
private IMovieNotificationWorkflow CreateMovieNotificationWorkflow(DiscordInteraction interaction, DiscordSettings settings) { var userInterface = new DiscordMovieUserInterface(interaction, GetMovieClient <IMovieSearcher>(settings)); IMovieNotificationWorkflow movieNotificationWorkflow = new DisabledMovieNotificationWorkflow(userInterface); if (settings.NotificationMode != NotificationMode.Disabled) { movieNotificationWorkflow = new MovieNotificationWorkflow(_notificationsRepository, userInterface, GetMovieClient <IMovieSearcher>(settings), settings.AutomaticallyNotifyRequesters); } return(movieNotificationWorkflow); }
private ITvShowNotificationWorkflow CreateMovieNotificationWorkflow(DiscordInteraction interaction, DiscordSettings settings, ITvShowSearcher tvShowSearcher) { var userInterface = new DiscordTvShowUserInterface(interaction); ITvShowNotificationWorkflow movieNotificationWorkflow = new DisabledTvShowNotificationWorkflow(userInterface); if (settings.NotificationMode != NotificationMode.Disabled) { movieNotificationWorkflow = new TvShowNotificationWorkflow(_notificationsRepository, userInterface, tvShowSearcher, settings.AutomaticallyNotifyRequesters); } return(movieNotificationWorkflow); }
private async Task HandleInvalidInteraction(DiscordInteraction interaction) { var at = this.Config.ResponseBehavior switch { InteractionResponseBehavior.Ack => interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate), InteractionResponseBehavior.Respond => interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, new() { Content = this.Config.ResponseMessage, IsEphemeral = true }), InteractionResponseBehavior.Ignore => Task.CompletedTask, _ => throw new ArgumentException("Unknown enum value.") }; await at; } }
internal ModalSubmitEventArgs(DiscordInteraction interaction) { this.Interaction = interaction; var dict = new Dictionary <string, string>(); foreach (var component in interaction.Data._components) { if (component.Components.First() is TextInputComponent input) { dict.Add(input.CustomId, input.Value); } } this.Values = dict; }
public Task HandleInteraction(BaseDiscordClient discord, DiscordInteraction interact, DiscordSlashClient c) { // This should not get here, but check just in case. if (interact.Type == InteractionType.Ping) { return(Task.CompletedTask); } // Create a cancellation token for the event in which it is needed. var cancelSource = new CancellationTokenSource(); // Store the command task in a ConcurrentDictionary and continue with execution to not hodlup the webhook response. RunningInteractions[interact] = new( Task.Run(async() => await ExecuteInteraction(discord, interact, c, cancelSource.Token)), cancelSource); return(Task.CompletedTask); }
private async Task ExecuteInteraction(BaseDiscordClient discord, DiscordInteraction interact, DiscordSlashClient c, CancellationToken cancellationToken) { try { cancellationToken.ThrowIfCancellationRequested(); if (interact.Data is null) { throw new Exception("Interact object has no command data."); } if (Commands.TryGetValue(interact.Data.Name, out var cmd)) { // TODO: Check how subcommands are returned. // TODO: Do argument parsing. var context = new InteractionContext(c, interact); if (interact.Data.Options is not null) { var args = await GetRawArguments(interact.Data.Options); cmd.ExecuteCommand(discord, context, args); } else { cmd.ExecuteCommand(discord, context); } } } catch (Exception ex) { _logger.LogError(ex, "Interaction Handler failed"); } finally { RunningInteractions.TryRemove(interact, out _); } }
public ITvShowNotificationWorkflow CreateNotificationWorkflow(DiscordInteraction interaction) { var settings = _settingsProvider.Provide(); return(CreateMovieNotificationWorkflow(interaction, settings, GetTvShowClient <ITvShowSearcher>(settings))); }
public async Task HandleAsync(DiscordInteraction interaction) { if (interaction.Guild is null) { throw new Exception("User tried to execute a command in DMs, somehow."); } var request = CommandRequest.FromInteractionData(interaction.Data); if (!_commands.ContainsKey(request.FullName)) { throw new Exception($"An interaction was created, but no command was registered for it: '{request.FullName}'"); } var command = _commands[request.FullName]; using var scope = _provider.CreateScope(); if (ActivatorUtilities.CreateInstance(scope.ServiceProvider, command.Class) is not ICommand instance) { throw new Exception($"Could not create an instance of a type {command.Class} for a command '{request.FullName}'."); } var context = new CommandContext(_client, interaction, instance.Ephemeral); await AcknowledgeInteraction(interaction, instance.Ephemeral); CommandResult result; try { if (request.Parameters is not null) { command.FillParameters(instance, request.Parameters, interaction.Data.Resolved); } var checkResult = await command.RunChecksAsync(context, _provider); if (!checkResult.IsSuccessful) { await context.RespondWithAccessDeniedAsync(checkResult.Reason); return; } result = await instance.HandleAsync(context); } catch (Exception e) { await context.RespondWithCriticalErrorAsync(e); throw; } if (instance.Ephemeral) { await RespondWithMessageAsync(context, result); } else { await RespondWithEmbedAsync(context, result); } }
public DiscordTvShowUserInterface(DiscordInteraction interactionContext) { _interactionContext = interactionContext; }
internal abstract void Handle(DiscordSocketClient client, DiscordInteraction interaction);
public IMovieNotificationWorkflow CreateNotificationWorkflow(DiscordInteraction interaction) { var settings = _settingsProvider.Provide(); return(CreateMovieNotificationWorkflow(interaction, settings)); }
public FormSelectMenuEventArgs(DiscordSocketClient client, DiscordInteraction interaction) : base(client, interaction) { Values = interaction.Data.SelectMenuValues; }
public InteractionContext(DiscordSlashClient c, DiscordInteraction i) { _client = c; Interaction = i; }
/// <summary> /// Sends a paginated message in response to an interaction. /// <para> /// <b>Pass the interaction directly. Interactivity will ACK it.</b> /// </para> /// </summary> /// <param name="interaction">The interaction to create a response to.</param> /// <param name="ephemeral">Whether the response should be ephemeral.</param> /// <param name="user">The user to listen for button presses from.</param> /// <param name="pages">The pages to paginate.</param> /// <param name="buttons">Optional: custom buttons</param> /// <param name="behaviour">Pagination behaviour.</param> /// <param name="deletion">Deletion behaviour</param> /// <param name="token">A custom cancellation token that can be cancelled at any point.</param> /// <param name="asEditResponse">If the response as edit of previous response.</param> public static Task SendPaginatedResponseAsync(this DiscordInteraction interaction, bool ephemeral, DiscordUser user, IEnumerable <Page> pages, PaginationButtons buttons = null, PaginationBehaviour?behaviour = default, ButtonPaginationBehavior?deletion = default, CancellationToken token = default, bool asEditResponse = false) => ChannelExtensions.GetInteractivity(interaction.Channel).SendPaginatedResponseAsync(interaction, ephemeral, user, pages, buttons, behaviour, deletion, token, asEditResponse);