using MongoDB.Entities; using PrivaPub.Federation.Actors; using PrivaPub.Models.Social; using PrivaPub.Models.User; using PrivaPub.StaticServices; using System.Text.Json.Nodes; using static PrivaPub.Federation.Objects.ActivityJson; namespace PrivaPub.Federation.Inbox.Handlers { public class AcceptHandler : IActivityHandler { readonly DbEntities _dbEntities; readonly ILocalActorService _localActors; public AcceptHandler(DbEntities dbEntities, ILocalActorService localActors) { _dbEntities = dbEntities; _localActors = localActors; } public virtual string Type => "Accept"; public async Task Handle(JsonNode activity, ForeignAvatar actor, CancellationToken token) { var following = await FindFollowing(activity["object"], actor, _dbEntities, _localActors, token); if (following == default) return; await Apply(following, token); } protected virtual Task Apply(Following following, CancellationToken token) => DB.Default.Update().MatchID(following.ID).Modify(f => f.State, FollowState.Accepted).ExecuteAsync(token); public static async Task FindFollowing(JsonNode follow, ForeignAvatar target, DbEntities dbEntities, ILocalActorService localActors, CancellationToken token) { if (follow is JsonObject && Value(follow, "type") is { } type && type != "Follow") return default; var followId = Id(follow); var byId = followId == default ? default : await dbEntities.Followings.Match(f => f.FollowActivityURI == followId && f.TargetActorURI == target.ActorURI).ExecuteFirstAsync(token); if (byId != default || follow is not JsonObject) return byId; var follower = await localActors.FindByUri(Id(follow["actor"]), token); return follower == default ? default : await dbEntities.Followings.Match(f => f.AvatarId == follower.Id && f.TargetActorURI == target.ActorURI).ExecuteFirstAsync(token); } } public class RejectHandler : AcceptHandler { public RejectHandler(DbEntities dbEntities, ILocalActorService localActors) : base(dbEntities, localActors) { } public override string Type => "Reject"; protected override Task Apply(Following following, CancellationToken token) => DB.Default.DeleteAsync(following.ID); } }