Skip to content

Commit 5bbde45

Browse files
Merge pull request #1022 from PaulBraetz/vc-status-moderation
Voice channel status moderation against blocklist patterns
2 parents b4324e5 + 9a3f09d commit 5bbde45

File tree

3 files changed

+83
-4
lines changed

3 files changed

+83
-4
lines changed

src/Modix.Services/Core/DiscordSocketListeningBehavior.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public Task StartAsync(
3434
DiscordSocketClient.AuditLogCreated += OnAuditLogCreatedAsync;
3535
DiscordSocketClient.ChannelCreated += OnChannelCreatedAsync;
3636
DiscordSocketClient.ChannelUpdated += OnChannelUpdatedAsync;
37+
DiscordSocketClient.VoiceChannelStatusUpdated += OnVoiceChannelStatusUpdated;
3738
DiscordSocketClient.GuildAvailable += OnGuildAvailableAsync;
3839
DiscordSocketClient.GuildMemberUpdated += OnGuildMemberUpdatedAsync;
3940
DiscordSocketClient.InteractionCreated += OnInteractionCreatedAsync;
@@ -61,6 +62,7 @@ public Task StopAsync(
6162
DiscordSocketClient.AuditLogCreated -= OnAuditLogCreatedAsync;
6263
DiscordSocketClient.ChannelCreated -= OnChannelCreatedAsync;
6364
DiscordSocketClient.ChannelUpdated -= OnChannelUpdatedAsync;
65+
DiscordSocketClient.VoiceChannelStatusUpdated -= OnVoiceChannelStatusUpdated;
6466
DiscordSocketClient.GuildAvailable -= OnGuildAvailableAsync;
6567
DiscordSocketClient.GuildMemberUpdated -= OnGuildMemberUpdatedAsync;
6668
DiscordSocketClient.InteractionCreated += OnInteractionCreatedAsync;
@@ -103,6 +105,13 @@ private Task OnChannelCreatedAsync(SocketChannel channel)
103105
return Task.CompletedTask;
104106
}
105107

108+
private Task OnVoiceChannelStatusUpdated(Cacheable<SocketVoiceChannel, ulong> channel, string oldStatus, string newStatus)
109+
{
110+
MessageDispatcher.Dispatch(new VoiceChannelStatusUpdatedNotification(channel, oldStatus, newStatus));
111+
112+
return Task.CompletedTask;
113+
}
114+
106115
private Task OnChannelUpdatedAsync(SocketChannel oldChannel, SocketChannel newChannel)
107116
{
108117
MessageDispatcher.Dispatch(new ChannelUpdatedNotification(oldChannel, newChannel));
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
3+
using Discord.WebSocket;
4+
5+
namespace Discord
6+
{
7+
/// <summary>
8+
/// Describes an application-wide notification that occurs when <see cref="IBaseSocketClient.VoiceChannelStatusUpdated"/> is raised.
9+
/// </summary>
10+
public class VoiceChannelStatusUpdatedNotification
11+
{
12+
/// <summary>
13+
/// Constructs a new <see cref="VoiceChannelStatusUpdatedNotification"/> from the given values.
14+
/// </summary>
15+
/// <param name="channel">The value to use for <see cref="Channel"/>.</param>
16+
/// <param name="oldStatus">The value to use for <see cref="OldStatus"/>.</param>
17+
/// <param name="newStatus">The value to use for <see cref="NewStatus"/>.</param>
18+
/// <exception cref="ArgumentNullException">Throws for <paramref name="oldStatus"/>.</exception>
19+
/// <exception cref="ArgumentNullException">Throws for <paramref name="newStatus"/>.</exception>
20+
public VoiceChannelStatusUpdatedNotification(Cacheable<SocketVoiceChannel, ulong> channel, string oldStatus, string newStatus)
21+
{
22+
ArgumentNullException.ThrowIfNull(oldStatus);
23+
ArgumentNullException.ThrowIfNull(newStatus);
24+
25+
Channel = channel;
26+
OldStatus = oldStatus;
27+
NewStatus = newStatus;
28+
}
29+
/// <summary>
30+
/// The voice channel whose status was updated.
31+
/// </summary>
32+
public Cacheable<SocketVoiceChannel, ulong> Channel { get; }
33+
/// <summary>
34+
/// The old voice channel status.
35+
/// </summary>
36+
public string OldStatus { get; }
37+
/// <summary>
38+
/// The new voice channel status.
39+
/// </summary>
40+
public string NewStatus { get; }
41+
}
42+
}

src/Modix.Services/Moderation/MessageContentCheckBehaviour.cs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace Modix.Services.Moderation
1515
{
1616
public class MessageContentCheckBehaviour :
1717
INotificationHandler<MessageReceivedNotification>,
18-
INotificationHandler<MessageUpdatedNotification>
18+
INotificationHandler<MessageUpdatedNotification>,
19+
INotificationHandler<VoiceChannelStatusUpdatedNotification>
1920
{
2021
private readonly IDesignatedChannelService _designatedChannelService;
2122
private readonly IAuthorizationService _authorizationService;
@@ -43,6 +44,29 @@ public Task HandleNotificationAsync(MessageReceivedNotification notification,
4344
public Task HandleNotificationAsync(MessageUpdatedNotification notification,
4445
CancellationToken cancellationToken = default)
4546
=> TryCheckMessageAsync(notification.NewMessage);
47+
public async Task HandleNotificationAsync(VoiceChannelStatusUpdatedNotification notification,
48+
CancellationToken cancellationToken = default)
49+
{
50+
var channel = await notification.Channel.GetOrDownloadAsync();
51+
var newStatus = notification.NewStatus;
52+
var isBlocked = await IsContentBlocked(channel, newStatus);
53+
54+
if (!isBlocked)
55+
{
56+
return;
57+
}
58+
59+
Log.Debug("Status {newStatus} from voice channel {channelId} is going to be deleted", newStatus, channel.Id);
60+
61+
//Setting to old status seems risky as there is a race condition
62+
//between two consecutive edits being moderated in parallel.
63+
//May client events being fired in parallel?
64+
await channel.SetStatusAsync(string.Empty);
65+
66+
Log.Debug("Status {newStatus} from voice channel {channelId} was deleted because it contains blocked content", newStatus, channel.Id);
67+
68+
await channel.SendMessageAsync("Sorry, the new status contained blocked content and has been removed!");
69+
}
4670

4771
private async Task TryCheckMessageAsync(IMessage message)
4872
{
@@ -91,16 +115,20 @@ await message.Channel.SendMessageAsync(
91115
$"Sorry {author.Mention} your message contained blocked content and has been removed!");
92116
}
93117

94-
private async Task<bool> IsContentBlocked(IGuildChannel channel, IMessage message)
118+
private Task<bool> IsContentBlocked(SocketVoiceChannel channel, string status) =>
119+
IsContentBlocked(channel.Guild.Id, status);
120+
private Task<bool> IsContentBlocked(IGuildChannel channel, IMessage message) =>
121+
IsContentBlocked(channel.GuildId, message.Content);
122+
private async Task<bool> IsContentBlocked(ulong guildId, string messageContent)
95123
{
96-
var patterns = await _messageContentPatternService.GetPatterns(channel.GuildId);
124+
var patterns = await _messageContentPatternService.GetPatterns(guildId);
97125

98126
foreach (var patternToCheck in patterns.Where(x => x.Type == MessageContentPatternType.Blocked))
99127
{
100128
// If the content is not blocked, we can just continue to check the next
101129
// blocked pattern
102130

103-
var (containsBlockedPattern, blockedMatches) = GetContentMatches(message.Content, patternToCheck);
131+
var (containsBlockedPattern, blockedMatches) = GetContentMatches(messageContent, patternToCheck);
104132

105133
if (!containsBlockedPattern)
106134
{

0 commit comments

Comments
 (0)