2026-10-05 22:48:57 +02:00
|
|
|
using PrivaPub.Federation.Actors;
|
|
|
|
|
using PrivaPub.Models.User;
|
|
|
|
|
|
|
|
|
|
using System.Text.Json.Nodes;
|
|
|
|
|
|
|
|
|
|
namespace PrivaPub.Federation.Inbox.Handlers
|
|
|
|
|
{
|
|
|
|
|
// An account pins one of its posts (Add to its `featured` collection) or unpins it (Remove), as Mastodon and Akkoma
|
2026-10-06 08:17:10 +02:00
|
|
|
// send it; inside a community's announce, the community features a post made in it. On its wall (Smithereen's, FEP-400e)
|
|
|
|
|
// it tells of a post someone wrote there, or takes it off. Any other target (a community's moderators) is not ours to
|
|
|
|
|
// keep.
|
2026-10-05 22:48:57 +02:00
|
|
|
public class FeaturedHandler : IActivityHandler
|
|
|
|
|
{
|
|
|
|
|
readonly IFeaturedPosts _featured;
|
2026-10-06 08:17:10 +02:00
|
|
|
readonly IWalls _walls;
|
|
|
|
|
readonly IRemoteActorService _remoteActors;
|
2026-10-06 10:03:44 +02:00
|
|
|
readonly Infrastructure.Jobs.IJobQueue _queue;
|
2026-10-05 22:48:57 +02:00
|
|
|
readonly bool _add;
|
|
|
|
|
|
2026-10-06 10:03:44 +02:00
|
|
|
public FeaturedHandler(IFeaturedPosts featured, bool add, IWalls walls = default, IRemoteActorService remoteActors = default,
|
|
|
|
|
Infrastructure.Jobs.IJobQueue queue = default)
|
2026-10-05 22:48:57 +02:00
|
|
|
{
|
|
|
|
|
_featured = featured;
|
2026-10-06 08:17:10 +02:00
|
|
|
_walls = walls;
|
|
|
|
|
_remoteActors = remoteActors;
|
2026-10-06 10:03:44 +02:00
|
|
|
_queue = queue;
|
2026-10-05 22:48:57 +02:00
|
|
|
_add = add;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string Type => _add ? "Add" : "Remove";
|
|
|
|
|
|
2026-10-06 08:17:10 +02:00
|
|
|
public async Task Handle(JsonNode activity, ForeignAvatar actor, CancellationToken token)
|
|
|
|
|
{
|
2026-10-06 10:03:44 +02:00
|
|
|
if (_add && _queue != default && await ConversationContainers.Unwrap(activity, actor, _queue, token))
|
|
|
|
|
return;
|
2026-10-06 08:17:10 +02:00
|
|
|
var target = Objects.ActivityJson.Id(activity["target"]);
|
|
|
|
|
// a collection of its own we do not know of: its document read again, at most hourly, in case it was kept before
|
|
|
|
|
// we read that collection (a wall)
|
|
|
|
|
if (_remoteActors != default && target != default && target != actor.FeaturedURL && target != actor.WallURL
|
|
|
|
|
&& Objects.Origin.Same(target, actor.ActorURI) && actor.UpdatedAt < DateTime.UtcNow.AddHours(-1))
|
|
|
|
|
actor = await _remoteActors.GetActor(actor.ActorURI, refresh: true, token) ?? actor;
|
|
|
|
|
if (_walls != default && !string.IsNullOrEmpty(actor.WallURL) && target == actor.WallURL)
|
|
|
|
|
await _walls.Receive(activity, actor, _add, token);
|
|
|
|
|
else
|
|
|
|
|
await _featured.Receive(activity, actor, _add, token);
|
|
|
|
|
}
|
2026-10-05 22:48:57 +02:00
|
|
|
}
|
|
|
|
|
}
|