namespace RadicadeServer.Utils { public static class UsernameRules { public const int MinLength = 3; public const int MaxLength = 24; private static readonly string[] ReservedNames = [ "me", "you", "recroom", "recnet", "radicade", "againstgravity", "system", "admin", "administrator", "moderator", "mod", "support", "staff", "official", "developer", "owner", "root" ]; public static string? Normalize(string? posted) { if (string.IsNullOrWhiteSpace(posted)) return null; var name = posted.Trim().TrimStart('@').Trim(); return name.Length == 0 ? null : name; } public static string? Parse(string? posted, out string? rejection) { rejection = null; var name = Normalize(posted); if (name == null) return null; rejection = Rejection(name); return rejection == null ? name : null; } public static string? Rejection(string name) { if (name.Length < MinLength) return $"Names must be at least {MinLength} characters."; if (name.Length > MaxLength) return $"Names must be {MaxLength} characters or fewer."; bool hasLetter = false; foreach (var character in name) { if (char.IsAsciiLetter(character)) { hasLetter = true; continue; } if (char.IsAsciiDigit(character)) continue; return "Names can only use letters and numbers."; } if (!hasLetter) return "Names must contain at least one letter."; if (ReservedNames.Any(reserved => string.Equals(reserved, name, StringComparison.OrdinalIgnoreCase))) return "That name is reserved. Please pick another one."; if (!name.IsPure()) return "That name is not allowed. Please pick another one."; return null; } public static string ComparisonKey(string name) => name.ToUpperInvariant(); public static string Generate() => RecNet.Generators.GenerateUsername(); } }