💄 Improvments in the activitypub
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 () =>
|
||||||
|
|||||||
Reference in New Issue
Block a user