Skip to content

Conversation

@Instellate
Copy link
Member

Summary

Introduces a new command framework called UnifiedCommands.

Details

UnifiedCommands is a command framework that does not depend on old, code that is hard to maintain and features that should be removed. Meaning a fresh slate for everything.

UnifiedCommands also tries to simplify the process of bot development by going for a ASP.NET like approach making it faster to write methods for commands.

It also has pre execution in form of conditions which is run before a command gets executed to make sure that the event follows the condition needed for execution to proceed. This can also modify values given through Dependency Injection if it is a singleton or scope.

Note

This is still in WIP. If you have any questions. Please ask me in the discord server or comment in this pr.
I will mark this as ready when it's ready for production usage, all features are completed, and if this command framework will get accepted.

Instellate and others added 30 commits April 24, 2023 21:38
This doesn't include long, float and etc.
Also added DSharpPlus.CH into the sln and updated README.md
Also did some renaming on some of the proprties.
Did some renaming as well.
Also implemented a permission middleware for example. Some bug fixing is also present.
Also some roslyn analysing fixing.
This needs more work. Also added more to the TODO.md
Just need  to make parameter mapping, conversion and binding.
This does not include error handling for it. Will do later.
I also did some bug fixing that I noticed in the code.
Also made so " " can be used in options as I forgot about that.
@OoLunar
Copy link
Contributor

OoLunar commented May 14, 2023

I'll think about it

Copy link
Contributor

@OoLunar OoLunar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most thorough I've been on a PR in a long while. I hold nothing against you. I am not mad at you. I appreciate all the work you've put into this.

With that being said, I have a ton of grievances with this, mostly excluding formatting, see comments below. Additionally, I still don't understand what purpose this extension would serve over the existing CommandsNext and SlashCommands extensions.

@@ -0,0 +1,16 @@
namespace DSharpPlus.UnifiedCommands;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<Project>
<ItemGroup>
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.6.0-1.final" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am against adding MSE.Configuration as it's usually the developer which configures this dependency. Instead we should stick to using our own Configuration classes which the developer can configure themselves.

Copy link
Member Author

@Instellate Instellate May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to have it like a configuration where you configure the class. I just following ASP.NET patterns a bit. But I will remove it to decrease dependencies as the use case is pretty useless.

this.Discord.UseInteractivity(icfg);

