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; } }