The Mastodon scenario waits on Mastodon's database, and tells the quoted post by its id

Mastodon's relationships API keeps each pair a day, and a read racing the change awaited writes the old answer back
after the change cleared it: an unfollow that had landed showed as a follow until the block. Changes from PrivaPub are
now awaited in Mastodon's database. The post to quote was found by its words, which alice's quotes from earlier runs
hold too; it is found by its id.

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-06 12:07:49 +02:00
1 parent 679463eb3f
commit b66f0acf4e
1 file changed
+14 -7
+14 -7
View File
@@ -14,6 +14,11 @@ AH="Authorization: Bearer $AT"
# what Mastodon holds of an account, newest first; and the one status whose uri is given # what Mastodon holds of an account, newest first; and the one status whose uri is given
m_statuses() { mcurl -H "$MH" "$M/api/v1/accounts/$1/statuses?limit=40"; } m_statuses() { mcurl -H "$MH" "$M/api/v1/accounts/$1/statuses?limit=40"; }
m_status_by_uri() { m_statuses "$1" | j "print(json.dumps(next((s for s in d if s['uri']=='$2'), None)))"; } m_status_by_uri() { m_statuses "$1" | j "print(json.dumps(next((s for s in d if s['uri']=='$2'), None)))"; }
# m_rows <follows|follow_requests|blocks> <account> <target>: what Mastodon's database holds between two of its accounts.
# Its relationships API keeps each pair a day, and a read racing the change awaited writes the old answer back after the
# change cleared it (an undone follow then shows for a day), so a change from PrivaPub is awaited here
m_rows() { podman exec pasture-postgres psql -U pasture -d mastodon -Atc "select count(*) from $1 where account_id = $2 and target_account_id = $3" 2>/dev/null; }
m_me=$(mcurl -H "$MH" "$M/api/v1/accounts/verify_credentials" | j "print(d['id'])")
echo " discovery" echo " discovery"
alice_on_m=$(mcurl -H "$MH" "$M/api/v2/search?q=@alice_masto@privapub.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])") alice_on_m=$(mcurl -H "$MH" "$M/api/v2/search?q=@alice_masto@privapub.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
@@ -27,7 +32,7 @@ echo " follows"
mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/unblock" mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/unblock"
mcurl -o /dev/null -X PATCH -H "$MH" "$M/api/v1/accounts/update_credentials" -d 'locked=false' mcurl -o /dev/null -X PATCH -H "$MH" "$M/api/v1/accounts/update_credentials" -d 'locked=false'
mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/follow" mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/follow"
until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$alice_on_m" | j "print(d[0][\"following\"])")" = "True" ]' && ok "mastouser follows alice_masto (Accept arrived)" || ko "Mastodon's follow not accepted" until_true 30 '[ "$(m_rows follows $m_me $alice_on_m)" = "1" ]' && ok "mastouser follows alice_masto (Accept arrived)" || ko "Mastodon's follow not accepted"
curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/follow" curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/follow"
until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/accounts/relationships?id[]=$masto_on_p" | j "print(d[0][\"following\"])")" = "True" ]' && ok "alice_masto follows mastouser (Accept arrived)" || ko "PrivaPub's follow not accepted" until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/accounts/relationships?id[]=$masto_on_p" | j "print(d[0][\"following\"])")" = "True" ]' && ok "alice_masto follows mastouser (Accept arrived)" || ko "PrivaPub's follow not accepted"
@@ -92,8 +97,10 @@ until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/statuses/$m_poll" | j "print(d[\"p
echo " quotes" echo " quotes"
q_target=$(mcurl -X POST -H "$MH" "$M/api/v1/statuses" -d 'status=quote me if you like&visibility=public' | j "print(d['id'])") q_target=$(mcurl -X POST -H "$MH" "$M/api/v1/statuses" -d 'status=quote me if you like&visibility=public' | j "print(d['id'])")
until_true 30 'curl -s -H "$AH" "$P/api/v1/timelines/home" | grep -q "quote me if you like"' || true # (told by its id: alice's quotes from earlier runs hold its words too)
q_target_on_p=$(curl -s -H "$AH" "$P/api/v1/timelines/home" | j "print(next(s['id'] for s in d if 'quote me if you like' in s['content']))") q_on_p() { curl -s -H "$AH" "$P/api/v1/timelines/home" | j "print(next((s['id'] for s in d if s['uri'].endswith('/$q_target')), ''))"; }
until_true 30 '[ -n "$(q_on_p)" ]' || true
q_target_on_p=$(q_on_p)
a_quote=$(curl -s -X POST -H "$AH" $P/api/v1/statuses -d "status=quoting Mastodon&visibility=public&quoted_status_id=$q_target_on_p" | j "print(d['id'])") a_quote=$(curl -s -X POST -H "$AH" $P/api/v1/statuses -d "status=quoting Mastodon&visibility=public&quoted_status_id=$q_target_on_p" | j "print(d['id'])")
until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/statuses/$a_quote" | j "print((d.get(\"quote\") or {}).get(\"state\"))")" = "accepted" ]' && ok "Mastodon approves alice_masto's quote (FEP-044f)" || ko "quote of a Mastodon post not approved" until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/statuses/$a_quote" | j "print((d.get(\"quote\") or {}).get(\"state\"))")" = "accepted" ]' && ok "Mastodon approves alice_masto's quote (FEP-044f)" || ko "quote of a Mastodon post not approved"
m_quote=$(mcurl -X POST -H "$MH" "$M/api/v1/statuses" -d "status=quoting PrivaPub&visibility=public&quoted_status_id=$a_post_on_m" | j "print(d['id'])") m_quote=$(mcurl -X POST -H "$MH" "$M/api/v1/statuses" -d "status=quoting PrivaPub&visibility=public&quoted_status_id=$a_post_on_m" | j "print(d['id'])")
@@ -130,7 +137,7 @@ masto_on_p_b=$(curl -s -H "$BH" "$P/api/v2/search?q=mastouser@mastodon.test&reso
# bob_masto follows mastouser once a run has passed here: unfollow first, so the follow below is a new request # bob_masto follows mastouser once a run has passed here: unfollow first, so the follow below is a new request
curl -s -o /dev/null -X POST -H "$BH" "$P/api/v1/accounts/$masto_on_p_b/unfollow" curl -s -o /dev/null -X POST -H "$BH" "$P/api/v1/accounts/$masto_on_p_b/unfollow"
bob_on_m=$(mcurl -H "$MH" "$M/api/v2/search?q=@bob_masto@privapub.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])") bob_on_m=$(mcurl -H "$MH" "$M/api/v2/search?q=@bob_masto@privapub.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$bob_on_m" | j "print(d[0][\"followed_by\"])")" = "False" ]' || true until_true 30 '[ "$(m_rows follows $bob_on_m $m_me)" = "0" ]' || true
curl -s -o /dev/null -X POST -H "$BH" "$P/api/v1/accounts/$masto_on_p_b/follow" curl -s -o /dev/null -X POST -H "$BH" "$P/api/v1/accounts/$masto_on_p_b/follow"
until_true 30 'mcurl -H "$MH" "$M/api/v1/follow_requests" | j "print(any(a[\"acct\"]==\"bob_masto@privapub.test\" for a in d))" | grep -q True' && ok "bob_masto's follow waits as a request on locked mastouser" || ko "follow request missing on Mastodon" until_true 30 'mcurl -H "$MH" "$M/api/v1/follow_requests" | j "print(any(a[\"acct\"]==\"bob_masto@privapub.test\" for a in d))" | grep -q True' && ok "bob_masto's follow waits as a request on locked mastouser" || ko "follow request missing on Mastodon"
bob_on_m=$(mcurl -H "$MH" "$M/api/v1/follow_requests" | j "print(next(a['id'] for a in d if a['acct']=='bob_masto@privapub.test'))") bob_on_m=$(mcurl -H "$MH" "$M/api/v1/follow_requests" | j "print(next(a['id'] for a in d if a['acct']=='bob_masto@privapub.test'))")
@@ -151,7 +158,7 @@ until_true 15 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$circl
requester=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval "print(db.Follower.findOne({LocalActorId:'$circle', IsAccepted:false}).ActorURI)") requester=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval "print(db.Follower.findOne({LocalActorId:'$circle', IsAccepted:false}).ActorURI)")
curl -s -o /dev/null -X POST $P/clientapi/group/approve -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \ curl -s -o /dev/null -X POST $P/clientapi/group/approve -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \
-d "{\"avatarId\":\"$alice_id\",\"groupId\":\"$circle\",\"memberActorURI\":\"$requester\"}" -d "{\"avatarId\":\"$alice_id\",\"groupId\":\"$circle\",\"memberActorURI\":\"$requester\"}"
until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$circle_on_m" | j "print(d[0][\"following\"])")" = "True" ]' && ok "the owner's approval makes mastouser a circle member" || ko "circle approval did not reach Mastodon" until_true 30 '[ "$(m_rows follows $m_me $circle_on_m)" = "1" ]' && ok "the owner's approval makes mastouser a circle member" || ko "circle approval did not reach Mastodon"
circle_post=$(curl -s -X POST $P/clientapi/post/insert -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \ circle_post=$(curl -s -X POST $P/clientapi/post/insert -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \
-d "{\"avatarId\":\"$alice_id\",\"text\":\"only the circle sees this\",\"groupId\":\"$circle\"}") -d "{\"avatarId\":\"$alice_id\",\"text\":\"only the circle sees this\",\"groupId\":\"$circle\"}")
circle_uri=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval 'print(db.Post.findOne({Text:/only the circle sees this/},{ObjectURI:1}).ObjectURI)') circle_uri=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval 'print(db.Post.findOne({Text:/only the circle sees this/},{ObjectURI:1}).ObjectURI)')
@@ -196,9 +203,9 @@ until_true 30 'mcurl -H "$MH" "$M/api/v1/admin/reports" | grep -q "pasture-repor
echo " blocks and unfollows" echo " blocks and unfollows"
curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/unfollow" curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/unfollow"
until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$alice_on_m" | j "print(d[0][\"followed_by\"])")" = "False" ]' && ok "alice_masto's unfollow reaches Mastodon" || ko "unfollow not applied on Mastodon" until_true 30 '[ "$(m_rows follows $alice_on_m $m_me)" = "0" ]' && ok "alice_masto's unfollow reaches Mastodon" || ko "unfollow not applied on Mastodon"
curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/block" curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/block"
until_true 30 '[ "$(mcurl -H "$MH" "$M/api/v1/accounts/relationships?id[]=$alice_on_m" | j "print(d[0][\"blocked_by\"])")" = "True" ]' && ok "alice_masto's block reaches Mastodon" || ko "block not applied on Mastodon" until_true 30 '[ "$(m_rows blocks $alice_on_m $m_me)" = "1" ]' && ok "alice_masto's block reaches Mastodon" || ko "block not applied on Mastodon"
curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/unblock" curl -s -o /dev/null -X POST -H "$AH" "$P/api/v1/accounts/$masto_on_p/unblock"
mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/block" mcurl -o /dev/null -X POST -H "$MH" "$M/api/v1/accounts/$alice_on_m/block"
until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/accounts/relationships?id[]=$masto_on_p" | j "print(d[0][\"blocked_by\"])")" = "True" ]' \ until_true 30 '[ "$(curl -s -H "$AH" "$P/api/v1/accounts/relationships?id[]=$masto_on_p" | j "print(d[0][\"blocked_by\"])")" = "True" ]' \