-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1036 from discord-csharp/refactor-auto-remove
V3: Refactor auto remove, new message and reaction notifications
- Loading branch information
Showing
34 changed files
with
457 additions
and
641 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,121 +1,82 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
using Discord; | ||
using Discord.Commands; | ||
|
||
using Modix.Common.Messaging; | ||
using Modix.Services.CommandHelp; | ||
using MediatR; | ||
using Modix.Bot.Notifications; | ||
using Modix.Bot.Responders.CommandErrors; | ||
using Modix.Services.Core; | ||
using Modix.Services.Utilities; | ||
|
||
using Serilog; | ||
|
||
using Stopwatch = System.Diagnostics.Stopwatch; | ||
|
||
namespace Modix.Bot.Behaviors | ||
namespace Modix.Bot.Behaviors; | ||
|
||
public class CommandListeningBehavior( | ||
ICommandPrefixParser commandPrefixParser, | ||
IServiceProvider serviceProvider, | ||
CommandService commandService, | ||
CommandErrorService commandErrorService, | ||
IDiscordClient discordClient, | ||
IAuthorizationService authorizationService) : INotificationHandler<MessageReceivedNotificationV3> | ||
{ | ||
/// <summary> | ||
/// Listens for user commands within messages received from Discord, and executes them, if found. | ||
/// </summary> | ||
public class CommandListeningBehavior : INotificationHandler<MessageReceivedNotification> | ||
public async Task Handle(MessageReceivedNotificationV3 notification, CancellationToken cancellationToken = default) | ||
{ | ||
/// <summary> | ||
/// Constructs a new <see cref="CommandListeningBehavior"/>, with the given dependencies. | ||
/// </summary> | ||
public CommandListeningBehavior( | ||
ICommandPrefixParser commandPrefixParser, | ||
IServiceProvider serviceProvider, | ||
CommandService commandService, | ||
CommandErrorHandler commandErrorHandler, | ||
IDiscordClient discordClient, | ||
IAuthorizationService authorizationService) | ||
{ | ||
_commandPrefixParser = commandPrefixParser; | ||
ServiceProvider = serviceProvider; | ||
CommandService = commandService; | ||
CommandErrorHandler = commandErrorHandler; | ||
DiscordClient = discordClient; | ||
AuthorizationService = authorizationService; | ||
} | ||
var stopwatch = new Stopwatch(); | ||
stopwatch.Start(); | ||
|
||
/// <inheritdoc /> | ||
public async Task HandleNotificationAsync(MessageReceivedNotification notification, CancellationToken cancellationToken = default) | ||
{ | ||
var stopwatch = new Stopwatch(); | ||
stopwatch.Start(); | ||
if (!(notification.Message is IUserMessage userMessage) | ||
|| (userMessage.Author is null)) | ||
return; | ||
|
||
if (!(notification.Message is IUserMessage userMessage) | ||
|| (userMessage.Author is null)) | ||
return; | ||
if (!(userMessage.Author is IGuildUser author) | ||
|| (author.Guild is null) | ||
|| author.IsBot | ||
|| author.IsWebhook) | ||
return; | ||
|
||
if (!(userMessage.Author is IGuildUser author) | ||
|| (author.Guild is null) | ||
|| author.IsBot | ||
|| author.IsWebhook) | ||
return; | ||
if (userMessage.Content.Length <= 1) | ||
return; | ||
|
||
if (userMessage.Content.Length <= 1) | ||
return; | ||
var argPos = await commandPrefixParser.TryFindCommandArgPosAsync(userMessage, cancellationToken); | ||
|
||
var argPos = await _commandPrefixParser.TryFindCommandArgPosAsync(userMessage, cancellationToken); | ||
if (argPos is null) | ||
return; | ||
if (argPos is null) | ||
return; | ||
|
||
var commandContext = new CommandContext(DiscordClient, userMessage); | ||
var commandContext = new CommandContext(discordClient, userMessage); | ||
|
||
await AuthorizationService.OnAuthenticatedAsync(author.Id, author.Guild.Id, author.RoleIds.ToList()); | ||
await authorizationService.OnAuthenticatedAsync(author.Id, author.Guild.Id, author.RoleIds.ToList()); | ||
|
||
var commandResult = await CommandService.ExecuteAsync(commandContext, argPos.Value, ServiceProvider); | ||
var commandResult = await commandService.ExecuteAsync(commandContext, argPos.Value, serviceProvider); | ||
|
||
if(!commandResult.IsSuccess) | ||
{ | ||
var error = $"{commandResult.Error}: {commandResult.ErrorReason}"; | ||
|
||
if (string.Equals(commandResult.ErrorReason, "UnknownCommand", StringComparison.OrdinalIgnoreCase)) | ||
Log.Error(error); | ||
else | ||
Log.Warning(error); | ||
if(!commandResult.IsSuccess) | ||
{ | ||
var error = $"{commandResult.Error}: {commandResult.ErrorReason}"; | ||
|
||
if (commandResult.Error == CommandError.Exception) | ||
await commandContext.Channel.SendMessageAsync($"Error: {commandResult.ErrorReason}", allowedMentions: AllowedMentions.None); | ||
else | ||
await CommandErrorHandler.AssociateErrorAsync(userMessage, error); | ||
if (string.Equals(commandResult.ErrorReason, "UnknownCommand", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
Log.Error(error); | ||
} | ||
else | ||
{ | ||
Log.Warning(error); | ||
} | ||
|
||
stopwatch.Stop(); | ||
Log.Information($"Command took {stopwatch.ElapsedMilliseconds}ms to process: {commandContext.Message}"); | ||
if (commandResult.Error == CommandError.Exception) | ||
{ | ||
await commandContext.Channel.SendMessageAsync($"Error: {commandResult.ErrorReason}", allowedMentions: AllowedMentions.None); | ||
} | ||
else | ||
{ | ||
await commandErrorService.SignalError(userMessage, error); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The <see cref="IServiceProvider"/> for the current service scope. | ||
/// </summary> | ||
internal protected IServiceProvider ServiceProvider { get; } | ||
|
||
/// <summary> | ||
/// A <see cref="Discord.Commands.CommandService"/> used to parse and execute commands. | ||
/// </summary> | ||
internal protected CommandService CommandService { get; } | ||
|
||
/// <summary> | ||
/// A <see cref="Services.CommandHelp.CommandErrorHandler"/> used to report and track command errors, in the Discord UI. | ||
/// </summary> | ||
internal protected CommandErrorHandler CommandErrorHandler { get; } | ||
|
||
/// <summary> | ||
/// An <see cref="IDiscordClient"/> used to interact with the Discord API. | ||
/// </summary> | ||
internal protected IDiscordClient DiscordClient { get; } | ||
|
||
/// <summary> | ||
/// An <see cref="IAuthorizationService"/> used to interact with the application authorization system. | ||
/// </summary> | ||
internal protected IAuthorizationService AuthorizationService { get; } | ||
stopwatch.Stop(); | ||
|
||
private readonly ICommandPrefixParser _commandPrefixParser; | ||
} | ||
Log.Information("Command took {StopwatchElapsedMilliseconds}ms to process: {CommandContextMessage}", | ||
stopwatch.ElapsedMilliseconds, | ||
commandContext.Message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/Modix.Bot/Notifications/MessageDeletedNotificationV3.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Discord; | ||
using MediatR; | ||
|
||
namespace Modix.Bot.Notifications; | ||
|
||
public class MessageDeletedNotificationV3(Cacheable<IMessage, ulong> message, Cacheable<IMessageChannel, ulong> channel) | ||
: INotification | ||
{ | ||
public Cacheable<IMessage, ulong> Message { get; } = message; | ||
public Cacheable<IMessageChannel, ulong> Channel { get; } = channel; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/Modix.Bot/Notifications/ReactionAddedNotificationV3.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Discord; | ||
using Discord.WebSocket; | ||
using MediatR; | ||
|
||
namespace Modix.Bot.Notifications; | ||
|
||
public class ReactionAddedNotificationV3( | ||
Cacheable<IUserMessage, ulong> message, | ||
Cacheable<IMessageChannel, ulong> channel, | ||
SocketReaction reaction) : INotification | ||
{ | ||
public Cacheable<IUserMessage, ulong> Message { get; } = message; | ||
public Cacheable<IMessageChannel, ulong> Channel { get; } = channel; | ||
public SocketReaction Reaction { get; } = reaction; | ||
} |
15 changes: 15 additions & 0 deletions
15
src/Modix.Bot/Notifications/ReactionRemovedNotificationV3.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Discord; | ||
using Discord.WebSocket; | ||
using MediatR; | ||
|
||
namespace Modix.Bot.Notifications; | ||
|
||
public class ReactionRemovedNotificationV3( | ||
Cacheable<IUserMessage, ulong> message, | ||
Cacheable<IMessageChannel, ulong> channel, | ||
SocketReaction reaction): INotification | ||
{ | ||
public Cacheable<IUserMessage, ulong> Message { get; } = message; | ||
public Cacheable<IMessageChannel, ulong> Channel { get; } = channel; | ||
public SocketReaction Reaction { get; } = reaction; | ||
} |
26 changes: 26 additions & 0 deletions
26
src/Modix.Bot/Responders/AutoRemoveMessages/AutoRemoveMessageResponder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using MediatR; | ||
using Modix.Bot.Notifications; | ||
|
||
namespace Modix.Bot.Responders.AutoRemoveMessages; | ||
|
||
public class AutoRemoveMessageResponder(AutoRemoveMessageService service) : | ||
INotificationHandler<ReactionAddedNotificationV3> | ||
{ | ||
public async Task Handle(ReactionAddedNotificationV3 notification, CancellationToken cancellationToken) | ||
{ | ||
if (cancellationToken.IsCancellationRequested | ||
|| notification.Reaction.Emote.Name != "❌" | ||
|| !service.IsKnownRemovableMessage(notification.Message.Id, out var cachedMessage) | ||
|| !cachedMessage.Users.Any(user => user.Id == notification.Reaction.UserId)) | ||
{ | ||
return; | ||
} | ||
|
||
await cachedMessage.Message.DeleteAsync(); | ||
|
||
service.UnregisterRemovableMessage(cachedMessage.Message); | ||
} | ||
} |
Oops, something went wrong.