Skip to content

Commit c56c223

Browse files
committed
use permanent buttons in /remind manage
1 parent 09d93a8 commit c56c223

File tree

93 files changed

+894
-643
lines changed

Some content is hidden

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

93 files changed

+894
-643
lines changed

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/CommandRunner.cs

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using Discord;
22
using TaylorBot.Net.Commands.Instrumentation;
33
using TaylorBot.Net.Commands.Parsers.Channels;
4+
using TaylorBot.Net.Commands.PostExecution;
45
using TaylorBot.Net.Commands.Preconditions;
6+
using TaylorBot.Net.Core.Client;
57
using TaylorBot.Net.Core.Logging;
68
using TaylorBot.Net.Core.Snowflake;
79
using TaylorBot.Net.Core.User;
@@ -24,7 +26,6 @@ public record RunContext(
2426
DiscordChannel Channel,
2527
CommandGuild? Guild,
2628
IDiscordClient Client,
27-
ISelfUser BotUser,
2829
RunContext.CurrentCommandInfo CommandInfo,
2930
Lazy<Task<string>> CommandPrefix,
3031
RunContext.OnGoingState OnGoing,
@@ -47,13 +48,51 @@ public string MentionCommand(string name) =>
4748
public GuildTextChannel? GuildTextChannel { get; set; } = Guild != null ? new GuildTextChannel(Channel.Id, Guild.Id, Channel.Type) : null;
4849
}
4950

51+
public class RunContextFactory(
52+
Lazy<ITaylorBotClient> taylorBotClient,
53+
InteractionMapper interactionMapper,
54+
CommandPrefixDomainService commandPrefixDomainService)
55+
{
56+
public RunContext BuildContext(ParsedInteraction interaction, CommandActivity activity, bool wasAcknowledged)
57+
{
58+
var guild = interaction.Guild != null
59+
? taylorBotClient.Value.DiscordShardedClient.GetGuild(interaction.Guild.Id)
60+
: null;
61+
62+
var user = interaction.User;
63+
64+
return new RunContext(
65+
CreatedAt: DateTimeOffset.UtcNow,
66+
User: new(
67+
user.id,
68+
user.username,
69+
user.avatar,
70+
user.discriminator,
71+
IsBot: user.bot == true,
72+
interaction.Guild != null
73+
? interactionMapper.ToMemberInfo(interaction.Guild.Id, interaction.Guild.Member)
74+
: null),
75+
FetchedUser: null,
76+
Channel: new(interaction.Channel.Id, (ChannelType)interaction.Channel.Partial.type),
77+
Guild: interaction.Guild != null ? new(interaction.Guild.Id, guild) : null,
78+
Client: taylorBotClient.Value.DiscordShardedClient,
79+
CommandInfo: new(interaction.Data.id, interaction.Data.name),
80+
CommandPrefix: new(() => commandPrefixDomainService.GetPrefixAsync(guild)),
81+
OnGoing: new(),
82+
activity,
83+
WasAcknowledged: wasAcknowledged
84+
);
85+
}
86+
}
87+
5088
public record Command(CommandMetadata Metadata, Func<ValueTask<ICommandResult>> RunAsync, IList<ICommandPrecondition>? Preconditions = null);
5189

5290
public record CommandMetadata(string Name, string? ModuleName = null, IReadOnlyList<string>? Aliases = null);
5391

5492
public interface ICommandRunner
5593
{
56-
ValueTask<ICommandResult> RunAsync(Command command, RunContext context);
94+
ValueTask<ICommandResult> RunSlashCommandAsync(Command command, RunContext context);
95+
Task<ICommandResult> RunInteractionAsync(Command command, RunContext context);
5796
}
5897

