💄 Improvments in the activitypub

This commit is contained in:
2026-01-02 13:56:37 +08:00
parent 24b1f24dea
commit 306934304e
5 changed files with 75 additions and 24 deletions

View File

@@ -26,7 +26,7 @@ public class ActivityPubActivityHandler(
{ {
if (!Uri.TryCreate(objectUri, UriKind.Absolute, out var uri)) if (!Uri.TryCreate(objectUri, UriKind.Absolute, out var uri))
return await db.Posts.FirstOrDefaultAsync(c => c.FediverseUri == objectUri); return await db.Posts.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
var domain = uri.Host; var domain = uri.Host;
// Remote post // Remote post
@@ -320,6 +320,37 @@ public class ActivityPubActivityHandler(
Visibility = PostVisibility.Public, Visibility = PostVisibility.Public,
Metadata = BuildMetadataFromActivity(objectDict) Metadata = BuildMetadataFromActivity(objectDict)
}; };
var inReplyTo = GetStringValue(objectDict, "inReplyTo");
if (!string.IsNullOrEmpty(inReplyTo))
{
var replyingTo = await db.Posts
.Where(c => c.FediverseUri == inReplyTo)
.FirstOrDefaultAsync();
if (replyingTo == null)
{
logger.LogWarning("Incoming post replied to {Uri}, but that post was not found in our database, skipping...", inReplyTo);
return true;
}
content.RepliedPostId = replyingTo.Id;
}
var quoteUri = GetStringValue(objectDict, "quoteUri");
if (!string.IsNullOrEmpty(quoteUri))
{
var forwardedItem = await db.Posts
.FirstOrDefaultAsync(c => c.FediverseUri == quoteUri);
if (forwardedItem == null)
{
logger.LogWarning("Incoming post quoted {Uri}, but the post not found in our database...", quoteUri);
content.ForwardedGone = true;
}
else
{
content.ForwardedPostId = forwardedItem.Id;
}
}
db.Posts.Add(content); db.Posts.Add(content);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
@@ -422,7 +453,7 @@ public class ActivityPubActivityHandler(
var objectUri = GetStringValue(objectDict, "id"); var objectUri = GetStringValue(objectDict, "id");
if (string.IsNullOrEmpty(objectUri)) if (string.IsNullOrEmpty(objectUri))
return false; return false;
var actor = await GetOrCreateActorAsync(actorUri); var actor = await GetOrCreateActorAsync(actorUri);
var content = await GetPostByUriAsync(objectUri); var content = await GetPostByUriAsync(objectUri);
@@ -730,9 +761,7 @@ public class ActivityPubActivityHandler(
.ToList(); .ToList();
if (fediverseTags.Count > 0) if (fediverseTags.Count > 0)
{ metadata["fediverse_tags"] = fediverseTags;
metadata["fediverseTags"] = fediverseTags;
}
} }
var emojiValue = objectDict.GetValueOrDefault("emoji"); var emojiValue = objectDict.GetValueOrDefault("emoji");
@@ -749,10 +778,14 @@ public class ActivityPubActivityHandler(
if (emojis.Count > 0) if (emojis.Count > 0)
{ {
metadata["fediverseEmojis"] = emojis; metadata["fediverse_emojis"] = emojis;
} }
} }
var fediverseUrl = objectDict.GetValueOrDefault("url");
if (fediverseUrl is not null)
metadata["fediverse_url"] = fediverseUrl.ToString()!;
return metadata; return metadata;
} }
} }

View File

