♻️ Update handling logic of activitypub
This commit is contained in:
@@ -107,7 +107,6 @@ public class SnPost : ModelBase, IIdentifiedResource, ITimelineEvent
|
|||||||
public List<ContentMention>? Mentions { get; set; }
|
public List<ContentMention>? Mentions { get; set; }
|
||||||
|
|
||||||
public int BoostCount { get; set; }
|
public int BoostCount { get; set; }
|
||||||
public int LikeCount { get; set; }
|
|
||||||
|
|
||||||
public Guid? ActorId { get; set; }
|
public Guid? ActorId { get; set; }
|
||||||
public SnFediverseActor? Actor { get; set; }
|
public SnFediverseActor? Actor { get; set; }
|
||||||
@@ -232,7 +231,6 @@ public class SnPost : ModelBase, IIdentifiedResource, ITimelineEvent
|
|||||||
|
|
||||||
proto.RepliesCount = RepliesCount;
|
proto.RepliesCount = RepliesCount;
|
||||||
proto.BoostCount = BoostCount;
|
proto.BoostCount = BoostCount;
|
||||||
proto.LikeCount = LikeCount;
|
|
||||||
|
|
||||||
if (ActorId.HasValue)
|
if (ActorId.HasValue)
|
||||||
proto.ActorId = ActorId.Value.ToString();
|
proto.ActorId = ActorId.Value.ToString();
|
||||||
@@ -349,7 +347,6 @@ public class SnPost : ModelBase, IIdentifiedResource, ITimelineEvent
|
|||||||
|
|
||||||
post.RepliesCount = proto.RepliesCount;
|
post.RepliesCount = proto.RepliesCount;
|
||||||
post.BoostCount = proto.BoostCount;
|
post.BoostCount = proto.BoostCount;
|
||||||
post.LikeCount = proto.LikeCount;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(proto.ActorId))
|
if (!string.IsNullOrEmpty(proto.ActorId))
|
||||||
post.ActorId = Guid.Parse(proto.ActorId);
|
post.ActorId = Guid.Parse(proto.ActorId);
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ message Post {
|
|||||||
optional PostContentType content_type = 44;
|
optional PostContentType content_type = 44;
|
||||||
repeated ContentMention mentions = 48;
|
repeated ContentMention mentions = 48;
|
||||||
int32 boost_count = 50;
|
int32 boost_count = 50;
|
||||||
int32 like_count = 51;
|
|
||||||
optional string actor_id = 53;
|
optional string actor_id = 53;
|
||||||
|
|
||||||
repeated PostAward awards = 33;
|
repeated PostAward awards = 33;
|
||||||
|
|||||||
@@ -16,9 +16,32 @@ public class ActivityPubActivityHandler(
|
|||||||
ActivityPubSignatureService signatureService,
|
ActivityPubSignatureService signatureService,
|
||||||
ActivityPubDeliveryService deliveryService,
|
ActivityPubDeliveryService deliveryService,
|
||||||
ActivityPubDiscoveryService discoveryService,
|
ActivityPubDiscoveryService discoveryService,
|
||||||
ILogger<ActivityPubActivityHandler> logger
|
ILogger<ActivityPubActivityHandler> logger,
|
||||||
|
IConfiguration configuration
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
private string Domain => configuration["ActivityPub:Domain"] ?? "localhost";
|
||||||
|
|
||||||
|
private async Task<SnPost?> GetPostByUriAsync(string objectUri)
|
||||||
|
{
|
||||||
|
var uri = new Uri(objectUri);
|
||||||
|
var domain = uri.Host;
|
||||||
|
|
||||||
|
// Remote post
|
||||||
|
if (domain != Domain) return await db.Posts.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
|
||||||
|
|
||||||
|
// Local post, extract ID from path like /posts/{guid}
|
||||||
|
var path = uri.AbsolutePath.Trim('/');
|
||||||
|
var segments = path.Split('/');
|
||||||
|
if (segments is not [.., "posts", _]) return null;
|
||||||
|
var idStr = segments[^1];
|
||||||
|
if (Guid.TryParse(idStr, out var id))
|
||||||
|
{
|
||||||
|
return await db.Posts.FirstOrDefaultAsync(p => p.Id == id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> HandleIncomingActivityAsync(
|
public async Task<bool> HandleIncomingActivityAsync(
|
||||||
HttpContext context,
|
HttpContext context,
|
||||||
string username,
|
string username,
|
||||||
@@ -237,8 +260,8 @@ public class ActivityPubActivityHandler(
|
|||||||
return objectType switch
|
return objectType switch
|
||||||
{
|
{
|
||||||
"Follow" => await UndoFollowAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
"Follow" => await UndoFollowAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
||||||
"Like" => await UndoLikeAsync(actorUri, objectDict.GetValueOrDefault("id")?.ToString()),
|
"Like" => await UndoLikeAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
||||||
"Announce" => await UndoAnnounceAsync(actorUri, objectDict.GetValueOrDefault("id")?.ToString()),
|
"Announce" => await UndoAnnounceAsync(actorUri, objectDict.GetValueOrDefault("object")?.ToString()),
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -287,8 +310,6 @@ public class ActivityPubActivityHandler(
|
|||||||
Attachments = ParseAttachments(objectDict.GetValueOrDefault("attachment")) ?? [],
|
Attachments = ParseAttachments(objectDict.GetValueOrDefault("attachment")) ?? [],
|
||||||
Type = objectType == "Article" ? PostType.Article : PostType.Moment,
|
Type = objectType == "Article" ? PostType.Article : PostType.Moment,
|
||||||
Visibility = PostVisibility.Public,
|
Visibility = PostVisibility.Public,
|
||||||
CreatedAt = SystemClock.Instance.GetCurrentInstant(),
|
|
||||||
UpdatedAt = SystemClock.Instance.GetCurrentInstant(),
|
|
||||||
Metadata = BuildMetadataFromActivity(objectDict)
|
Metadata = BuildMetadataFromActivity(objectDict)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,8 +327,7 @@ public class ActivityPubActivityHandler(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actor = await GetOrCreateActorAsync(actorUri);
|
var actor = await GetOrCreateActorAsync(actorUri);
|
||||||
var content = await db.Posts
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
|
|
||||||
|
|
||||||
if (content == null)
|
if (content == null)
|
||||||
{
|
{
|
||||||
@@ -319,7 +339,7 @@ public class ActivityPubActivityHandler(
|
|||||||
.FirstOrDefaultAsync(r =>
|
.FirstOrDefaultAsync(r =>
|
||||||
r.ActorId == actor.Id &&
|
r.ActorId == actor.Id &&
|
||||||
r.PostId == content.Id &&
|
r.PostId == content.Id &&
|
||||||
r.Symbol == "❤️");
|
r.Symbol == "thumb_up");
|
||||||
|
|
||||||
if (existingReaction != null)
|
if (existingReaction != null)
|
||||||
{
|
{
|
||||||
@@ -330,7 +350,7 @@ public class ActivityPubActivityHandler(
|
|||||||
var reaction = new SnPostReaction
|
var reaction = new SnPostReaction
|
||||||
{
|
{
|
||||||
FediverseUri = activity.GetValueOrDefault("id")?.ToString() ?? Guid.NewGuid().ToString(),
|
FediverseUri = activity.GetValueOrDefault("id")?.ToString() ?? Guid.NewGuid().ToString(),
|
||||||
Symbol = "❤️",
|
Symbol = "thumb_up",
|
||||||
Attitude = PostReactionAttitude.Positive,
|
Attitude = PostReactionAttitude.Positive,
|
||||||
IsLocal = false,
|
IsLocal = false,
|
||||||
PostId = content.Id,
|
PostId = content.Id,
|
||||||
@@ -341,7 +361,7 @@ public class ActivityPubActivityHandler(
|
|||||||
};
|
};
|
||||||
|
|
||||||
db.PostReactions.Add(reaction);
|
db.PostReactions.Add(reaction);
|
||||||
content.LikeCount++;
|
content.Upvotes++;
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
@@ -356,8 +376,7 @@ public class ActivityPubActivityHandler(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actor = await GetOrCreateActorAsync(actorUri);
|
var actor = await GetOrCreateActorAsync(actorUri);
|
||||||
var content = await db.Posts
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
|
|
||||||
|
|
||||||
if (content != null)
|
if (content != null)
|
||||||
{
|
{
|
||||||
@@ -375,15 +394,12 @@ public class ActivityPubActivityHandler(
|
|||||||
if (string.IsNullOrEmpty(objectUri))
|
if (string.IsNullOrEmpty(objectUri))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var content = await db.Posts
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
|
|
||||||
|
|
||||||
if (content != null)
|
if (content == null) return true;
|
||||||
{
|
|
||||||
content.DeletedAt = SystemClock.Instance.GetCurrentInstant();
|
content.DeletedAt = SystemClock.Instance.GetCurrentInstant();
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
logger.LogInformation("Deleted federated content: {Uri}", objectUri);
|
logger.LogInformation("Deleted federated content: {Uri}", objectUri);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -394,8 +410,7 @@ public class ActivityPubActivityHandler(
|
|||||||
if (string.IsNullOrEmpty(objectUri))
|
if (string.IsNullOrEmpty(objectUri))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var content = await db.Posts
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
.FirstOrDefaultAsync(c => c.FediverseUri == objectUri);
|
|
||||||
|
|
||||||
if (content != null)
|
if (content != null)
|
||||||
{
|
{
|
||||||
@@ -430,32 +445,39 @@ public class ActivityPubActivityHandler(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UndoLikeAsync(string actorUri, string? activityId)
|
private async Task<bool> UndoLikeAsync(string actorUri, string? objectUri)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(objectUri))
|
||||||
|
return false;
|
||||||
|
|
||||||
var actor = await GetOrCreateActorAsync(actorUri);
|
var actor = await GetOrCreateActorAsync(actorUri);
|
||||||
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
|
|
||||||
var reactions = await db.PostReactions
|
if (content == null)
|
||||||
.Where(r => r.ActorId == actor.Id && r.Symbol == "❤️")
|
return false;
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
foreach (var reaction in reactions)
|
var reaction = await db.PostReactions
|
||||||
|
.FirstOrDefaultAsync(r =>
|
||||||
|
r.ActorId == actor.Id &&
|
||||||
|
r.PostId == content.Id &&
|
||||||
|
r.Symbol == "thumb_up");
|
||||||
|
|
||||||
|
if (reaction != null)
|
||||||
{
|
{
|
||||||
var content = await db.Posts.FindAsync(reaction.PostId);
|
|
||||||
if (content != null)
|
|
||||||
{
|
|
||||||
content.LikeCount--;
|
|
||||||
}
|
|
||||||
db.PostReactions.Remove(reaction);
|
db.PostReactions.Remove(reaction);
|
||||||
|
content.Upvotes--;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UndoAnnounceAsync(string actorUri, string? activityId)
|
private async Task<bool> UndoAnnounceAsync(string actorUri, string? objectUri)
|
||||||
{
|
{
|
||||||
var content = await db.Posts
|
if (string.IsNullOrEmpty(objectUri))
|
||||||
.FirstOrDefaultAsync(c => c.FediverseUri == activityId);
|
return false;
|
||||||
|
|
||||||
|
var content = await GetPostByUriAsync(objectUri);
|
||||||
|
|
||||||
if (content != null)
|
if (content != null)
|
||||||
{
|
{
|
||||||
|
|||||||
2373
DysonNetwork.Sphere/Migrations/20251231143021_RemoveSeprateLikeCountOnPost.Designer.cs
generated
Normal file
2373
DysonNetwork.Sphere/Migrations/20251231143021_RemoveSeprateLikeCountOnPost.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class RemoveSeprateLikeCountOnPost : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "like_count",
|
||||||
|
table: "posts");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "like_count",
|
||||||
|
table: "posts",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -840,10 +840,6 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("character varying(2048)")
|
.HasColumnType("character varying(2048)")
|
||||||
.HasColumnName("language");
|
.HasColumnName("language");
|
||||||
|
|
||||||
b.Property<int>("LikeCount")
|
|
||||||
.HasColumnType("integer")
|
|
||||||
.HasColumnName("like_count");
|
|
||||||
|
|
||||||
b.Property<List<ContentMention>>("Mentions")
|
b.Property<List<ContentMention>>("Mentions")
|
||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("mentions");
|
.HasColumnName("mentions");
|
||||||
|
|||||||
Reference in New Issue
Block a user