Skip to content

Commit 1a31aac

Browse files
Migrate to DSharpPlus.Commands (#243)
* WIP: Update DSharpPlus to 5.0.0-nightly-02379 * Fix missed breaking changes * Adjust text command names to avoid duplicate commands when registering Text command names are in the format "commandtextcmd", like "bantextcmd"; the original name ("ban") is now the first alias * Resolve remaining TODOs * Fix (at least partially) group commands * Error handling: Strip "textcmd" from cmd names, fix check failure handling * Fix [RequirePermissions] usage * Combine commands that can be combined, move all commands to Commands namespace * Upgrade DSharpPlus to 5.0.0-nightly-02422 * Remove mistakenly-added file * Fix incorrect namespaces * Remove import of deleted namespace * Restore friendlier note in command syntax error embed * Use SlashCommandContext for user context commands as workaround for potential DSharpPlus bug * Prevent !debug overrides from being registered as a slash command * Upgrade DSharpPlus and switch back to UserCommandContext Nightly 02426 resolves the bug that was present in DSharpPlus * Fix missed merge conflict changes / adjust for DSharpPlus.Commands * Implement a help command for text cmds & fix global cmd registration * Help: Properly filter out args of type CommandContext * Help: Show perms error when user lacks perms for requested cmd * Fix command registration * Add missing returns to permission error messages * Correctly show permission errors even on ArgumentParseException * Fix permission checks Show correct command names & permissions in RequireHomeserverPerm failure messages, properly honor OwnerOverride * Lockdown: Only try to FollowUpAsync when slash cmd is used * Fix flaws in help handler Fixes aliases not showing for some commands + help failing to show for commands that are not suffixed with 'textcmd' * fix inverted error msgs in security actions * fix command permission checks in DMs * Move 'overrides' group out of 'debug', make 'overrides dump' text-only * Properly hide subcommands from help that the user lacks perms for * fix !help outside server showing extra commands it shouldnt --------- Co-authored-by: Erisa A <[email protected]>
1 parent 13a2a17 commit 1a31aac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4059
-4316
lines changed

Cliptok.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
<ItemGroup>
1515
<PackageReference Include="Abyssal.HumanDateParser" Version="2.0.0-20191113.1" />
1616
<PackageReference Include="DSharpPlus" Version="5.0.0-nightly-02430" />
17-
<PackageReference Include="DSharpPlus.CommandsNext" Version="5.0.0-nightly-02430" />
18-
<PackageReference Include="DSharpPlus.SlashCommands" Version="5.0.0-nightly-02430" />
17+
<PackageReference Include="DSharpPlus.Commands" Version="5.0.0-nightly-02430" />
1918
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0" />
2019
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.0" />
2120
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />

CommandChecks/HomeServerPerms.cs

+18-52
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public enum ServerPermLevel
2525

2626
public static async Task<ServerPermLevel> GetPermLevelAsync(DiscordMember target)
2727
{
28-
if (target.Guild.Id != Program.cfgjson.ServerID)
28+
if (target is null || target.Guild is null || target.Guild.Id != Program.cfgjson.ServerID)
2929
return ServerPermLevel.Nothing;
3030

3131
// Torch approved of this.
@@ -66,7 +66,7 @@ public static async Task<ServerPermLevel> GetPermLevelAsync(DiscordMember target
6666
}
6767

6868
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
69-
public class RequireHomeserverPermAttribute : CheckBaseAttribute
69+
public class RequireHomeserverPermAttribute : ContextCheckAttribute
7070
{
7171
public ServerPermLevel TargetLvl { get; set; }
7272
public bool WorkOutside { get; set; }
@@ -79,16 +79,19 @@ public RequireHomeserverPermAttribute(ServerPermLevel targetlvl, bool workOutsid
7979
OwnerOverride = ownerOverride;
8080
TargetLvl = targetlvl;
8181
}
82+
}
8283

83-
public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
84+
public class RequireHomeserverPermCheck : IContextCheck<RequireHomeserverPermAttribute>
85+
{
86+
public async ValueTask<string?> ExecuteCheckAsync(RequireHomeserverPermAttribute attribute, CommandContext ctx)
8487
{
8588
// If the command is supposed to stay within the server and its being used outside, fail silently
86-
if (!WorkOutside && (ctx.Channel.IsPrivate || ctx.Guild.Id != Program.cfgjson.ServerID))
87-
return false;
89+
if (!attribute.WorkOutside && (ctx.Channel.IsPrivate || ctx.Guild.Id != Program.cfgjson.ServerID))
90+
return "This command must be used in the home server, but was executed outside of it.";
8891

8992
// bot owners can bypass perm checks ONLY if the command allows it.
90-
if (OwnerOverride && Program.cfgjson.BotOwners.Contains(ctx.User.Id))
91-
return true;
93+
if (attribute.OwnerOverride && Program.cfgjson.BotOwners.Contains(ctx.User.Id))
94+
return null;
9295

9396
DiscordMember member;
9497
if (ctx.Channel.IsPrivate || ctx.Guild.Id != Program.cfgjson.ServerID)
@@ -100,7 +103,7 @@ public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help
100103
}
101104
catch (DSharpPlus.Exceptions.NotFoundException)
102105
{
103-
return false;
106+
return "The invoking user must be a member of the home server; they are not.";
104107
}
105108
}
106109
else
@@ -109,58 +112,21 @@ public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help
109112
}
110113

111114
var level = await GetPermLevelAsync(member);
112-
if (level >= TargetLvl)
113-
return true;
115+
if (level >= attribute.TargetLvl)
116+
return null;
114117

115-
else if (!help && ctx.Command.QualifiedName != "edit")
116-
{
117-
var levelText = level.ToString();
118-
if (level == ServerPermLevel.Nothing && Program.rand.Next(1, 100) == 69)
119-
levelText = $"naught but a thing, my dear human. Congratulations, you win {Program.rand.Next(1, 10)} bonus points.";
120-
121-
await ctx.RespondAsync(
122-
$"{Program.cfgjson.Emoji.NoPermissions} Invalid permissions to use command **{ctx.Command.Name}**!\n" +
123-
$"Required: `{TargetLvl}`\nYou have: `{levelText}`");
124-
}
125-
return false;
118+
return "The invoking user does not have permission to use this command.";
126119
}
127120
}
128121