5998
public class CommandRunner(
@@ -66,16 +105,36 @@ public class CommandRunner(
66105
UserNoOngoingCommandPrecondition userNoOngoingCommand
67106
) : ICommandRunner
68107
{
69-
private readonly List<ICommandPrecondition> _preconditions = [notDisabled, notGuildDisabled, notGuildChannelDisabled, userNotIgnored, memberTracked, textChannelTracked, userNoOngoingCommand];
108+
private readonly List<ICommandPrecondition> slashCommandsPreconditions = [notDisabled, notGuildDisabled, notGuildChannelDisabled, userNotIgnored, memberTracked, textChannelTracked, userNoOngoingCommand];
109+
110+
public async ValueTask<ICommandResult> RunSlashCommandAsync(Command command, RunContext context)
111+
{
112+
context.Activity.CommandName = command.Metadata.Name;
113+
context.Activity.UserId = context.User.Id;
114+
context.Activity.ChannelId = context.Channel.Id;
115+
context.Activity.GuildId = context.Guild?.Id;
116+
117+
foreach (var precondition in slashCommandsPreconditions.Concat(command.Preconditions ?? []))
118+
{
119+
if (await precondition.CanRunAsync(command, context) is PreconditionFailed failed)
120+
return failed;
121+
}
122+
123+
var result = await command.RunAsync();
124+
125+
return result;
126+
}
127+
128+
private readonly List<ICommandPrecondition> interactionsPreconditions = [userNotIgnored, memberTracked, textChannelTracked];
70129

71-
public async ValueTask<ICommandResult> RunAsync(Command command, RunContext context)
130+
public async Task<ICommandResult> RunInteractionAsync(Command command, RunContext context)
72131
{
73132
context.Activity.CommandName = command.Metadata.Name;
74133
context.Activity.UserId = context.User.Id;
75134
context.Activity.ChannelId = context.Channel.Id;
76135
context.Activity.GuildId = context.Guild?.Id;
77136

78-
foreach (var precondition in _preconditions.Concat(command.Preconditions ?? []))
137+
foreach (var precondition in interactionsPreconditions.Concat(command.Preconditions ?? []))
79138
{
80139
if (await precondition.CanRunAsync(command, context) is PreconditionFailed failed)
81140
return failed;

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/DiscordNet/DiscordNetContextMapper.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public static RunContext MapToRunContext(ITaylorBotCommandContext context)
1616
new(context.Channel.Id, channelType.Value),
1717
context.Guild != null ? new(context.Guild.Id, context.Guild) : null,
1818
context.Client,
19-
context.CurrentUser,
2019
new(string.Empty, string.Empty),
2120
new(Task.FromResult(context.CommandPrefix)),
2221
new(),

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/DiscordNet/HelpModule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static string BuildDescription(ModuleInfo module)
108108
});
109109

110110
var context = DiscordNetContextMapper.MapToRunContext(Context);
111-
var result = await commandRunner.RunAsync(command, context);
111+
var result = await commandRunner.RunSlashCommandAsync(command, context);
112112

113113
return new TaylorBotResult(result, context);
114114
}

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/Events/InteractionCreatedHandler.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,38 @@ public Task InteractionCreatedAsync(Interaction interaction)
4444

4545
case MESSAGE_COMPONENT:
4646
_ = Task.Run(async () => await taskExceptionLogger.LogOnError(
47-
async () => await messageComponentHandler.HandleAsync(interaction),
47+
async () =>
48+
{
49+
using var activity = commandActivityFactory.Create(CommandType.MessageComponent);
50+
try
51+
{
52+
await messageComponentHandler.HandleAsync(interaction, activity);
53+
}
54+
catch (Exception e)
55+
{
56+
activity.SetError(e);
57+
throw;
58+
}
59+
},
4860
nameof(MessageComponentHandler)
4961
));
5062
break;
5163

5264
case MODAL_SUBMIT:
5365
_ = Task.Run(async () => await taskExceptionLogger.LogOnError(
54-
async () => await modalInteractionHandler.HandleAsync(interaction),
66+
async () =>
67+
{
68+
using var activity = commandActivityFactory.Create(CommandType.ModalSubmit);
69+
try
70+
{
71+
await modalInteractionHandler.HandleAsync(interaction, activity);
72+
}
73+
catch (Exception e)
74+
{
75+
activity.SetError(e);
76+
throw;
77+
}
78+
},
5579
nameof(ModalInteractionHandler)
5680
));
5781
break;

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/Extensions/ServiceCollectionExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using TaylorBot.Net.Commands.Parsers.Users;
1414
using TaylorBot.Net.Commands.PostExecution;
1515
using TaylorBot.Net.Commands.Preconditions;
16+
using TaylorBot.Net.Commands.StringMappers;
1617
using TaylorBot.Net.Commands.Types;
1718
using TaylorBot.Net.Core.Client;
1819
using TaylorBot.Net.Core.Program.Events;
@@ -42,7 +43,9 @@ public static IServiceCollection AddCommandApplication(this IServiceCollection s
4243
.AddTransient<DisabledGuildCommandDomainService>()
4344
.AddTransient<SingletonTaskRunner>()
4445
.AddTransient<IUserMessageReceivedHandler, CommandHandler>()
46+
.AddTransient<PermissionStringMapper>()
4547
.AddTransient<InteractionMapper>()
48+
.AddTransient<RunContextFactory>()
4649
.AddTransient<SlashCommandHandler>()
4750
.AddSingleton<MessageComponentHandler>()
4851
.AddSingleton<ModalInteractionHandler>()
@@ -77,6 +80,9 @@ public static IServiceCollection AddCommandApplication(this IServiceCollection s
7780
.AddTransient<MemberTrackedPrecondition>()
7881
.AddTransient<TextChannelTrackedPrecondition>()
7982
.AddTransient<UserNoOngoingCommandPrecondition>()
83+
.AddTransient<UserHasPermissionOrOwnerPrecondition.Factory>()
84+
.AddTransient<TaylorBotOwnerPrecondition>()
85+
.AddTransient<InGuildPrecondition.Factory>()
8086
.AddTransient<ICommandRunner, CommandRunner>()
8187
.AddOptionParser<StringParser, ParsedString>()
8288
.AddOptionParser<OptionalStringParser, ParsedOptionalString>()

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/Instrumentation/CommandActivity.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ public enum CommandType
99
Unknown = 0,
1010
Slash,
1111
Prefix,
12+
MessageComponent,
13+
ModalSubmit,
1214
}
1315

1416
public class CommandActivityFactory(TaylorBotInstrumentation instrumentation)
@@ -38,7 +40,16 @@ public sealed class CommandActivity(Activity? activity) : IDisposable
3840

3941
public SnowflakeId? GuildId { set => activity?.SetTag("guild.id", value?.Id); }
4042

41-
public string CommandName { set => activity?.SetTag("command.name", value); }
43+
public string? CommandName
44+
{
45+
set
46+
{
47+
if (value != null)
48+
{
49+
activity?.SetTag("command.name", value);
50+
}
51+
}
52+
}
4253

4354
public CommandType Type { set => activity?.SetTag("command.type", value); }
4455

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/Parsers/Users/ParsedMemberNotAuthorAndTaylorBot.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ namespace TaylorBot.Net.Commands.Parsers.Users;
88

99
public record ParsedMemberNotAuthorAndTaylorBot(DiscordMember Member);
1010

11-
public class MemberNotAuthorAndTaylorBotParser(MemberNotAuthorParser memberNotAuthorParser) : IOptionParser<ParsedMemberNotAuthorAndTaylorBot>
11+
public class MemberNotAuthorAndTaylorBotParser(MemberNotAuthorParser memberNotAuthorParser, Lazy<ITaylorBotClient> taylorBotClient) : IOptionParser<ParsedMemberNotAuthorAndTaylorBot>
1212
{
1313
public async ValueTask<Result<ParsedMemberNotAuthorAndTaylorBot, ParsingFailed>> ParseAsync(RunContext context, JsonElement? optionValue, Interaction.Resolved? resolved)
1414
{
1515
var parsedMember = await memberNotAuthorParser.ParseAsync(context, optionValue, resolved);
1616
if (parsedMember)
1717
{
18-
return parsedMember.Value.Member.User.Id != context.BotUser.Id ?
18+
return parsedMember.Value.Member.User.Id != taylorBotClient.Value.DiscordShardedClient.CurrentUser.Id ?
1919
new ParsedMemberNotAuthorAndTaylorBot(parsedMember.Value.Member) :
2020
Error(new ParsingFailed("Member can't be TaylorBot 🤭"));
2121
}

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/Parsers/Users/ParsedUserNotAuthorAndTaylorBot.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ namespace TaylorBot.Net.Commands.Parsers.Users;
88

99
public record ParsedUserNotAuthorAndTaylorBot(DiscordUser User);
1010

11-
public class UserNotAuthorAndTaylorBotParser(UserNotAuthorParser userNotAuthorParser) : IOptionParser<ParsedUserNotAuthorAndTaylorBot>
11+
public class UserNotAuthorAndTaylorBotParser(UserNotAuthorParser userNotAuthorParser, Lazy<ITaylorBotClient> taylorBotClient) : IOptionParser<ParsedUserNotAuthorAndTaylorBot>
1212
{
1313
public async ValueTask<Result<ParsedUserNotAuthorAndTaylorBot, ParsingFailed>> ParseAsync(RunContext context, JsonElement? optionValue, Interaction.Resolved? resolved)
1414
{
1515
var parsedUser = await userNotAuthorParser.ParseAsync(context, optionValue, resolved);
1616
if (parsedUser)
1717
{
18-
return parsedUser.Value.User.Id != context.BotUser.Id ?
18+
return parsedUser.Value.User.Id != taylorBotClient.Value.DiscordShardedClient.CurrentUser.Id ?
1919
new ParsedUserNotAuthorAndTaylorBot(parsedUser.Value.User) :
2020
Error(new ParsingFailed("User can't be TaylorBot 🤭"));
2121
}

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/PostExecution/GenericPromptCancelButtonHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ public class GenericPromptCancelButtonHandler(InteractionResponseClient response
66
{
77
public static CustomIdNames CustomIdName => CustomIdNames.GenericPromptCancel;
88

9-
public IComponentHandlerInfo Info => new MessageHandlerInfo(CustomIdName.ToText());
9+
public IComponentHandlerInfo Info => new MessageHandlerInfo(CustomIdName.ToText(), RequireOriginalUser: true);
1010

11-
public async Task HandleAsync(DiscordButtonComponent button)
11+
public async Task HandleAsync(DiscordButtonComponent button, RunContext context)
1212
{
13-
await responseClient.EditOriginalResponseAsync(button, EmbedFactory.CreateErrorEmbed("Operation cancelled 👍"));
13+
await responseClient.EditOriginalResponseAsync(button.Interaction, EmbedFactory.CreateErrorEmbed("Operation cancelled 👍"));
1414
}
1515
}

src/TaylorBot.Net/Core/src/TaylorBot.Net.Commands/PostExecution/InteractionCustomId.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public enum CustomIdNames
4545
ModMailUserMessageReply = 101,
4646
ModMailUserMessageReplyModal = 102,
4747
ModMailReplyConfirm = 103,
48+
RemindManageClear = 104,
49+
RemindManageClearAll = 105,
4850
}
4951

5052
public static class CustomIdExtensions

0 commit comments

Comments
 (0)