Skip to content

Commit

Permalink
Optimize and calculate total weight
Browse files Browse the repository at this point in the history
  • Loading branch information
hhvrc committed Sep 12, 2024
1 parent b78f3f5 commit bccdb27
Showing 1 changed file with 40 additions and 17 deletions.
57 changes: 40 additions & 17 deletions DiscordBot/MessageHandler/MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public sealed class MessageHandler
{ "slut", 0.6f },
{ "fuck", 0.3f },
};
private static readonly HashSet<string> _containedProfanitiesSet = new(_containedProfanities.Keys);

private static readonly Dictionary<string, float> _standaloneProfanities = new() {
{ "anal", 0.6f },
Expand All @@ -32,38 +31,62 @@ public sealed class MessageHandler
{ "piss", 0.3f },
{ "ass", 0.2f },
};
private static readonly HashSet<string> _standaloneProfanitiesSet = new(_standaloneProfanities.Keys);

private static bool TryGetProfanityWeight(string str, out float weight)
private readonly record struct WordRange(int Start, int Length);

private static bool TryGetProfanityWeight(string str, out int count, out float weight)
{
count = 0;
weight = 0;

if (string.IsNullOrEmpty(str)) return false;

// Whole string contains word check
foreach (var profanity in _containedProfanities)
ReadOnlySpan<char> strSpan = str.AsSpan();

// Look trough string for all contained matches
foreach (var kvp in _containedProfanities)
{
if (str.AsSpan().Contains(profanity.Key, StringComparison.OrdinalIgnoreCase))
if (strSpan.Contains(kvp.Key.AsSpan(), StringComparison.OrdinalIgnoreCase))
{
weight = profanity.Value;
return true;
count++;
weight = weight == 0f ? kvp.Value : MathF.Max(weight, kvp.Value) + 0.1f;
}
}

str = str.ToLower();
// Collect all word ranges
int rangeStart = 0;
List<WordRange> wordRanges = [];
for (int i = 0; i < strSpan.Length; i++)
{
char c = strSpan[i];

// Words of string matches words check
var words = str.Split([' ', '\t', '\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
if (c is not (' ' or '\t' or '\r' or '\n')) continue;

foreach (var word in words)
if (rangeStart < i)
{
wordRanges.Add(new WordRange(rangeStart, i - rangeStart));
}

rangeStart = i + 1;
}

// Check if any of the words are standalone matches
foreach (var item in _standaloneProfanities)
{
if (_standaloneProfanities.TryGetValue(word, out weight))
foreach (var wordRange in wordRanges)
{
return true;
if (strSpan.Slice(wordRange.Start, wordRange.Length).Equals(item.Key.AsSpan(), StringComparison.OrdinalIgnoreCase))
{
count++;
weight = weight == 0f ? item.Value : MathF.Max(weight, item.Value) + 0.1f;
}
}
}

return false;
// Roof the weight to 1.0
weight = MathF.Min(weight, 1.0f);

return count > 0;
}

public static async Task HandleMessageAsync(SocketMessage message)
Expand All @@ -74,10 +97,10 @@ public static async Task HandleMessageAsync(SocketMessage message)
if (!message.Channel.Name.Contains("bot", StringComparison.OrdinalIgnoreCase)) return;

// Check if the message contains a swear word
if (TryGetProfanityWeight(message.Content, out float weight))
if (TryGetProfanityWeight(message.Content, out int count, out float weight))
{
// Respond to the message
await message.Channel.SendMessageAsync($"Profanity detected! Weight: {weight}");
await message.Channel.SendMessageAsync($"Profanity detected! {count} bad {(count > 1 ? "words" : "word")} with total weight: {weight}");
}
}
}

0 comments on commit bccdb27

Please sign in to comment.