this.SlashCommandService = this.Discord.UseSlashCommands();
/* this.SlashCommandService = this.Discord.UseSlashCommands();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we commenting out the slash commands tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented it out when testing the application part of the framework as SlashCommands would prevent me from testing that part. I haven't commented it out yet as I am still working on the application part.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be an alternative solution?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative solution could be adding an option into the config.json for toggling on/off UnifiedCommands and SlashCommands.

public bool IsNullable { get; set; } = false;

public ApplicationMethodParameterData(string name)
=> Name = name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline

public ObjectFactory Factory { get; }

public ApplicationModuleData(ObjectFactory factory)
=> Factory = factory;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't inline those please, having it indented by one level is fine - these lines can become very long, and id rather have all cases wrapped than some

{
public string Name { get; }
public string Description { get; }
// public Type Type { get; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out and what function does it serve? Can we use generic attributes for it?

Copy link
Contributor

@OoLunar OoLunar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most thorough I've been on a PR in a long while. I hold nothing against you. I am not mad at you. I appreciate all the work you've put into this.

With that being said, I have a ton of grievances with this, mostly excluding formatting, see comments below. Additionally, I still don't understand what purpose this extension would serve over the existing CommandsNext and SlashCommands extensions.

@Instellate
Copy link
Member Author

Instellate commented May 16, 2023

I (was going to) initially started this as a personal project to have a more ASP.NET like experience with programing discord bots with D#+. As I don't like property/field di and I want proper implementation of scopes. And some other minor stuff. Talked about it a bit and it caught attention from @akiraveliara and @inftord.

Namely this is just trying to be a more "modern" and easier to use/convenient command framework. Therefor following a

public IApplicationResult Command() 
{
    return Reply("Hello there");
}

kind of way as that's how ASP.NET does their stuff.
Aki complained also that CNext is hard to maintain. So this is trying to be easy to maintain on top of that.

Copy link
Member

@Plerx2493 Plerx2493 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some comments about logging exceptions to the user. Feel free to correct me if anything is wrong

{
_client.Logger.LogError(
e,
"Exception was thrown while trying to execute command {MethodName}. Was thrown from ",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this formatting right? looks as if there is something missing at the end. AFAIK the logger appends the exception which will be worded weird.:

Exception was thrown while trying to execute command {MethodName}. Was thrown from
System.Exception
....

if (parameter.ParameterType != typeof(string))
{
throw new InvalidMessageModuleStructure(
"You need to use string if you are using RemainingTextAttribute.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if the error message contains the methodname, so the user can see easily where they have to change something

parameterData.Type = parameterType == typeof(double)
? MessageParameterDataType.Double
: throw new InvalidMessageModuleStructure(
$"You cannot use type {parameterType.Name} as a parameter.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if the error message contains the methodname, so the user can see easily where they have to change something

ApplicationOptionAttribute? name = parameter.GetCustomAttribute<ApplicationOptionAttribute>();
if (name is null)
{
throw new Exception("Parameter needs to have `ApplicationNameAttribute` marked.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if the error message contains the methodname, so the user can see easily where they have to change something

{
data.Type = parameter.ParameterType == typeof(DiscordAttachment)
? ApplicationCommandOptionType.Attachment
: throw new Exception("Not a valid parameter type.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if the error message contains the methodname, so the user can see easily where they have to change something

Copy link
Member

@akiraveliara akiraveliara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a note about formatting: don't inline initializer blocks, and if you wrap a line because it gets too long, use allman formatting. the pull request in its entirety is also sorely missing xmldocs.

it should be considered to unify the command conditions as far as possible. one of the main pain points with slash commands and commandsnext today is that they more or less duplicate this code.

you should probably consider adding todo tags for currently unfinished implementation so we can use IDE tooling to fill them all out before releasing a stable version.

i would furthermore like to reiterate my comments about changing Application* to Interaction, as well as restoring MessageCommand to its full length

@@ -0,0 +1,6 @@
namespace DSharpPlus.UnifiedCommands.Application.Entities;

public class DiscordModalBuilder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be moved to corelib, once finished

internal void AddCondition(Func<IServiceProvider, IApplicationCondition> func)
=> _conditionBuilders.Add(func);

internal void ExecuteCommand(DiscordInteraction interaction, DiscordClient client)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this method will need large-scale future refactoring, just to note it here.

/// <summary>
/// Enum representing the possibilities for conversion failure.
/// </summary>
public enum InvalidMessageConversionType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on second thoughts yeah this should be changed to something allowing users to define their own failure types

public class MessageOptionAttribute : Attribute
{
public string Option { get; set; }
public string? ShorthandOption { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there might be merit in turning this into a char

Copy link
Member Author

@Instellate Instellate May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some shorthands might be more than one character. But usually that isn't the case. But I think we should keep shorthand option as a string for the people that needs it to be more than one character.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does lock us out of combining shorthands à la git commit -aS


## Decisions
- Should we continue using DSharpPlus.Interactivity or should it be reimplemented into CommandModule?
- Should we call classes as `xCommand` (for example `MessageCommand`) or should we call it `x` (for example `Message`) No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally i think it should be Interaction and MessageCommand/TextCommand/whatever, our priority isn't with making names short

Services.AddSingleton(configuration);
if (!Services.Any(s => s.ServiceType == typeof(IErrorHandler)))
{
client.Logger.LogTrace("Didn't find a error handler, using the default error handler");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably LogDebug here

@dongle-the-gadget
Copy link

Does the new condition API allow dependency injection? I currently have a check that requires access to a DbContext in DI and I would like to use a single scope so that the DbContext can be reused for both the condition and the method.

@OoLunar
Copy link
Contributor

OoLunar commented Jan 30, 2024

Closed by #1680.

@OoLunar OoLunar closed this Jan 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants