Skip to content

Commit

Permalink
feat: Add support for sanitizing slash commands mentions
Browse files Browse the repository at this point in the history
  • Loading branch information
Lexedia committed Aug 16, 2024
1 parent f88e0f7 commit 8c53764
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
28 changes: 24 additions & 4 deletions lib/src/utils/sanitizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ final channelMentionRegex = RegExp(r"<#(\d+)>");
/// A pattern that matches guild emojis in a message.
final guildEmojiRegex = RegExp(r"<(a?):(\w+):(\d+)>");

const _baseCommandNamePattern = r"[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]+";

/// A pattern that matches slash commands in a message.
final commandMentionRegex = RegExp(
'<\\/(?<commandName>(?:$_baseCommandNamePattern(?:\\s$_baseCommandNamePattern){0,2})):(\\d{17,19})>',
unicode: true,
multiLine: true,
);

/// A type of target [sanitizeContent] can operate on.
enum SanitizerTarget {
/// Sanitize user mentions that match [userMentionRegex].
Expand All @@ -34,6 +43,9 @@ enum SanitizerTarget {

/// Sanitize guild emojis that match [guildEmojiRegex].
emojis,

/// Sanitize slash commands mentions that match [commandMentionRegex].
commands,
}

/// An action [sanitizeContent] can take on a target.
Expand Down Expand Up @@ -77,9 +89,10 @@ Future<String> sanitizeContent(
SanitizerTarget.everyone => everyoneMentionRegex,
SanitizerTarget.channels => channelMentionRegex,
SanitizerTarget.emojis => guildEmojiRegex,
SanitizerTarget.commands => commandMentionRegex,
};

Future<String> name(Match match, SanitizerTarget target) async => switch (target) {
Future<String> name(RegExpMatch match, SanitizerTarget target) async => switch (target) {
SanitizerTarget.everyone => match.group(1)!,
SanitizerTarget.channels => switch (await client.channels[Snowflake.parse(match.group(1)!)].getOrNull()) {
GuildChannel(:final name) || GroupDmChannel(:final name) => name,
Expand All @@ -99,18 +112,24 @@ Future<String> sanitizeContent(
},
},
SanitizerTarget.emojis => match.group(2)!,
SanitizerTarget.commands => match.namedGroup('commandName')!,
};

String prefix(SanitizerTarget target) => switch (target) {
SanitizerTarget.users || SanitizerTarget.roles => '@',
SanitizerTarget.everyone => '@$_whitespaceCharacter',
SanitizerTarget.channels => '#',
SanitizerTarget.emojis => '',
SanitizerTarget.commands => '</',
};

String suffix(SanitizerTarget target) => target == SanitizerTarget.emojis ? ':' : '';
String suffix(SanitizerTarget target) => switch (target) {
SanitizerTarget.emojis => ':',
SanitizerTarget.commands => '>',
_ => '',
};

Future<String> resolve(Match match, SanitizerTarget target, SanitizerAction action) async => switch (action) {
Future<String> resolve(RegExpMatch match, SanitizerTarget target, SanitizerAction action) async => switch (action) {
SanitizerAction.ignore => match.group(0)!,
SanitizerAction.remove => '',
SanitizerAction.nameNoPrefix => await name(match, target),
Expand All @@ -120,7 +139,8 @@ Future<String> sanitizeContent(
SanitizerTarget.roles => '<@&$_whitespaceCharacter${match.group(1)!}>',
SanitizerTarget.everyone => '@$_whitespaceCharacter${match.group(1)!}',
SanitizerTarget.channels => '<#$_whitespaceCharacter${match.group(1)!}>',
SanitizerTarget.emojis => '<$_whitespaceCharacter${match.group(1) ?? ''}:${match.group(2)}:${match.group(3)}>',
SanitizerTarget.emojis => '<$_whitespaceCharacter${match.group(1) ?? ''}\\:${match.group(2)}\\:${match.group(3)}>',
SanitizerTarget.commands => '</$_whitespaceCharacter${match.namedGroup('commandName')}:${match.group(2)}>',
},
};

Expand Down
6 changes: 3 additions & 3 deletions test/unit/sanitizer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import 'package:test/test.dart';

const _whitespaceCharacter = "‎";

final sampleContent = '<@1234> test <@!2345> test2 <@&3456> test3 <#4567> test4 <a:test_emoji:5678> test5 <:test_emoji:6789>';
final removed = ' test test2 test3 test4 test5 ';
final sampleContent = '<@1234> test <@!2345> test2 <@&3456> test3 <#4567> test4 <a:test_emoji:5678> test5 <:test_emoji:6789> test6 </test command:123456789123456789>';
final removed = ' test test2 test3 test4 test5 test6 ';
final sanitized =
'<@${_whitespaceCharacter}1234> test <@${_whitespaceCharacter}2345> test2 <@&${_whitespaceCharacter}3456> test3 <#${_whitespaceCharacter}4567> test4 <${_whitespaceCharacter}a:test_emoji:5678> test5 <$_whitespaceCharacter:test_emoji:6789>';
'<@${_whitespaceCharacter}1234> test <@${_whitespaceCharacter}2345> test2 <@&${_whitespaceCharacter}3456> test3 <#${_whitespaceCharacter}4567> test4 <${_whitespaceCharacter}a\\:test_emoji\\:5678> test5 <$_whitespaceCharacter\\:test_emoji\\:6789> test6 </${_whitespaceCharacter}test command:123456789123456789>';

class MockNyxxRest with Mock implements NyxxRest {}

Expand Down

0 comments on commit 8c53764

Please sign in to comment.