🐛 Fix activitypub nested object issue
This commit is contained in:
@@ -247,19 +247,22 @@ public class ActivityPubActivityHandler(
|
|||||||
private async Task<bool> HandleUndoAsync(string actorUri, Dictionary<string, object> activity)
|
private async Task<bool> HandleUndoAsync(string actorUri, Dictionary<string, object> activity)
|
||||||
{
|
{
|
||||||
var objectValue = activity.GetValueOrDefault("object");
|
var objectValue = activity.GetValueOrDefault("object");
|
||||||
|
var objectDict = ConvertToDictionary(objectValue);
|
||||||
|
|
||||||
if (objectValue is not Dictionary<string, object> objectDict)
|
if (objectDict == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("Unable undo operation, no object found... {Object}", JsonSerializer.Serialize(activity));
|
logger.LogWarning("Unable undo operation, no object found... {Object}", JsonSerializer.Serialize(activity));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectType = objectDict.GetValueOrDefault("type")?.ToString();
|
var objectType = GetStringValue(objectDict, "type");
|
||||||
|
var objectUri = GetStringValue(objectDict, "object");
|
||||||
|
|
||||||
return objectType switch
|
return objectType switch
|
||||||
{
|
{
|
||||||
"Follow" => await UndoFollowAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
"Follow" => await UndoFollowAsync(actorUri, objectUri),
|
||||||
"Like" => await UndoLikeAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
"Like" => await UndoLikeAsync(actorUri, objectUri),
|
||||||
"Announce" => await UndoAnnounceAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
"Announce" => await UndoAnnounceAsync(actorUri, objectUri),
|
||||||
_ => throw new InvalidOperationException($"Unhandled undo operation for {objectType}")
|
_ => throw new InvalidOperationException($"Unhandled undo operation for {objectType}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -267,10 +270,12 @@ public class ActivityPubActivityHandler(
|
|||||||
private async Task<bool> HandleCreateAsync(string actorUri, Dictionary<string, object> activity)
|
private async Task<bool> HandleCreateAsync(string actorUri, Dictionary<string, object> activity)
|
||||||
{
|
{
|
||||||
var objectValue = activity.GetValueOrDefault("object");
|
var objectValue = activity.GetValueOrDefault("object");
|
||||||
if (objectValue is not Dictionary<string, object> objectDict)
|
var objectDict = ConvertToDictionary(objectValue);
|
||||||
|
|
||||||
|
if (objectDict == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var objectType = objectDict.GetValueOrDefault("type")?.ToString();
|
var objectType = GetStringValue(objectDict, "type");
|
||||||
if (objectType != "Note" && objectType != "Article")
|
if (objectType != "Note" && objectType != "Article")
|
||||||
{
|
{
|
||||||
logger.LogInformation("Skipping non-note content type: {Type}", objectType);
|
logger.LogInformation("Skipping non-note content type: {Type}", objectType);
|
||||||
@@ -279,7 +284,7 @@ public class ActivityPubActivityHandler(
|
|||||||
|
|
||||||
var actor = await GetOrCreateActorAsync(actorUri);
|
var actor = await GetOrCreateActorAsync(actorUri);
|
||||||
|
|
||||||
var contentUri = objectDict.GetValueOrDefault("id")?.ToString();
|
var contentUri = GetStringValue(objectDict, "id");
|
||||||
if (string.IsNullOrEmpty(contentUri))
|
if (string.IsNullOrEmpty(contentUri))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -298,16 +303,16 @@ public class ActivityPubActivityHandler(
|
|||||||
FediverseType = objectType == "Article"
|
FediverseType = objectType == "Article"
|
||||||
? FediverseContentType.FediverseArticle
|
? FediverseContentType.FediverseArticle
|
||||||
: FediverseContentType.FediverseNote,
|
: FediverseContentType.FediverseNote,
|
||||||
Title = objectDict.GetValueOrDefault("name")?.ToString(),
|
Title = GetStringValue(objectDict, "name"),
|
||||||
Description = objectDict.GetValueOrDefault("summary")?.ToString(),
|
Description = GetStringValue(objectDict, "summary"),
|
||||||
Content = objectDict.GetValueOrDefault("content")?.ToString(),
|
Content = GetStringValue(objectDict, "content"),
|
||||||
ContentType = objectDict.GetValueOrDefault("contentMap") != null
|
ContentType = objectDict.GetValueOrDefault("contentMap") != null
|
||||||
? PostContentType.Html
|
? PostContentType.Html
|
||||||
: PostContentType.Markdown,
|
: PostContentType.Markdown,
|
||||||
PublishedAt = ParseInstant(objectDict.GetValueOrDefault("published")),
|
PublishedAt = ParseInstant(objectDict.GetValueOrDefault("published")),
|
||||||
EditedAt = ParseInstant(objectDict.GetValueOrDefault("updated")),
|
EditedAt = ParseInstant(objectDict.GetValueOrDefault("updated")),
|
||||||
ActorId = actor.Id,
|
ActorId = actor.Id,
|
||||||
Language = objectDict.GetValueOrDefault("language")?.ToString(),
|
Language = GetStringValue(objectDict, "language"),
|
||||||
Mentions = ParseMentions(objectDict.GetValueOrDefault("tag")),
|
Mentions = ParseMentions(objectDict.GetValueOrDefault("tag")),
|
||||||
Attachments = ParseAttachments(objectDict.GetValueOrDefault("attachment")) ?? [],
|
Attachments = ParseAttachments(objectDict.GetValueOrDefault("attachment")) ?? [],
|
||||||
Type = objectType == "Article" ? PostType.Article : PostType.Moment,
|
Type = objectType == "Article" ? PostType.Article : PostType.Moment,
|
||||||
@@ -545,6 +550,56 @@ public class ActivityPubActivityHandler(
|
|||||||
return uriObj.Host;
|
return uriObj.Host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string? GetStringValue(Dictionary<string, object> dict, string key)
|
||||||
|
{
|
||||||
|
var value = dict.GetValueOrDefault(key);
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
string str => str,
|
||||||
|
JsonElement element => element.ValueKind == JsonValueKind.String ? element.GetString() : element.ToString(),
|
||||||
|
_ => value.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, object>? ConvertToDictionary(object? value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (value is Dictionary<string, object> dict)
|
||||||
|
return dict;
|
||||||
|
|
||||||
|
if (value is JsonElement { ValueKind: JsonValueKind.Object } element)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, object>();
|
||||||
|
foreach (var property in element.EnumerateObject())
|
||||||
|
{
|
||||||
|
result[property.Name] = ConvertJsonElementToObject(property.Value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ConvertJsonElementToObject(JsonElement element)
|
||||||
|
{
|
||||||
|
return element.ValueKind switch
|
||||||
|
{
|
||||||
|
JsonValueKind.String => element.GetString() ?? string.Empty,
|
||||||
|
JsonValueKind.Number => element.TryGetInt64(out var longValue) ? longValue : element.GetDouble(),
|
||||||
|
JsonValueKind.True => true,
|
||||||
|
JsonValueKind.False => false,
|
||||||
|
JsonValueKind.Null => null!,
|
||||||
|
JsonValueKind.Object => ConvertToDictionary(element) ?? new Dictionary<string, object>(),
|
||||||
|
JsonValueKind.Array => element.EnumerateArray().Select(ConvertJsonElementToObject).ToList(),
|
||||||
|
_ => element.ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private Instant? ParseInstant(object? value)
|
private Instant? ParseInstant(object? value)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user