129-
public class HomeServerAttribute : CheckBaseAttribute
130-
{
131-
public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
132-
{
133-
return !ctx.Channel.IsPrivate && ctx.Guild.Id == Program.cfgjson.ServerID;
134-
}
135-
}
122+
public class HomeServerAttribute : ContextCheckAttribute;
136123

137-
public class SlashRequireHomeserverPermAttribute : SlashCheckBaseAttribute
124+
public class HomeServerCheck : IContextCheck<HomeServerAttribute>
138125
{
139-
public ServerPermLevel TargetLvl;
140-
public bool OwnerOverride;
141-
142-
public SlashRequireHomeserverPermAttribute(ServerPermLevel targetlvl, bool ownerOverride = false)
126+
public async ValueTask<string?> ExecuteCheckAsync(HomeServerAttribute attribute, CommandContext ctx)
143127
{
144-
TargetLvl = targetlvl;
145-
OwnerOverride = ownerOverride;
146-
}
147-
148-
public override async Task<bool> ExecuteChecksAsync(InteractionContext ctx)
149-
{
150-
if (ctx.Guild.Id != Program.cfgjson.ServerID)
151-
return false;
152-
153-
// bot owners can bypass perm checks ONLY if the command allows it.
154-
if (OwnerOverride && Program.cfgjson.BotOwners.Contains(ctx.User.Id))
155-
return true;
156-
157-
var level = await GetPermLevelAsync(ctx.Member);
158-
if (level >= TargetLvl)
159-
return true;
160-
else
161-
return false;
128+
return !ctx.Channel.IsPrivate && ctx.Guild.Id == Program.cfgjson.ServerID ? null : "This command must be used in the home server, but was executed outside of it.";
162129
}
163130
}
164-
165131
}
166132
}

CommandChecks/OwnerChecks.cs

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
namespace Cliptok.CommandChecks
22
{
3-
public class IsBotOwnerAttribute : CheckBaseAttribute
3+
public class IsBotOwnerAttribute : ContextCheckAttribute;
4+
5+
public class IsBotOwnerCheck : IContextCheck<IsBotOwnerAttribute>
46
{
5-
public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
7+
public async ValueTask<string?> ExecuteCheckAsync(IsBotOwnerAttribute attribute, CommandContext ctx)
68
{
79
if (Program.cfgjson.BotOwners.Contains(ctx.User.Id))
810
{
9-
return true;
11+
return null;
1012
}
1113
else
1214
{
13-
if (!help)
14-
{
15-
await ctx.RespondAsync($"{Program.cfgjson.Emoji.NoPermissions} This command is only accessible to bot owners.");
16-
}
17-
return false;
15+
return "Bot owner-only command was executed by a non-owner.";
1816
}
1917
}
2018
}

CommandChecks/UserRoleChecks.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
namespace Cliptok.CommandChecks
22
{
3-
public class UserRolesPresentAttribute : CheckBaseAttribute
3+
public class UserRolesPresentAttribute : ContextCheckAttribute;
4+
5+
public class UserRolesPresentCheck : IContextCheck<UserRolesPresentAttribute>
46
{
5-
public override async Task<bool> ExecuteCheckAsync(CommandContext ctx, bool help)
7+
public async ValueTask<string?> ExecuteCheckAsync(UserRolesPresentAttribute attribute, CommandContext ctx)
68
{
7-
return Program.cfgjson.UserRoles is not null;
9+
return Program.cfgjson.UserRoles is null ? "A user role command was executed, but user roles are not configured in config.json." : null;
810
}
911
}
1012
}

0 commit comments

Comments
 (0)