Pins across servers, both ways

An account elsewhere that pins or unpins one of its posts (Add or Remove on its `featured`) now shows those pins on its
profile here (`pinned=true`), in its order and its public posts only; a community's announce of a moderator's Add does
the same for the community. The `featured` collection itself is read with the account's counts, at most once a day, so
pins made before PrivaPub ever saw an account show too. Any other target (Smithereen's wall, a community's moderators)
is dropped. A persona's pin and unpin go to the post's audience as Add and Remove on /trophies, as Mastodon sends them.

Checked live against Mastodon (scenarios/pins.sh, 8 checks). The town's checker learnt three peer rules from the
village: Misskey and Sharkey keep a forwarded reply only with its author's LD signature (only Mastodon signs), they
count no renote by a bot, and Mastodon never sees a Lemmy vote on a post in a community. The village of 2026-10-05
checks clean, 2454 of 2454.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-05 22:48:57 +02:00
1 parent 5f150b7a59
commit 1c7d1ece9c
23 files changed
+510 -19

No files matched your search

+19 -7
View File
@@ -37,10 +37,17 @@ NEEDS_PICTURE = {"pixelfed"}
# others there (nobody relays a followers-only reply), nor anything under it
THREAD_BOUND = {"friendica"}
# Mastodon takes an activity another server passes on only with its author's LD signature (or a FEP-8b32 proof) and
# drops it otherwise (ActivityPub::ProcessActivityService); of the platforms here only Mastodon and Misskey and its forks
# sign their Creates that way, so another's reply PrivaPub passes on never lands there
NEEDS_LD_SIGNATURE = {"mastodon"}
LD_SIGNS = {"mastodon", "misskey", "sharkey"}
# drops it otherwise (ActivityPub::ProcessActivityService); Misskey and Sharkey skip it the same way ("http-signature
# verification failed and no LD-Signature"). Of the platforms here only Mastodon signs its Creates that way: Misskey
# 2026.10's carry no signature (seen in the village of 2026-10-05), so another's reply PrivaPub passes on lands there
# only when Mastodon wrote it
NEEDS_LD_SIGNATURE = {"mastodon", "misskey", "sharkey"}
LD_SIGNS = {"mastodon"}
# Misskey and Sharkey count no renote by a bot (NoteCreateService: `!user.isBot` before incRenoteCount)
BOT_RENOTES_UNCOUNTED = {"misskey", "sharkey"}
# a Lemmy account's vote goes to the community alone, which announces it; Mastodon takes no Announce of a Like, so a
# Lemmy vote on a Mastodon post in a community never counts there
GROUP_VOTES_UNSEEN = {"mastodon"}
class World:
@@ -256,6 +263,7 @@ class Sweep:
# -- counts on the object's own server, and PrivaPub's exact counts
def counts(self, stored):
likes, reacts, boosts, votes = defaultdict(int), defaultdict(lambda: defaultdict(int)), defaultdict(int), defaultdict(lambda: defaultdict(int))
bot_boosts = defaultdict(int)
for f in self.w.interactions:
ref = f["ref"]
if f["verb"] == "like":
@@ -269,6 +277,8 @@ class Sweep:
reacts[ref]["❤️" if f["emoji"] in HEARTS else f["emoji"]] += 1
elif f["verb"] == "boost":
boosts[ref] += 1
if self.w.planner.accounts[f["actor"]]["bot"]:
bot_boosts[ref] += 1
elif f["verb"] == "vote":
for c in f["choices"]:
votes[ref][c] += 1
@@ -293,12 +303,14 @@ class Sweep:
self.add(f"count.vote.{v}", "privapub", "privapub", row.votes == want, ref, want, row.votes)
elif origin != "lemmy":
# elsewhere: at least the plain likes that every platform sends as Like
plain = sum(1 for f in self.w.interactions if f["ref"] == ref and f["verb"] == "like")
plain = sum(1 for f in self.w.interactions if f["ref"] == ref and f["verb"] == "like"
and not (origin in GROUP_VOTES_UNSEEN and o.get("group") and self.w.platform(f["actor"]) == "lemmy"))
if plain:
total = (row.likes or 0)
self.add(f"count.like.{v}", "*", origin, total >= plain, ref, f">={plain}", total)
if boosts[ref]:
self.add(f"count.boost.{v}", "*", origin, (row.boosts or 0) >= boosts[ref], ref, f">={boosts[ref]}", row.boosts)
counted = boosts[ref] - (bot_boosts[ref] if origin in BOT_RENOTES_UNCOUNTED else 0)
if counted:
self.add(f"count.boost.{v}", "*", origin, (row.boosts or 0) >= counted, ref, f">={counted}", row.boosts)
if votes[ref]:
want = sum(votes[ref].values())
got = sum(row.votes or [])