Exemplo n.º 1
0
        private async Task AcknowledgeInteraction(DiscordInteraction interaction, bool ephemeral)
        {
            var builder = new DiscordInteractionResponseBuilder()
                          .AsEphemeral(ephemeral);

            await interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder);
        }
Exemplo n.º 2
0
 public DiscordMovieUserInterface(
     DiscordInteraction interactionContext,
     IMovieSearcher movieSearcher)
 {
     _interactionContext = interactionContext;
     _movieSearcher      = movieSearcher;
 }
Exemplo n.º 3
0
        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());
            }
        }
Exemplo n.º 4
0
        internal void Prepare(DiscordInteraction interaction)
        {
            Client = (DiscordSocketClient)interaction.Client;

            Caller       = interaction.User;
            CallerMember = interaction.Member;

            Channel = interaction.Channel;
            Guild   = interaction.Guild;
        }
Exemplo n.º 5
0
        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)));
        }
Exemplo n.º 6
0
        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;
        }
Exemplo n.º 7
0
        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()));
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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;
        }
    }
Exemplo n.º 11
0
        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;
        }
Exemplo n.º 12
0
        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);
        }
Exemplo n.º 13
0
        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 _);
            }
        }
Exemplo n.º 14
0
        public ITvShowNotificationWorkflow CreateNotificationWorkflow(DiscordInteraction interaction)
        {
            var settings = _settingsProvider.Provide();

            return(CreateMovieNotificationWorkflow(interaction, settings, GetTvShowClient <ITvShowSearcher>(settings)));
        }
Exemplo n.º 15
0
        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);
            }
        }
Exemplo n.º 16
0
 public DiscordTvShowUserInterface(DiscordInteraction interactionContext)
 {
     _interactionContext = interactionContext;
 }
Exemplo n.º 17
0
 internal abstract void Handle(DiscordSocketClient client, DiscordInteraction interaction);
Exemplo n.º 18
0
        public IMovieNotificationWorkflow CreateNotificationWorkflow(DiscordInteraction interaction)
        {
            var settings = _settingsProvider.Provide();

            return(CreateMovieNotificationWorkflow(interaction, settings));
        }
Exemplo n.º 19
0
 public FormSelectMenuEventArgs(DiscordSocketClient client, DiscordInteraction interaction) : base(client, interaction)
 {
     Values = interaction.Data.SelectMenuValues;
 }
 public InteractionContext(DiscordSlashClient c, DiscordInteraction i)
 {
     _client     = c;
     Interaction = i;
 }
Exemplo n.º 21
0
 /// <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);