using System.Text.Json; namespace RadicadeServer.Auth; public static class SteamWhitelist { public sealed class WhitelistFile { public bool Enabled { get; set; } public List SteamIds { get; set; } = new(); } private static readonly JsonSerializerOptions CaseInsensitive = new() { PropertyNameCaseInsensitive = true }; private static readonly object Lock = new(); private static WhitelistFile? _data; private static string _filePath = ""; private static bool _loaded; private static DateTime _lastWriteUtc = DateTime.MinValue; public static string FilePath => _filePath; public static bool CreatedEmptyConfig { get; private set; } public static void Load() { lock (Lock) { if (_loaded) return; _filePath = Path.GetFullPath(Path.Join(DBConfig.PrivateData, "steamwhitelist.json")); _loaded = true; CreatedEmptyConfig = !File.Exists(_filePath); try { if (CreatedEmptyConfig) { _data = new WhitelistFile { Enabled = false, SteamIds = new List() }; } else { var raw = File.ReadAllText(_filePath); _data = JsonSerializer.Deserialize(raw, CaseInsensitive) ?? new WhitelistFile(); _data.SteamIds ??= new List(); _lastWriteUtc = File.GetLastWriteTimeUtc(_filePath); } } catch (Exception) { _data = new WhitelistFile { Enabled = false, SteamIds = new List() }; } } } public static bool Enabled { get { EnsureLoaded(); lock (Lock) return _data!.Enabled; } set { EnsureLoaded(); lock (Lock) { _data!.Enabled = value; SaveLocked(); } } } public static IReadOnlyCollection SteamIds { get { EnsureLoaded(); lock (Lock) return _data!.SteamIds.ToList(); } } public static void SetSteamIds(IEnumerable steamIds) { EnsureLoaded(); lock (Lock) { _data!.SteamIds = steamIds .Where(id => !string.IsNullOrWhiteSpace(id)) .Select(id => id.Trim()) .Distinct() .ToList(); SaveLocked(); } } public static bool Contains(string steamId) { if (string.IsNullOrWhiteSpace(steamId)) return false; EnsureLoaded(); lock (Lock) return _data!.SteamIds.Contains(steamId.Trim()); } public static bool Add(string steamId) { if (string.IsNullOrWhiteSpace(steamId)) return false; steamId = steamId.Trim(); EnsureLoaded(); lock (Lock) { if (_data!.SteamIds.Contains(steamId)) return false; _data.SteamIds.Add(steamId); SaveLocked(); return true; } } public static bool Remove(string steamId) { if (string.IsNullOrWhiteSpace(steamId)) return false; steamId = steamId.Trim(); EnsureLoaded(); lock (Lock) { var removed = _data!.SteamIds.Remove(steamId); if (removed) SaveLocked(); return removed; } } private static void EnsureLoaded() { if (!_loaded) { Load(); return; } lock (Lock) { DateTime lastWriteUtc; try { lastWriteUtc = File.GetLastWriteTimeUtc(_filePath); } catch { return; } if (lastWriteUtc > _lastWriteUtc) { try { var raw = File.ReadAllText(_filePath); var reloaded = JsonSerializer.Deserialize(raw, CaseInsensitive); if (reloaded != null) { reloaded.SteamIds ??= new List(); _data = reloaded; _lastWriteUtc = lastWriteUtc; } } catch (Exception) { } } } } private static void SaveLocked() { try { var dir = Path.GetDirectoryName(_filePath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); var options = new JsonSerializerOptions { WriteIndented = true }; File.WriteAllText(_filePath, JsonSerializer.Serialize(_data, options)); _lastWriteUtc = File.GetLastWriteTimeUtc(_filePath); } catch (Exception) { } } }