65 lines
No EOL
1.7 KiB
C#
65 lines
No EOL
1.7 KiB
C#
using System.Text;
|
|
|
|
namespace Foxcord.Rest.Rate;
|
|
|
|
// All of this code is taken from Arikawa:
|
|
// https://github.com/diamondburned/arikawa/blob/v3/api/rate/rate.go
|
|
internal static class BucketKeyUtils
|
|
{
|
|
private static readonly string[] MajorRootPaths = ["channels", "guilds"];
|
|
|
|
internal static string Parse(string path)
|
|
{
|
|
path = path.Split("?", 2)[0];
|
|
var parts = path.Split("/");
|
|
if (parts.Length == 0) return path;
|
|
parts = parts.Skip(1).ToArray();
|
|
|
|
var skip = 0;
|
|
if (MajorRootPaths.Contains(parts[0])) skip = 2;
|
|
|
|
skip++;
|
|
for (; skip < parts.Length; skip += 2)
|
|
{
|
|
if (long.TryParse(parts[skip], out _) || StringIsEmojiOnly(parts[skip]) || StringIsCustomEmoji(parts[skip]))
|
|
parts[skip] = "";
|
|
}
|
|
|
|
path = string.Join("/", parts);
|
|
return $"/{path}";
|
|
}
|
|
|
|
private static bool StringIsCustomEmoji(string emoji)
|
|
{
|
|
var parts = emoji.Split(":");
|
|
if (parts.Length != 2) return false;
|
|
|
|
if (!long.TryParse(parts[1], out _)) return false;
|
|
if (parts[0].Contains(' ')) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool StringIsEmojiOnly(string emoji)
|
|
{
|
|
var runes = emoji.EnumerateRunes().ToArray();
|
|
switch (runes.Length)
|
|
{
|
|
case 0:
|
|
return false;
|
|
case 1:
|
|
case 2:
|
|
return EmojiRune(runes[0]);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool EmojiRune(Rune r)
|
|
{
|
|
if (r == new Rune('\u00a9') || r == new Rune('\u00ae') ||
|
|
(r >= new Rune('\u2000') && r <= new Rune('\u3300'))) return true;
|
|
|
|
return false;
|
|
}
|
|
} |