namespace Supercell.Laser.Server.SCID { using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Http; using Supercell.Laser.Server.Database.Models; internal static partial class SCIDApi { public static IResult Handle(HttpRequest request, string path, Dictionary body) { path = NormalizeSocialPath(path); if (path.StartsWith("social/", StringComparison.Ordinal)) return HandleSocial(request, path, body); switch (path) { case "account/info.get": return AccountInfo(request, body); case "account/settings.get": return SettingsGet(request, body); case "account/settings.set": return SettingsSet(request, body); case "account/settings.setConsent": return SettingsSetConsent(request, body); case "inventory/v1/items.claim": case "inventory/v1/items.claimComplete": case "inventory/v1/items.donate": case "inventory/v1/items.accept": case "inventory/v1/items.reject": case "event/v1/notification.ack": return Ok(); case "inventory/v1/items.list": return Ok(new { items = Array.Empty() }); default: return Ok(); } } private static string NormalizeSocialPath(string path) { return path switch { "profile.get" => "social/v1/profile.get", "profile.info" => "social/v1/profile.info", "profile.set" => "social/v1/profile.set", "profile.validate" => "social/v1/profile.validate", "profile.report" => "social/v1/profile.report", "profiles.list" => "social/v1/profiles.list", "friends.remove" => "social/v1/friends.remove", "friends.block" => "social/v1/friends.block", "friends.unblock" => "social/v1/friends.unblock", "friends.rejectRequest" => "social/v1/friends.rejectRequest", "friends.acceptRequest" => "social/v1/friends.acceptRequest", "ingame.invitetoplay" => "social/v1/ingame.invitetoplay", "friends.list" => "social/v2/friends.list", "friends.createRequest" => "social/v2/friends.createRequest", "friends.cancelRequest" => "social/v2/friends.cancelRequest", _ => path }; } private static IResult AccountInfo(HttpRequest request, Dictionary body) { SCIDAccount account = GetCurrentAccount(request, body); object[] connected = account?.GameAccountId > 0 ? new object[] { new { system = "laser", environment = "prod" } } : Array.Empty(); return Ok(new { availableSystems = new[] { new { system = "laser", environment = "prod" } }, connectedSystems = connected }); } private static IResult SettingsGet(HttpRequest request, Dictionary body) { SCIDAccount account = GetCurrentAccount(request, body); if (account == null) return Fail("invalid_token"); return Ok(SettingsData(account)); } private static IResult SettingsSet(HttpRequest request, Dictionary body) { SCIDAccount account = GetCurrentAccount(request, body); if (account == null) return Fail("invalid_token"); if (body.ContainsKey("accept_marketing")) account.EmailMarketingPermission = GetBoolean(body, "accept_marketing"); SCIDBase.Save(account); return Ok(SettingsData(account)); } private static IResult SettingsSetConsent(HttpRequest request, Dictionary body) { SCIDAccount account = GetCurrentAccount(request, body); if (account == null) return Fail("invalid_token"); string scope = Get(body, "marketing_scope")?.Trim(); if (string.IsNullOrEmpty(scope)) return Fail("invalid_scope"); if (!body.ContainsKey("marketing_scope_consent")) return Fail("invalid_consent"); bool consent = GetBoolean(body, "marketing_scope_consent"); account.MarketingConsents ??= new(); account.MarketingConsents[scope] = consent; SCIDBase.Save(account); return Ok(new { scope_id = scope, scope_localized_name = scope, scope_consent = consent }); } private static object SettingsData(SCIDAccount account) { account.MarketingConsents ??= new(); return new { email_marketing_permission = account.EmailMarketingPermission, marketing_scope_consents = account.MarketingConsents.Select(x => new { scope_id = x.Key, scope_localized_name = x.Key, scope_consent = x.Value }).ToArray() }; } private static SCIDAccount GetCurrentAccount(HttpRequest request, Dictionary body) { return SCIDAuthentication.FromRequest(request, body); } private static bool GetBoolean(Dictionary body, string key) { string raw = Get(body, key); if (bool.TryParse(raw, out bool value)) return value; return raw == "1" || string.Equals(raw, "yes", StringComparison.OrdinalIgnoreCase); } private static string Get(Dictionary body, string key) { return body.TryGetValue(key, out string value) ? value : null; } private static IResult Ok() => Results.Json(new { ok = true }); private static IResult Ok(object data) => Results.Json(new { ok = true, data }); private static IResult Fail(string error) => Results.Json(new { ok = false, error }); } }