68 lines
2.8 KiB
C#
68 lines
2.8 KiB
C#
using System.Text.Json.Nodes;
|
|||
|
|
|
||
|
|
using static PrivaPub.Federation.Objects.ActivityJson;
|
||
|
|
|
||
|
|
namespace PrivaPub.Federation.Objects
|
||
|
|
{
|
||
|
|
public static class ObjectFeatures
|
||
|
|
{
|
||
|
|
public static List<string> Detect(JsonObject raw)
|
||
|
|
{
|
||
|
|
var found = new List<string>();
|
||
|
|
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<string> Namespaces(JsonObject raw, string activityContext = default) =>
|
||
|
|
Namespaces(raw?["@context"] ?? (activityContext == default ? default : JsonNode.Parse(activityContext)));
|
||
|
|
|
||
|
|
static List<string> Namespaces(JsonNode context) => context switch
|
||
|
|
{
|
||
|
|
JsonValue single when single.TryGetValue<string>(out var url) => new List<string> { url },
|
||
|
|
JsonArray array => array.SelectMany(entry => entry switch
|
||
|
|
{
|
||
|
|
JsonValue value when value.TryGetValue<string>(out var url) => new[] { url },
|
||
|
|
JsonObject terms => terms.Where(t => t.Value is JsonValue v && v.TryGetValue<string>(out var target) && target.EndsWith('#'))
|
||
|
|
.Select(t => t.Key + "=" + t.Value!.GetValue<string>()),
|
||
|
|
_ => Enumerable.Empty<string>()
|
||
|
|
})
|
||
|
|
.Take(32)
|
||
|
|
.ToList(),
|
||
|
|
_ => new List<string>()
|
||
|
|
};
|
||
|
|
|
||
|
|
static IEnumerable<JsonObject> Items(JsonNode node) => node switch
|
||
|
|
{
|
||
|
|
JsonArray array => array.OfType<JsonObject>(),
|
||
|
|
JsonObject single => new[] { single },
|
||
|
|
_ => Enumerable.Empty<JsonObject>()
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|