using System.Text.Json.Nodes; using static PrivaPub.Federation.Objects.ActivityJson; namespace PrivaPub.Federation.Objects { public static class ObjectFeatures { public static List Detect(JsonObject raw) { var found = new List(); if (raw == default) return found; void When(bool condition, string feature) { if (condition) found.Add(feature); } When(raw.ContainsKey("quote"), "fep-044f-quote"); When(raw.ContainsKey("quoteAuthorization"), "fep-044f-authorization"); When(raw.ContainsKey("_misskey_quote") || raw.ContainsKey("quoteUrl") || raw.ContainsKey("quoteUri"), "legacy-quote"); When(raw.ContainsKey("interactionPolicy"), "interaction-policy"); When(raw.ContainsKey("context"), "context"); When(raw.ContainsKey("proof"), "fep-8b32-proof"); When(raw.Any(p => p.Key.StartsWith("_misskey_", StringComparison.Ordinal)), "misskey"); When(raw["source"] is JsonObject, "source:" + (Value(raw["source"], "mediaType") ?? "unknown")); When(raw["source"] is JsonValue, "source:url"); When(raw.ContainsKey("htmlMfm"), "fep-c16b-mfm"); When(raw.ContainsKey("formerRepresentations"), "former-representations"); When(raw.ContainsKey("searchableBy"), "fep-268d-searchable-by"); When(raw.ContainsKey("audience"), "fep-1b12-audience"); When(Items(raw["attachment"]).Any(a => Value(a, "type") == "Link"), "fep-8967-link"); When(Items(raw["tag"]).Any(t => Value(t, "type") == "Emoji"), "custom-emoji"); When(Value(raw, "type") == "Question", "poll"); When(raw["contentMap"] is JsonObject, "content-map"); When(raw["url"] is JsonArray, "url-variants"); var contentType = Value(raw, "mediaType"); When(contentType is not (null or "text/html"), "content:" + contentType); return found; } public static List Namespaces(JsonObject raw, string activityContext = default) => Namespaces(raw?["@context"] ?? (activityContext == default ? default : JsonNode.Parse(activityContext))); static List Namespaces(JsonNode context) => context switch { JsonValue single when single.TryGetValue(out var url) => new List { url }, JsonArray array => array.SelectMany(entry => entry switch { JsonValue value when value.TryGetValue(out var url) => new[] { url }, JsonObject terms => terms.Where(t => t.Value is JsonValue v && v.TryGetValue(out var target) && target.EndsWith('#')) .Select(t => t.Key + "=" + t.Value!.GetValue()), _ => Enumerable.Empty() }) .Take(32) .ToList(), _ => new List() }; static IEnumerable Items(JsonNode node) => node switch { JsonArray array => array.OfType(), JsonObject single => new[] { single }, _ => Enumerable.Empty() }; } }