Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cliptok.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.2" />
<PackageReference Include="Serilog.Sinks.TextWriter" Version="3.0.0" />
<PackageReference Include="SkiaSharp" Version="4.148.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="4.148.0" />
<PackageReference Include="StackExchange.Redis" Version="2.13.17" />
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Linq.Async" Version="7.0.1" />
Expand Down
35 changes: 35 additions & 0 deletions Commands/DebugCmds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,41 @@ public class DebugCmds
{
public static Dictionary<ulong, PendingUserOverride> OverridesPendingAddition = new();

[Command("gif")]
[Description("Debug GIF properties.")]
public async Task GifDebug(CommandContext ctx, string gifToCheck)
{
if (Program.cfgjson.SeizureDetection is null)
{
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Seizure detection is not configured! Please check `seizureDetection` in config.json.");
return;
}

string gifUrl;
var emojiMatches = Constants.RegexConstants.animoji_rx.Matches(gifToCheck);
if (emojiMatches.Count > 0)
{
gifUrl = "https://cdn.discordapp.com/emojis/" + Constants.RegexConstants.id_rx.Match(emojiMatches.First().Value).Value + ".gif";
}
else
{
gifUrl = gifToCheck;
}

SeizureDetectionHelpers.ImageInfo Gif = await SeizureDetectionHelpers.GetGifPropertiesAsync(gifUrl);
string strOut = "**GIF information**\n";
strOut += $"----------\nFrame count: **{Gif.FrameCount}**\n";
strOut += $"Unique frame count: **{Gif.UniqueFrameCount}**\n";
strOut += $"Average frame difference: **{Math.Round(Gif.AverageFrameDifference, 2)}**\n";
strOut += $"Average frame contrast: **{Math.Round(Gif.AverageContrast, 2)}**\n";
strOut += $"Length: **{Gif.Length}ms**\n";
strOut += $"Frame duration: **{Math.Round(Gif.Duration, 2)}ms**\n";
strOut += $"Framerate: **{Math.Round(Gif.FrameRate, 2)}fps**\n";
strOut += $"Seizure-inducing: **{Gif.IsSeizureInducing}**\n";
strOut += "----------";
await ctx.RespondAsync(strOut);
}

[Command("logprint")]
public async Task LogPrint(TextCommandContext ctx)
{
Expand Down
1 change: 1 addition & 0 deletions Constants/RegexConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ public class RegexConstants
readonly public static Regex webhook_rx = new("(?:https?:\\/\\/)?discord(?:app)?.com\\/api\\/(?:v\\d\\/)?webhooks\\/(?<id>\\d+)\\/(?<token>[A-Za-z0-9_\\-]+)", RegexOptions.ECMAScript);
readonly public static Regex id_rx = new("[0-9]{17,}");
readonly public static Regex image_url_rx = new(@"https:\/\/(?:(?:i\.)?imgur\.com\/(?:a\/)?[A-Za-z0-9]+(?:\.[A-Za-z]{3,4})?|i\.ibb\.co\/[A-Za-z0-9]+\/[A-Za-z0-9]+\.[A-Za-z]{3,4}|(?:cdn\.discordapp\.com|media\.discordapp\.net)\/attachments\/[0-9]{17,}\/[0-9]{17,}\/[A-Za-z0-9]+\.[A-Za-z]{3,4}\?ex=[A-Za-z0-9]+&is=[A-Za-z0-9]+&hm=[A-Za-z0-9]+&?(?:=&format=[A-Za-z0-9]+&width=[0-9]+&height=[0-9]+)?)");
readonly public static Regex animoji_rx = new Regex("<a:.{2,32}:[0-9]{1,32}>");
}
}
35 changes: 35 additions & 0 deletions Events/MessageEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ public static async Task MessageHandlerAsync(DiscordClient client, MockDiscordMe

if (await RunPhishingApiFilterAsync(client, message, channel, member, permLevel, msgContentWithEmbedData, isAnEdit, limitFilters, wasAutoModBlock)) return;

if (await RunSeizureInducingEmojiFilterAsync(client, message, channel, member, permLevel, msgContentWithEmbedData, isAnEdit, limitFilters, wasAutoModBlock)) return;

if (await RunEveryoneHerePingFilterAsync(client, message, channel, member, permLevel, msgContentWithEmbedData, isAnEdit, limitFilters, wasAutoModBlock)) return;

if (await RunMassMentionsWarnFilterAsync(client, message, channel, member, permLevel, msgContentWithEmbedData, isAnEdit, limitFilters, wasAutoModBlock)) return;
Expand Down Expand Up @@ -1210,6 +1212,39 @@ private static async Task<bool> RunPhishingApiFilterAsync(DiscordClient client,
return false;
}

private static async Task<bool> RunSeizureInducingEmojiFilterAsync(DiscordClient client, MockDiscordMessage message, DiscordChannel channel, DiscordMember member, ServerPermLevel permLevel, string msgContentWithEmbedData, bool isAnEdit, bool limitFilters, bool wasAutoModBlock)
{
if (Program.cfgjson.SeizureDetection is null)
return false;

var emojiMatches = animoji_rx.Matches(message.Content);
if (emojiMatches.Count > 0)
{
foreach (Match emoji in emojiMatches)
{
string id = id_rx.Match(emoji.Value).Value;
string url = "https://cdn.discordapp.com/emojis/" + id + ".gif";

if ((await SeizureDetectionHelpers.GetGifPropertiesAsync(url)).IsSeizureInducing)
{
if (wasAutoModBlock)
{
Program.discord.Logger.LogDebug("AutoMod-blocked message in {channelId} by user {userId} triggered seizure-inducing emoji filter", channel.Id, message.Author.Id);
}
else
{
Program.discord.Logger.LogDebug("Message {messageId} in {channelId} by user {userId} triggered seizure-inducing emoji filter", message.Id, channel.Id, message.Author.Id);
}

await DeleteAndWarnAsync(message, "Sent a seizure-inducing emoji", client, wasAutoModBlock: wasAutoModBlock);
return true;
}
}
}

return false;
}

private static async Task<bool> RunEveryoneHerePingFilterAsync(DiscordClient client, MockDiscordMessage message, DiscordChannel channel, DiscordMember member, ServerPermLevel permLevel, string messageContentOverride = default, bool isAnEdit = false, bool limitFilters = false, bool wasAutoModBlock = false)
{
var msgContent = message.Content;
Expand Down
1 change: 1 addition & 0 deletions GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
global using Newtonsoft.Json.Linq;
global using Serilog;
global using Serilog.Sinks.SystemConsole.Themes;
global using SkiaSharp;
global using StackExchange.Redis;
global using System;
global using System.Collections.Generic;
Expand Down
Loading