PieFed 1.7.17 (dockurr's image of the release) runs in the pasture with its Celery worker on the shared Postgres and Redis, and scenarios/piefed.sh checks it both ways: 29 checks, communities, titled threads, comments, votes up and down, a community poll and a vote in it, private messages, a moderator's lock, unlock and removal, the unfollow and statistics. What it showed: - PieFed sends a community's announces to the inbox of the Application at a peer's root (as Lemmy serves its site actor) and to /inbox otherwise. PrivaPub answered 404 at its root, so every announce went to an /inbox it does not have. The instance actor now answers at / for ActivityPub requests, unsigned under SecureMode as at its own address. - PieFed keeps serving a thread its moderator removed, so the removal could never be checked against the post's origin. A community on the post's own server now speaks for it; one elsewhere still waits for the origin to say the post is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
125 lines
12 KiB
Bash
125 lines
12 KiB
Bash
# PieFed 1.7.17: the threadiverse in Flask. Communities both ways (FEP-1b12), threads with titles, comments both ways,
|
|
# votes up and down both ways, a community poll, private messages both ways, a moderator's lock and removal,
|
|
# statistics. PieFed is driven through its Lemmy-style API (/api/alpha) as pfuser.
|
|
PF=https://piefed.test:6443
|
|
PFT=$(cat "$here/.state/piefed.token" 2>/dev/null)
|
|
# pf <method> <path> [json]: a PieFed API call as pfuser
|
|
pf() {
|
|
local method=$1 path=$2 body=${3:-}
|
|
if [ -n "$body" ]; then
|
|
site piefed.test -s -X "$method" "$PF/api/alpha/$path" -H "Authorization: Bearer $PFT" -H 'Content-Type: application/json' -d "$body"
|
|
else
|
|
site piefed.test -s -X "$method" "$PF/api/alpha/$path" -H "Authorization: Bearer $PFT"
|
|
fi
|
|
}
|
|
# the posts PieFed holds in a community, and the one whose ap_id is given
|
|
pf_posts() { pf GET "post/list?community_id=$1&sort=New&limit=50" | j "print(json.dumps([p['post'] for p in d.get('posts', [])]))"; }
|
|
pf_post_by_ap() { pf_posts "$1" | j "print(json.dumps(next((p for p in d if p['ap_id']=='$2'), None)))"; }
|
|
pf_comments() { pf GET "comment/list?post_id=$1&limit=50" | j "print(json.dumps([c['comment'] for c in d.get('comments', [])]))"; }
|
|
|
|
echo "piefed"
|
|
[ -n "$PFT" ] && ok "PieFed token for pfuser" || { ko "PieFed token"; return 1; }
|
|
PT=$(privapub_token alice_piefed)
|
|
PH="Authorization: Bearer $PT"
|
|
[ -n "$PT" ] && ok "PrivaPub token for alice_piefed" || { ko "PrivaPub token for alice_piefed"; return 1; }
|
|
jwt=$(privapub_root)
|
|
alice_id=$(curl -s -H "$PH" "$P/api/v1/accounts/verify_credentials" | j "print(d['id'])")
|
|
run=$(date +%s)
|
|
dogs="pfdogs$run"
|
|
pies="pies$run"
|
|
|
|
echo " communities"
|
|
dogs_gid=$(curl -s -X POST $P/clientapi/group/insert -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \
|
|
-d "{\"avatarId\":\"$alice_id\",\"userName\":\"$dogs\",\"name\":\"Pasture dogs\",\"description\":\"a PrivaPub community\",\"isCommunity\":true}" | j "print(d['id'])")
|
|
dogs_on_pf=$(pf GET "resolve_object?q=!$dogs@privapub.test" | j "print(d['community']['community']['id'])")
|
|
[ -n "$dogs_on_pf" ] && ok "PieFed resolves a PrivaPub community" || ko "PieFed cannot resolve the PrivaPub community"
|
|
pf POST community/follow "{\"community_id\":$dogs_on_pf,\"follow\":true}" >/dev/null
|
|
until_true 45 '[ "$(pf GET "community?id=$dogs_on_pf" | j "print(d[\"community_view\"][\"subscribed\"])")" = "Subscribed" ]' \
|
|
&& 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'])")
|
|
pies_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=@$pies@piefed.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
|
|
[ -n "$pies_on_p" ] && ok "PrivaPub resolves a PieFed community" || ko "PrivaPub cannot resolve the PieFed community"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$pies_on_p/follow"
|
|
until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$pies_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \
|
|
&& 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'])")
|
|
dogs_on_p=$(curl -s -H "$PH" "$P/api/v1/accounts/lookup?acct=$dogs" | j "print(d['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"
|
|
curl -s -o /dev/null -X POST $P/clientapi/post/insert -H 'Content-Type: application/json' -H "Authorization: Bearer $jwt" \
|
|
-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 '[ -n "$(p_home_has "$pf_pies_thread")" ]' \
|
|
&& ok "the PieFed community's announce brings its thread to alice's home" || ko "PieFed community thread missing from alice's home"
|
|
pies_thread_on_p=$(p_home_has "$pf_pies_thread")
|
|
p_thread=$(curl -s -X POST -H "$PH" $P/api/v1/statuses --data-urlencode "status=A PrivaPub thread
|
|
@$pies@piefed.test posted from PrivaPub" -d 'visibility=public')
|
|
p_thread_id=$(echo "$p_thread" | j "print(d['id'])"); p_thread_uri=$(echo "$p_thread" | j "print(d['uri'])")
|
|
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"
|
|
p_thread_on_pf=$(pf_post_by_ap "$pies_on_pf" "$p_thread_uri" | j "print(d['id'])")
|
|
|
|
echo " comments"
|
|
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
|
|
until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$p_thread_id" | j "print(d[\"favourites_count\"])")" = "1" ]' \
|
|
&& 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"
|
|
until_true 45 '[ "$(pf GET "post?id=$pies_thread_id" | j "print(d[\"post_view\"][\"counts\"][\"upvotes\"])")" = "2" ]' \
|
|
&& 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\"])"))"
|
|
|
|
echo " polls"
|
|
ends=$(date -u -d '+2 days' +%Y-%m-%dT%H:%M:%S.000000Z)
|
|
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}]}}")
|
|
pf_poll_uri=$(echo "$pf_poll" | j "print(d['post_view']['post']['ap_id'])")
|
|
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))"
|
|
poll_on_p=$(p_home_has "$pf_poll_uri")
|
|
poll=$(curl -s -H "$PH" "$P/api/v1/statuses/$poll_on_p" | j "print(json.dumps(d.get('poll')))")
|
|
[ "$(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)"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/polls/$(echo "$poll" | j "print(d['id'])")/votes" -H 'Content-Type: application/json' -d '{"choices":[1]}'
|
|
pf_poll_id=$(echo "$pf_poll" | j "print(d['post_view']['post']['id'])")
|
|
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"
|
|
[ "$(curl -s -o /dev/null -w '%{http_code}' -X POST -H "$PH" $P/api/v1/statuses -d "status=too late&in_reply_to_id=$pies_thread_on_p&visibility=public")" = "422" ] \
|
|
&& ok "a reply to the locked thread is refused" || ko "a reply to the locked thread was taken"
|
|
pf POST post/lock "{\"post_id\":$pies_thread_id,\"locked\":false}" >/dev/null
|
|
until_true 45 '[ "$(p_locked)" = "False" ]' && ok "a moderator's unlock reaches PrivaPub" || ko "a moderator's unlock did not reach PrivaPub"
|
|
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"
|
|
|
|
echo " statistics"
|
|
stats_check piefed.test piefed
|