# Lemmy 0.19.20, what most of the threadiverse runs: communities both ways (FEP-1b12), threads with titles, comments both # ways, votes up and down both ways, private messages both ways, a moderator's lock, ban and removal, statistics. Driven # through its v3 API; scenarios/lemmy.sh does the same against Lemmy 1.0. LM=https://lemmy19.test:6443 LT=$(cat "$here/.state/lemmy19.token" 2>/dev/null) # lm [json]: a Lemmy v3 API call as lemmyuser lm() { local method=$1 path=$2 body=${3:-} if [ -n "$body" ]; then site lemmy19.test -s -X "$method" "$LM/api/v3/$path" -H "Authorization: Bearer $LT" -H 'Content-Type: application/json' -d "$body" else site lemmy19.test -s -X "$method" "$LM/api/v3/$path" -H "Authorization: Bearer $LT" fi } lm_posts() { lm GET "post/list?community_id=$1&sort=New&limit=50" | j "print(json.dumps([p['post'] for p in d.get('posts', [])]))"; } lm_post_by_ap() { lm_posts "$1" | j "print(json.dumps(next((p for p in d if p['ap_id']=='$2'), None)))"; } lm_worker() { podman exec pasture-postgres psql -U pasture -d lemmy19 -tAc "select count(*) from federation_queue_state q join instance i on i.id=q.instance_id where i.domain='privapub.test'"; } echo "lemmy19" [ -n "$LT" ] && ok "Lemmy 0.19 token for lemmyuser" || { ko "Lemmy 0.19 token"; return 1; } LAT=$(privapub_token alice_lemmy19) LAH="Authorization: Bearer $LAT" [ -n "$LAT" ] && ok "PrivaPub token for alice_lemmy19" || { ko "PrivaPub token for alice_lemmy19"; return 1; } jwt=$(privapub_root) alice_id=$(curl -s -H "$LAH" "$P/api/v1/accounts/verify_credentials" | j "print(d['id'])") run=$(date +%s) dogs="ldogs$run" cats="lcats$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_lm=$(lm GET "resolve_object?q=!$dogs@privapub.test" | j "print(d['community']['community']['id'])") [ -n "$dogs_on_lm" ] && ok "Lemmy 0.19 resolves a PrivaPub community" || ko "Lemmy 0.19 cannot resolve the PrivaPub community" # (a newly seen server gets its send worker within a minute; what was queued before it starts is never sent) until_true 45 '[ "$(lm_worker)" = "1" ]' || true lm POST community/follow "{\"community_id\":$dogs_on_lm,\"follow\":true}" >/dev/null until_true 45 '[ "$(lm GET "community?id=$dogs_on_lm" | j "print(d[\"community_view\"][\"subscribed\"])")" = "Subscribed" ]' \ && ok "lemmyuser follows the PrivaPub community (Accept arrived)" || ko "Lemmy 0.19's community follow not accepted" cats_on_lm=$(lm POST community "{\"name\":\"$cats\",\"title\":\"Pasture cats\"}" | j "print(d['community_view']['community']['id'])") cats_on_p=$(curl -s -H "$LAH" "$P/api/v2/search?q=@$cats@lemmy19.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])") [ -n "$cats_on_p" ] && ok "PrivaPub resolves a Lemmy 0.19 community" || ko "PrivaPub cannot resolve the Lemmy 0.19 community" curl -s -o /dev/null -X POST -H "$LAH" "$P/api/v1/accounts/$cats_on_p/follow" until_true 45 '[ "$(curl -s -H "$LAH" "$P/api/v1/accounts/relationships?id[]=$cats_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \ && ok "alice follows the Lemmy 0.19 community (Accept arrived)" || ko "PrivaPub's community follow not accepted" echo " threads" lm_thread=$(lm POST post "{\"name\":\"A Lemmy 0.19 thread\",\"body\":\"posted from Lemmy 0.19 into PrivaPub\",\"community_id\":$dogs_on_lm}" | j "print(d['post_view']['post']['ap_id'])") dogs_on_p=$(curl -s -H "$LAH" "$P/api/v1/accounts/lookup?acct=$dogs" | j "print(d['id'])") until_true 45 '[ "$(curl -s -H "$LAH" "$P/api/v1/accounts/$dogs_on_p/statuses" | j "print(any(s[\"uri\"]==\"$lm_thread\" and (s.get(\"privapub\") or {}).get(\"title\")==\"A Lemmy 0.19 thread\" for s in d))")" = "True" ]' \ && ok "a Lemmy 0.19 thread in the PrivaPub community arrives with its title" || ko "Lemmy 0.19'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 Lemmy 0.19\",\"groupId\":\"$dogs_gid\"}" dogs_post=$(podman exec pasture-mongo mongosh --quiet PrivaPub --eval 'print(db.Post.findOne({Text:/posted into our own community for Lemmy 0.19/}, {}, {sort:{_id:-1}}).ObjectURI)') until_true 45 '[ "$(lm_post_by_ap "$dogs_on_lm" "$dogs_post" | j "print(d and d[\"name\"])")" = "A PrivaPub community thread $run" ]' \ && ok "a titled post in the PrivaPub community reaches Lemmy 0.19 through its announce" || ko "PrivaPub community post missing on Lemmy 0.19" lm_cats_thread=$(lm POST post "{\"name\":\"Cats only $run\",\"body\":\"a Lemmy 0.19 community post\",\"community_id\":$cats_on_lm}" | j "print(d['post_view']['post']['ap_id'])") p_home_has() { curl -s -H "$LAH" "$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 "$lm_cats_thread")" ]' && ok "the Lemmy 0.19 community's announce brings its thread to alice's home" || ko "Lemmy 0.19 community thread missing from alice's home" lm_cats_on_p=$(p_home_has "$lm_cats_thread") p_thread=$(curl -s -X POST -H "$LAH" $P/api/v1/statuses --data-urlencode "status=A PrivaPub thread @$cats@lemmy19.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 '[ "$(lm_post_by_ap "$cats_on_lm" "$p_thread_uri")" != "null" ]' && ok "alice's thread lands in the Lemmy 0.19 community" || ko "PrivaPub thread missing from the Lemmy 0.19 community" p_thread_on_lm=$(lm_post_by_ap "$cats_on_lm" "$p_thread_uri" | j "print(d['id'])") echo " comments" lm POST comment "{\"post_id\":$p_thread_on_lm,\"content\":\"a Lemmy 0.19 comment on PrivaPub\"}" >/dev/null until_true 45 '[ "$(curl -s -H "$LAH" "$P/api/v1/statuses/$p_thread_id/context" | j "print(any(\"a Lemmy 0.19 comment on PrivaPub\" in s[\"content\"] for s in d[\"descendants\"]))")" = "True" ]' \ && ok "Lemmy 0.19's comment threads under alice's post" || ko "Lemmy 0.19's comment missing on PrivaPub" curl -s -o /dev/null -X POST -H "$LAH" $P/api/v1/statuses -d "status=a PrivaPub comment on Lemmy 0.19&in_reply_to_id=$lm_cats_on_p&visibility=public" lm_cats_id=$(lm GET "resolve_object?q=$lm_cats_thread" | j "print(d['post']['post']['id'])") until_true 45 '[ "$(lm GET "comment/list?post_id=$lm_cats_id" | j "print(any(\"a PrivaPub comment on Lemmy 0.19\" in c[\"comment\"][\"content\"] for c in d.get(\"comments\", [])))")" = "True" ]' \ && ok "alice's reply becomes a comment on Lemmy 0.19" || ko "PrivaPub reply missing as a Lemmy 0.19 comment" echo " votes" lm POST post/like "{\"post_id\":$p_thread_on_lm,\"score\":1}" >/dev/null until_true 60 '[ "$(curl -s -H "$LAH" "$P/api/v1/statuses/$p_thread_id" | j "print(d[\"favourites_count\"])")" = "1" ]' \ && ok "Lemmy 0.19's upvote counts as a like on PrivaPub" || ko "Lemmy 0.19's relayed upvote not counted" lm POST post/like "{\"post_id\":$p_thread_on_lm,\"score\":-1}" >/dev/null until_true 60 '[ "$(curl -s -H "$LAH" "$P/api/v1/statuses/$p_thread_id" | j "print(d[\"favourites_count\"], ((d.get(\"privapub\") or {}).get(\"votes\") or {}).get(\"down\"))")" = "0 1" ]' \ && ok "Lemmy 0.19's change to a downvote reaches PrivaPub" || ko "Lemmy 0.19's change to a downvote not applied" curl -s -o /dev/null -X POST -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p/favourite" until_true 45 '[ "$(lm GET "post?id=$lm_cats_id" | j "print(d[\"post_view\"][\"counts\"][\"upvotes\"])")" = "2" ]' && ok "alice's like is an upvote on Lemmy 0.19" || ko "like not counted as an upvote on Lemmy 0.19" echo " private messages" alice_on_lm=$(lm GET "resolve_object?q=@alice_lemmy19@privapub.test" | j "print(d['person']['person']['id'])") lm POST private_message "{\"content\":\"a secret from Lemmy 0.19\",\"recipient_id\":$alice_on_lm}" >/dev/null until_true 45 'curl -s -H "$LAH" "$P/api/v1/conversations" | grep -q "a secret from Lemmy 0.19"' && ok "Lemmy 0.19's private message arrives as a DM" || ko "Lemmy 0.19's private message missing on PrivaPub" # (0.19 takes a private message only as a ChatMessage and answers alice's direct Note 400, G-0008; 1.0 takes a Note) curl -s -o /dev/null -X POST -H "$LAH" $P/api/v1/statuses -d 'status=@lemmyuser@lemmy19.test a secret from PrivaPub&visibility=direct' until_true 30 'lm GET "private_message/list?limit=50" | grep -q "a secret from PrivaPub"' && ok "alice's DM arrives as a Lemmy 0.19 private message" \ || xf "alice's DM never reaches Lemmy 0.19, which takes private messages only as ChatMessage (G-0008)" echo " moderation" p_locked() { curl -s -H "$LAH" "$P/api/v1/statuses/$lm_cats_on_p" | j "print((d.get('privapub') or {}).get('locked'))"; } p_reply() { curl -s -o /dev/null -w '%{http_code}' -X POST -H "$LAH" $P/api/v1/statuses -d "status=$1&in_reply_to_id=$lm_cats_on_p&visibility=public"; } p_banned() { curl -s -H "$LAH" "$P/api/v1/accounts/relationships?id[]=$cats_on_p" | j "print(d[0]['blocked_by'])"; } lm POST post/lock "{\"post_id\":$lm_cats_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" [ "$(p_reply "too late")" = "422" ] && ok "a reply to the locked thread is refused" || ko "a reply to the locked thread was taken" lm POST post/lock "{\"post_id\":$lm_cats_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" lm POST community/ban_user "{\"community_id\":$cats_on_lm,\"person_id\":$alice_on_lm,\"ban\":true,\"reason\":\"pasture\"}" >/dev/null until_true 45 '[ "$(p_banned)" = "True" ]' && ok "the community's ban of alice_lemmy19 reaches PrivaPub (blocked_by)" || ko "the community's ban did not reach PrivaPub" [ "$(p_reply "while banned")" = "422" ] && ok "a banned persona's reply in the community is refused" || ko "a banned persona's reply was taken" lm POST community/ban_user "{\"community_id\":$cats_on_lm,\"person_id\":$alice_on_lm,\"ban\":false,\"reason\":\"pasture\"}" >/dev/null until_true 45 '[ "$(p_banned)" = "False" ]' && ok "the community's unban reaches PrivaPub" || ko "the community's unban did not reach PrivaPub" lm POST post/remove "{\"post_id\":$lm_cats_id,\"removed\":true,\"reason\":\"pasture\"}" >/dev/null until_true 45 '[ -z "$(p_home_has "$lm_cats_thread")" ]' && ok "a moderator's removal reaches PrivaPub" || ko "a moderator's removal did not reach PrivaPub" echo " statistics" stats_check lemmy19.test lemmy