P7: feeds read as accounts, and PieFed's post Move
Build / Build (push) Successful in 7m50s

Lemmy 1.0's multi-communities and PieFed's feeds (`type: Feed`) resolve as accounts: the feed's `following` is kept
once a day with its counts, each community in it is read in turn, and `/api/v1/accounts/:id/following` lists them.
Lemmy's feed carries the instance's key and its text in `description`; both are taken as they are. Following a feed
answers 422 until the owner decides how a feed is followed.

A post moved to another community (PieFed's Move{object: post, origin, target}), relayed by the community it leaves,
goes there with its thread; a move into a community we host is not taken.

Checked in the pasture: a Lemmy 1.0 feed and a PieFed feed list their communities (ours among them); a PieFed post moved
from its web code arrives moved, with its comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-07 21:42:54 +02:00
1 parent 62189bf11d
commit 3b3f1f6b93
10 files changed
+226 -25

No files matched your search

@@ -253,7 +253,10 @@ namespace PrivaPub.Api.Mastodon.Controllers
[HttpGet("/api/v1/accounts/{id}/following"), Scope("read:accounts", requiresUser: false), Microsoft.AspNetCore.Authorization.AllowAnonymous]
public async Task<IActionResult> Following(string id, CancellationToken token)
{
var (local, _) = await Find(id, token);
var (local, remote) = await Find(id, token);
// a feed's following is what it is: its communities, as its server lists them
if (remote is { AvatarType: AvatarType.Feed })
return Json(await AccountsFor(remote.FeedCommunities.Take(Limit(40, 80)), token));
if (local == default || local.Id != MyId)
return Json(Array.Empty<Account>());
var following = await Page.From(Params, Limit(40, 80))
@@ -269,6 +272,8 @@ namespace PrivaPub.Api.Mastodon.Controllers
var (local, remote) = await Find(id, token);
if (local == default && remote == default)
return NotFoundError();
if (remote is { AvatarType: AvatarType.Feed })
return Error(StatusCodes.Status422UnprocessableEntity, "A feed is followed through its communities");
var following = await _follows.FollowAs(Me, local?.Uri ?? remote.ActorURI, Params.Bool("reblogs") != false, token);
return following == default ? Error(StatusCodes.Status403Forbidden, "This action is not allowed") : Json(await Relationship(id, token));
}