@@ -158,9 +158,9 @@ public class ActivityPubController(
.Take(pageSize) .Take(pageSize)
.ToListAsync(); .ToListAsync();
var items = posts.Select(post => var items = Task.WhenAll(posts.Select(async post =>
{ {
var postObject = objFactory.CreatePostObject(post, actorUrl); var postObject = await objFactory.CreatePostObject(post, actorUrl);
postObject["url"] = $"https://{Domain}/posts/{post.Id}"; postObject["url"] = $"https://{Domain}/posts/{post.Id}";
return new Dictionary<string, object> return new Dictionary<string, object>
{ {
@@ -172,7 +172,7 @@ public class ActivityPubController(
["cc"] = new[] { $"{actorUrl}/followers" }, ["cc"] = new[] { $"{actorUrl}/followers" },
["@object"] = postObject ["@object"] = postObject
}; };
}).Cast<object>().ToList(); })).Result.Cast<object>().ToList();
var collectionPage = new ActivityPubCollectionPage var collectionPage = new ActivityPubCollectionPage
{ {

View File

@@ -169,7 +169,7 @@ public class ActivityPubDeliveryService(
["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(), ["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(),
["to"] = new[] { ActivityPubObjectFactory.PublicTo }, ["to"] = new[] { ActivityPubObjectFactory.PublicTo },
["cc"] = new[] { $"{actorUrl}/followers" }, ["cc"] = new[] { $"{actorUrl}/followers" },
["object"] = objFactory.CreatePostObject(post, actorUrl) ["object"] = await objFactory.CreatePostObject(post, actorUrl)
}; };
var followers = await GetRemoteFollowersAsync(); var followers = await GetRemoteFollowersAsync();
@@ -205,7 +205,7 @@ public class ActivityPubDeliveryService(
["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(), ["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(),
["to"] = new[] { ActivityPubObjectFactory.PublicTo }, ["to"] = new[] { ActivityPubObjectFactory.PublicTo },
["cc"] = new[] { $"{actorUrl}/followers" }, ["cc"] = new[] { $"{actorUrl}/followers" },
["object"] = objFactory.CreatePostObject(post, actorUrl) ["object"] = await objFactory.CreatePostObject(post, actorUrl)
}; };
var followers = await GetRemoteFollowersAsync(); var followers = await GetRemoteFollowersAsync();

View File

@@ -16,7 +16,7 @@ public class ActivityPubObjectFactory(IConfiguration configuration, AppDatabase
.FirstOrDefaultAsync(a => a.PublisherId == publisherId); .FirstOrDefaultAsync(a => a.PublisherId == publisherId);
} }
public Dictionary<string, object> CreatePostObject( public async Task<Dictionary<string, object>> CreatePostObject(
SnPost post, SnPost post,
string actorUrl string actorUrl
) )
@@ -51,21 +51,28 @@ public class ActivityPubObjectFactory(IConfiguration configuration, AppDatabase
var finalContent = contentBuilder.ToString(); var finalContent = contentBuilder.ToString();
var postReceivers = new List<string> { PublicTo }; var postReceivers = new List<string> { $"{actorUrl}/followers" };
if (post.RepliedPost != null) if (post.RepliedPostId != null)
{ {
var repliedPost = await db.Posts
.Where(p => p.Id == post.RepliedPostId)
.Include(p => p.Publisher)
.Include(p => p.Actor)
.FirstOrDefaultAsync();
post.RepliedPost = repliedPost;
// Local post // Local post
if (post.RepliedPost.Publisher != null) if (repliedPost?.Publisher != null)
{ {
var actor = GetLocalActorAsync(post.RepliedPost.PublisherId!.Value).GetAwaiter().GetResult(); var actor = await GetLocalActorAsync(repliedPost.PublisherId!.Value);
if (actor?.FollowersUri != null) if (actor?.FollowersUri != null)
postReceivers.Add(actor.FollowersUri); postReceivers.Add(actor.FollowersUri);
} }
// Fediverse post // Fediverse post
if (post.Actor?.FollowersUri != null) if (repliedPost?.Actor?.FollowersUri != null)
postReceivers.Add(post.Actor.FollowersUri); postReceivers.Add(post.Actor!.FollowersUri!);
} }
var postObject = new Dictionary<string, object> var postObject = new Dictionary<string, object>
@@ -75,8 +82,8 @@ public class ActivityPubObjectFactory(IConfiguration configuration, AppDatabase
["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(), ["published"] = (post.PublishedAt ?? post.CreatedAt).ToDateTimeOffset(),
["attributedTo"] = actorUrl, ["attributedTo"] = actorUrl,
["content"] = Markdown.ToHtml(finalContent), ["content"] = Markdown.ToHtml(finalContent),
["to"] = postReceivers, ["to"] = new[] { PublicTo },
["cc"] = new[] { $"{actorUrl}/followers" }, ["cc"] = postReceivers,
["attachment"] = post.Attachments.Select(a => new Dictionary<string, object> ["attachment"] = post.Attachments.Select(a => new Dictionary<string, object>
{ {
["type"] = "Document", ["type"] = "Document",
@@ -85,6 +92,7 @@ public class ActivityPubObjectFactory(IConfiguration configuration, AppDatabase
}).ToList<object>() }).ToList<object>()
}; };
// The post's replied post is ensure loaded above, so we directly using it here
if (post.RepliedPost != null) if (post.RepliedPost != null)
{ {
// Local post // Local post
@@ -95,14 +103,19 @@ public class ActivityPubObjectFactory(IConfiguration configuration, AppDatabase
postObject["inReplyTo"] = post.RepliedPost.FediverseUri; postObject["inReplyTo"] = post.RepliedPost.FediverseUri;
} }
if (post.ForwardedPost != null) if (post.ForwardedPostId != null)
{ {
var forwardedPost = await db.Posts
.Where(p => p.Id == post.ForwardedPostId)
.Include(p => p.Publisher)
.FirstOrDefaultAsync();
// Local post // Local post
if (post.ForwardedPost.Publisher != null) if (forwardedPost?.Publisher != null)
postObject["quoteUri"] = $"https://{baseDomain}/posts/{post.RepliedPostId}"; postObject["quoteUri"] = $"https://{baseDomain}/posts/{post.RepliedPostId}";
// Fediverse post // Fediverse post
if (post.ForwardedPost.FediverseUri != null) if (forwardedPost?.FediverseUri != null)
postObject["quoteUri"] = post.ForwardedPost.FediverseUri; postObject["quoteUri"] = forwardedPost.FediverseUri;
} }
if (post.EditedAt.HasValue) if (post.EditedAt.HasValue)

View File

@@ -645,6 +645,11 @@ public partial class PostService(
}); });
} }
} }
else
{
logger.LogWarning("Seems {PublisherName} didn't enable actor, skipping delivery of Like activity...",
accountPublisher?.Name);
}
} }
_ = Task.Run(async () => _ = Task.Run(async () =>