&& ok "pfuser follows the PrivaPub community (Accept arrived)"|| ko "PieFed's community follow not accepted ($(pf GET "community?id=$dogs_on_pf"| j "print(d[\"community_view\"][\"subscribed\"])"))"
pies_on_pf=$(pf POST community "{\"name\":\"$pies\",\"title\":\"Pasture pies\",\"description\":\"pies of the pasture\"}"| j "print(d['community_view']['community']['id'])")
&& ok "alice follows the PieFed community (Accept arrived)"|| ko "PrivaPub's community follow not accepted"
echo" threads"
pf_thread=$(pf POST post "{\"title\":\"A PieFed thread\",\"body\":\"posted from PieFed into PrivaPub\",\"community_id\":$dogs_on_pf}"| j "print(d['post_view']['post']['ap_id'])")
until_true 45'[ "$(curl -s -H "$PH" "$P/api/v1/accounts/$dogs_on_p/statuses" | j "print(any(s[\"uri\"]==\"$pf_thread\" and (s.get(\"privapub\") or {}).get(\"title\")==\"A PieFed thread\" for s in d))")" = "True" ]'\
&& ok "a PieFed thread in the PrivaPub community arrives with its title"|| ko "PieFed's thread missing or untitled on PrivaPub"
-d "{\"avatarId\":\"$alice_id\",\"title\":\"A PrivaPub community thread $run\",\"text\":\"posted into our own community for PieFed\",\"groupId\":\"$dogs_gid\"}"
dogs_post=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval 'print(db.Post.findOne({Text:/posted into our own community for PieFed/}, {}, {sort:{_id:-1}}).ObjectURI)')
until_true 45'[ "$(pf_post_by_ap "$dogs_on_pf" "$dogs_post" | j "print(d and d[\"title\"])")" = "A PrivaPub community thread $run" ]'\
&& ok "a titled post in the PrivaPub community reaches PieFed through its announce"|| ko "PrivaPub community post missing on PieFed"
pf_pies_thread=$(pf POST post "{\"title\":\"Pies only $run\",\"body\":\"a PieFed community post\",\"community_id\":$pies_on_pf}"| j "print(d['post_view']['post']['ap_id'])")
p_home_has(){ curl -s -H "$PH""$P/api/v1/timelines/home?limit=40"| j "print(next(((s.get('reblog') or s)['id'] for s in d if (s.get('reblog') or s)['uri']=='$1'), ''))";}
until_true 45'[ "$(pf_post_by_ap "$pies_on_pf" "$p_thread_uri")" != "null" ]'&& ok "alice's thread lands in the PieFed community"|| ko "PrivaPub thread missing from the PieFed community"
pf POST comment "{\"post_id\":$p_thread_on_pf,\"body\":\"a PieFed comment on PrivaPub\"}" >/dev/null
until_true 45'[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$p_thread_id/context" | j "print(any(\"a PieFed comment on PrivaPub\" in s[\"content\"] for s in d[\"descendants\"]))")" = "True" ]'\
&& ok "PieFed's comment threads under alice's post"|| ko "PieFed's comment missing on PrivaPub"
curl -s -o /dev/null -X POST -H "$PH"$P/api/v1/statuses -d "status=a PrivaPub comment on PieFed&in_reply_to_id=$pies_thread_on_p&visibility=public"
pies_thread_id=$(pf GET "resolve_object?q=$pf_pies_thread"| j "print(d['post']['post']['id'])")
until_true 45'[ "$(pf_comments "$pies_thread_id" | j "print(any(\"a PrivaPub comment on PieFed\" in c[\"body\"] for c in d))")" = "True" ]'\
&& ok "alice's reply becomes a comment on PieFed"|| ko "PrivaPub reply missing as a PieFed comment"
echo" votes"
pf POST post/like "{\"post_id\":$p_thread_on_pf,\"score\":1}" >/dev/null
&& ok "PieFed's upvote counts as a like on PrivaPub"|| ko "PieFed's upvote not counted"
pf POST post/like "{\"post_id\":$p_thread_on_pf,\"score\":-1}" >/dev/null
until_true 45'[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$p_thread_id" | j "print(d[\"favourites_count\"], ((d.get(\"privapub\") or {}).get(\"votes\") or {}).get(\"down\"))")" = "0 1" ]'\
&& ok "PieFed's change to a downvote reaches PrivaPub"|| ko "PieFed's change to a downvote not applied ($(curl -s -H "$PH""$P/api/v1/statuses/$p_thread_id"| j "print(d[\"favourites_count\"], (d.get(\"privapub\") or {}).get(\"votes\"))"))"
curl -s -o /dev/null -X POST -H "$PH""$P/api/v1/statuses/$pies_thread_on_p/favourite"
&& ok "alice's like is an upvote on PieFed"|| ko "like not counted as an upvote on PieFed ($(pf GET "post?id=$pies_thread_id"| j "print(d[\"post_view\"][\"counts\"])"))"
pf_poll=$(pf POST post "{\"title\":\"Which pie $run\",\"body\":\"vote for one\",\"community_id\":$pies_on_pf,\"poll\":{\"mode\":\"single\",\"end_poll\":\"$ends\",\"choices\":[{\"id\":1,\"choice_text\":\"apple\",\"sort_order\":0},{\"id\":2,\"choice_text\":\"cherry\",\"sort_order\":1}]}}")
until_true 45'[ -n "$(p_home_has "$pf_poll_uri")" ]'&& ok "a PieFed poll reaches alice's home"|| ko "the PieFed poll never arrived ($(echo"$pf_poll"| cut -c1-200))"
["$(echo"$poll"| j "print([o['title'] for o in d['options']])")"="['apple', 'cherry']"]&& ok "as a poll with its choices"|| ko "the PieFed poll is no poll on PrivaPub ($poll)"
until_true 60'[ "$(pf GET "post?id=$pf_poll_id" | j "print(sum(c.get(\"num_votes\", 0) for c in d[\"post_view\"][\"post\"][\"poll\"][\"choices\"] if c[\"choice_text\"]==\"cherry\"))")" = "1" ]'\
&& ok "alice's vote counts on PieFed"|| ko "alice's vote not counted on PieFed ($(pf GET "post?id=$pf_poll_id"| j "print(d[\"post_view\"][\"post\"].get(\"poll\"))"))"
echo" private messages"
alice_on_pf=$(pf GET "resolve_object?q=@alice_piefed@privapub.test"| j "print(d['person']['person']['id'])")
pf POST private_message "{\"content\":\"a secret from PieFed\",\"recipient_id\":$alice_on_pf}" >/dev/null
until_true 45'curl -s -H "$PH" "$P/api/v1/conversations" | grep -q "a secret from PieFed"'&& ok "PieFed's private message arrives as a DM"|| ko "PieFed's private message missing on PrivaPub"
curl -s -o /dev/null -X POST -H "$PH"$P/api/v1/statuses -d 'status=@pfuser@piefed.test a secret from PrivaPub&visibility=direct'
until_true 45'pf GET "private_message/list?limit=50" | grep -q "a secret from PrivaPub"'&& ok "alice's DM arrives as a PieFed private message"|| ko "DM missing on PieFed"
echo" moderation"
p_locked(){ curl -s -H "$PH""$P/api/v1/statuses/$pies_thread_on_p"| j "print((d.get('privapub') or {}).get('locked'))";}
pf POST post/lock "{\"post_id\":$pies_thread_id,\"locked\":true}" >/dev/null
until_true 45'[ "$(p_locked)" = "True" ]'&& ok "a moderator's lock reaches PrivaPub"|| ko "a moderator's lock did not reach PrivaPub"
# PieFed takes a report only from a person or a service, as Lemmy does (owner decision 2026-10-06): alice's report of
# pfuser's thread and comment leaves from PrivaPub's reporter, one Flag each, and never names her
pf POST comment "{\"post_id\":$pies_thread_id,\"body\":\"a PieFed comment to report $run\"}" >/dev/null
pf_comment_on_p(){ curl -s -H "$PH""$P/api/v1/statuses/$pies_thread_on_p/context"| j "print(next((s['id'] for s in d['descendants'] if 'a PieFed comment to report $run' in s['content']), ''))";}
until_true 45'[ -n "$(pf_comment_on_p)" ]'&& ok "pfuser's comment to report reaches PrivaPub"|| ko "pfuser's comment never reached PrivaPub"
&& ok "PrivaPub says alice's report was forwarded"|| ko "PrivaPub did not forward alice's report"
pf_reports(){ podman exec pasture-postgres psql -U pasture -d piefed -tAc "select count(*) from report r join \"user\" u on u.id = r.reporter_id where r.reasons = '$reason' and u.ap_profile_id = '$P_REPORTER' and r.$1";}
until_true 45'[ "$(pf_reports "suspect_post_id is not null and r.suspect_post_reply_id is null")" = "1" ]'&& ok "PieFed keeps the thread's report from PrivaPub's reporter, with alice's words"|| ko "PieFed kept no report of the thread"
until_true 45'[ "$(pf_reports "suspect_post_reply_id is not null")" = "1" ]'&& ok "PieFed keeps the comment's report from PrivaPub's reporter, with alice's words"|| ko "PieFed kept no report of the comment"
["$(podman exec pasture-postgres psql -U pasture -d piefed -tAc "select count(*) from report r join \"user\" u on u.id = r.reporter_id where u.ap_profile_id like '%alice_piefed%'")"="0"]\
&& ok "no report on PieFed names alice"|| ko "a report on PieFed names alice"
pf POST post/remove "{\"post_id\":$pies_thread_id,\"removed\":true,\"reason\":\"pasture\"}" >/dev/null
until_true 45'[ -z "$(p_home_has "$pf_pies_thread")" ]'&& ok "a moderator's removal reaches PrivaPub"|| ko "a moderator's removal did not reach PrivaPub"
echo" unfollow"
curl -s -o /dev/null -X POST -H "$PH""$P/api/v1/accounts/$pies_on_p/unfollow"
until_true 45'[ "$(podman exec pasture-postgres psql -U pasture -d piefed -tAc "select count(*) from community_member m join \"user\" u on u.id = m.user_id where u.ap_profile_id like '"'%alice_piefed%'"' and m.community_id = $pies_on_pf")" = "0" ]'\
&& ok "alice's unfollow reaches the PieFed community"|| ko "the PieFed community still counts alice"