Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions DSharpPlus.Commands/CommandsExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ namespace DSharpPlus.Commands;
/// <summary>
/// An all in one extension for managing commands.
/// </summary>
public sealed class CommandsExtension : BaseExtension
public sealed class CommandsExtension
{
public DiscordClient Client { get; private set; }

/// <inheritdoc cref="DiscordClient.ServiceProvider"/>
public IServiceProvider ServiceProvider { get; private set; }

Expand Down Expand Up @@ -129,7 +131,7 @@ internal CommandsExtension(CommandsConfiguration configuration)
/// Sets up the extension to use the specified <see cref="DiscordClient"/>.
/// </summary>
/// <param name="client">The client to register our event handlers too.</param>
protected override void Setup(DiscordClient client)
public void Setup(DiscordClient client)
{
if (client is null)
{
Expand All @@ -142,8 +144,8 @@ protected override void Setup(DiscordClient client)

this.Client = client;
this.ServiceProvider = client.ServiceProvider;
this.Client.SessionCreated += async (_, _) => await RefreshAsync();
this.logger = client.ServiceProvider.GetRequiredService<ILogger<CommandsExtension>>();

this.logger = client.ServiceProvider.GetService<ILogger<CommandsExtension>>();

DefaultClientErrorHandler errorHandler = new(client.Logger);
this.commandErrored = new(errorHandler);
Expand Down Expand Up @@ -480,12 +482,6 @@ internal void BuildCommands()
this.Commands = commands.ToFrozenDictionary();
}

/// <inheritdoc />
public override void Dispose()
{
return;
}

/// <summary>
/// The default command error handler. Only used if <see cref="UseDefaultCommandErrorHandler"/> is set to true.
/// </summary>
Expand Down
67 changes: 42 additions & 25 deletions DSharpPlus.Commands/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using DSharpPlus.Extensions;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace DSharpPlus.Commands;

Expand All @@ -13,33 +13,50 @@ namespace DSharpPlus.Commands;
public static class ExtensionMethods
{
/// <summary>
/// Registers the extension with the <see cref="DiscordClient"/>.
/// Registers the extension with the <see cref="DiscordClientBuilder"/>.
/// </summary>
/// <param name="client">The client to register the extension with.</param>
/// <param name="builder">The client builder to register the extension with.</param>
/// <param name="setup">Any setup code you want to run on the extension, such as registering commands and converters.</param>
/// <param name="configuration">The configuration to use for the extension.</param>
public static CommandsExtension UseCommands(this DiscordClient client, CommandsConfiguration? configuration = null)
{
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
else if (client.GetExtension<CommandsExtension>() is not null)
{
throw new InvalidOperationException("Commands extension is already initialized.");
}

CommandsExtension extension = new(configuration ?? new());
client.AddExtension(extension);
return extension;
}
public static DiscordClientBuilder UseCommands
(
this DiscordClientBuilder builder,
Action<CommandsExtension> setup,
CommandsConfiguration? configuration = null
)
=> builder.ConfigureServices(services => services.AddCommandsExtension(setup, configuration));

/// <summary>
/// Retrieves the <see cref="CommandsExtension"/> from the <see cref="DiscordClient"/>.
/// Registers the commands extension with an <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="client">The client to retrieve the extension from.</param>
public static CommandsExtension? GetCommandsExtension(this DiscordClient client) => client is null
? throw new ArgumentNullException(nameof(client))
: client.GetExtension<CommandsExtension>();
/// <param name="services">The service collection to register the extension with.</param>
/// <param name="setup">Any setup code you want to run on the extension, such as registering commands and converters.</param>
/// <param name="configuration">The configuration to use for the extension.</param>
public static IServiceCollection AddCommandsExtension
(
this IServiceCollection services,
Action<CommandsExtension> setup,
CommandsConfiguration? configuration = null
)
{
services.ConfigureEventHandlers(b =>
{
b.AddEventHandlers<RefreshEventHandler>(ServiceLifetime.Singleton)
.AddEventHandlers<ProcessorInvokingHandlers>(ServiceLifetime.Transient);
})
.AddSingleton(provider =>
{
DiscordClient client = provider.GetRequiredService<DiscordClient>();

CommandsExtension extension = new(configuration ?? new());
extension.Setup(client);
setup(extension);

return extension;
});

return services;
}

/// <inheritdoc cref="Array.IndexOf{T}(T[], T)"/>
internal static int IndexOf<T>(this IEnumerable<T> array, T? value) where T : IEquatable<T>
Expand Down
54 changes: 54 additions & 0 deletions DSharpPlus.Commands/ProcessorInvokingHandlers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Threading.Tasks;

using DSharpPlus.Commands.Processors;
using DSharpPlus.Commands.Processors.MessageCommands;
using DSharpPlus.Commands.Processors.SlashCommands;
using DSharpPlus.Commands.Processors.TextCommands;
using DSharpPlus.Commands.Processors.UserCommands;
using DSharpPlus.EventArgs;

namespace DSharpPlus.Commands;

// this is a temporary measure until we can land proper IoC support
internal sealed class ProcessorInvokingHandlers
: IEventHandler<ContextMenuInteractionCreatedEventArgs>,
IEventHandler<InteractionCreatedEventArgs>,
IEventHandler<MessageCreatedEventArgs>
{
private readonly CommandsExtension extension;

public ProcessorInvokingHandlers(CommandsExtension extension)
=> this.extension = extension;

// user and message context menu commands
public async Task HandleEventAsync(DiscordClient sender, ContextMenuInteractionCreatedEventArgs eventArgs)
{
if (this.extension.Processors.TryGetValue(typeof(UserCommandProcessor), out ICommandProcessor? userProcessor))
{
await ((UserCommandProcessor)userProcessor).ExecuteInteractionAsync(sender, eventArgs);
}

if (this.extension.Processors.TryGetValue(typeof(MessageCommandProcessor), out ICommandProcessor? msgProcessor))
{
await ((MessageCommandProcessor)msgProcessor).ExecuteInteractionAsync(sender, eventArgs);
}
}

// slash commands
public async Task HandleEventAsync(DiscordClient sender, InteractionCreatedEventArgs eventArgs)
{
if (this.extension.Processors.TryGetValue(typeof(SlashCommandProcessor), out ICommandProcessor? processor))
{
await ((SlashCommandProcessor)processor).ExecuteInteractionAsync(sender, eventArgs);
}
}

// text commands
public async Task HandleEventAsync(DiscordClient sender, MessageCreatedEventArgs eventArgs)
{
if (this.extension.Processors.TryGetValue(typeof(TextCommandProcessor), out ICommandProcessor? processor))
{
await ((TextCommandProcessor)processor).ExecuteTextCommandAsync(sender, eventArgs);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ public sealed class MessageCommandProcessor : ICommandProcessor<InteractionCreat
/// <inheritdoc />
public async ValueTask ConfigureAsync(CommandsExtension extension)
{
if (this.extension is null)
{
extension.Client.ContextMenuInteractionCreated += ExecuteInteractionAsync;
}

this.extension = extension;
this.slashCommandProcessor = this.extension.GetProcessor<SlashCommandProcessor>() ?? new SlashCommandProcessor();

Expand Down
Loading