# Mitra 5.9.1: follows both ways, posts, replies, likes, reposts, an emoji reaction, a poll, an edit and a deletion both # ways, direct messages, the unfollow, statistics. Mitra signs its deliveries with RSA and carries FEP-8b32 proofs made # with its Ed25519 key. Driven through its Mastodon API as mitrauser, with the token peers/mitra.sh got. MI=https://mitra.test:6443 MIT=$(cat "$here/.state/mitra/mitrauser.token" 2>/dev/null) mi() { site mitra.test -s -H "Authorization: Bearer $MIT" "$@"; } mi_json() { local method=$1 path=$2 body=$3; mi -X "$method" "$MI$path" -H 'Content-Type: application/json' -d "$body"; } mi_status_of() { mi "$MI/api/v1/statuses/${1:-none}"; } 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 '$1' in ((s.get('reblog') or s)['content'] or '')), ''))"; } p_status() { curl -s -H "$PH" "$P/api/v1/statuses/$1" | j "print(d.get('$2'))"; } echo "mitra" [ "$(mi "$MI/api/v1/accounts/verify_credentials" | j "print(d['username'])")" = "mitrauser" ] && ok "Mitra token for mitrauser" || { ko "Mitra token"; return 1; } PT=$(privapub_token alice_mitra) PH="Authorization: Bearer $PT" [ -n "$PT" ] && ok "PrivaPub token for alice_mitra" || { ko "PrivaPub token for alice_mitra"; return 1; } run=$(date +%s) echo " follows" # (its search resolves an account elsewhere only when it is not limited to a type) alice_on_mi=$(mi "$MI/api/v2/search?q=alice_mitra%40privapub.test&resolve=true" | j "print(d['accounts'][0]['id'])") [ -n "$alice_on_mi" ] && ok "Mitra resolves alice" || ko "Mitra cannot resolve alice" mi -o /dev/null -X POST "$MI/api/v1/accounts/$alice_on_mi/follow" until_true 45 '[ "$(mi "$MI/api/v1/accounts/relationships?id[]=$alice_on_mi" | j "print(d[0][\"following\"])")" = "True" ]' \ && ok "mitrauser follows alice (Accept arrived)" || ko "alice's Accept never reached Mitra" mi_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=mitrauser@mitra.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])") [ -n "$mi_on_p" ] && ok "PrivaPub resolves mitrauser" || ko "PrivaPub cannot resolve mitrauser" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$mi_on_p/follow" until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$mi_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \ && ok "alice follows mitrauser (Accept arrived)" || ko "Mitra's Accept never arrived" echo " posts" mi_post=$(mi_json POST /api/v1/statuses "{\"status\":\"a Mitra post $run\",\"visibility\":\"public\"}") mi_post_id=$(echo "$mi_post" | j "print(d['id'])") until_true 45 '[ -n "$(p_home_has "a Mitra post $run")" ]' && ok "mitrauser's post reaches alice's home" || ko "mitrauser's post never reached alice" mi_on_p_post=$(p_home_has "a Mitra post $run") p_post=$(curl -s -X POST -H "$PH" $P/api/v1/statuses -d "status=a PrivaPub post for Mitra $run&visibility=public") p_post_id=$(echo "$p_post" | j "print(d['id'])"); p_post_uri=$(echo "$p_post" | j "print(d['uri'])") until_true 45 '[ "$(mi "$MI/api/v1/timelines/home?limit=40" | j "print(any(s[\"uri\"] == \"$p_post_uri\" for s in d))")" = "True" ]' \ && ok "alice's post reaches mitrauser's home" || ko "alice's post never reached Mitra" p_on_mi=$(mi "$MI/api/v1/timelines/home?limit=40" | j "print(next(s['id'] for s in d if s['uri'] == '$p_post_uri'))") echo " replies" mi_json POST /api/v1/statuses "{\"status\":\"@alice_mitra@privapub.test a Mitra reply $run\",\"in_reply_to_id\":\"$p_on_mi\",\"visibility\":\"public\"}" >/dev/null until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$p_post_id/context" | j "print(any(\"a Mitra reply $run\" in s[\"content\"] for s in d[\"descendants\"]))")" = "True" ]' \ && ok "mitrauser's reply threads under alice's post" || ko "mitrauser's reply missing on PrivaPub" curl -s -o /dev/null -X POST -H "$PH" $P/api/v1/statuses -d "status=@mitrauser@mitra.test a PrivaPub reply $run&in_reply_to_id=$mi_on_p_post&visibility=public" until_true 45 '[ "$(mi "$MI/api/v1/statuses/$mi_post_id/context" | j "print(any(\"a PrivaPub reply $run\" in s[\"content\"] for s in d[\"descendants\"]))")" = "True" ]' \ && ok "alice's reply threads under mitrauser's post" || ko "alice's reply missing on Mitra" echo " likes, reposts and reactions" mi -o /dev/null -X POST "$MI/api/v1/statuses/$p_on_mi/favourite" until_true 45 '[ "$(p_status $p_post_id favourites_count)" = "1" ]' && ok "mitrauser's like counts on PrivaPub" || ko "mitrauser's like never counted" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$mi_on_p_post/favourite" until_true 45 '[ "$(mi_status_of $mi_post_id | j "print(d[\"favourites_count\"])")" = "1" ]' && ok "alice's like counts on Mitra" || ko "alice's like never counted on Mitra" mi -o /dev/null -X POST "$MI/api/v1/statuses/$p_on_mi/reblog" until_true 45 '[ "$(p_status $p_post_id reblogs_count)" = "1" ]' && ok "mitrauser's repost is a boost on PrivaPub" || ko "mitrauser's repost never counted" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$mi_on_p_post/reblog" until_true 45 '[ "$(mi_status_of $mi_post_id | j "print(d[\"reblogs_count\"])")" = "1" ]' && ok "alice's boost counts on Mitra" || ko "alice's boost never counted on Mitra" mi -o /dev/null -X PUT "$MI/api/v1/pleroma/statuses/$p_on_mi/reactions/%F0%9F%8E%89" until_true 45 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$p_post_id" | j "print(any(r[\"name\"] == \"🎉\" for r in (d.get(\"pleroma\") or {}).get(\"emoji_reactions\") or d.get(\"reactions\") or []))")" = "True" ]' \ && ok "mitrauser's reaction reaches alice's post" || ko "mitrauser's reaction never arrived ($(curl -s -H "$PH" "$P/api/v1/statuses/$p_post_id" | j "print((d.get('pleroma') or {}).get('emoji_reactions'))"))" echo " polls" mi_poll=$(mi_json POST /api/v1/statuses "{\"status\":\"a Mitra poll $run\",\"visibility\":\"public\",\"poll\":{\"options\":[\"hay\",\"clover\"],\"expires_in\":3600}}") until_true 45 '[ -n "$(p_home_has "a Mitra poll $run")" ]' && ok "mitrauser's poll reaches alice" || ko "mitrauser's poll never reached alice" p_poll=$(curl -s -H "$PH" "$P/api/v1/statuses/$(p_home_has "a Mitra poll $run")" | j "print(d['poll']['id'] if d.get('poll') else '')") curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/polls/$p_poll/votes" -d 'choices[]=1' until_true 45 '[ "$(mi_status_of $(echo "$mi_poll" | j "print(d[\"id\"])") | j "print(d[\"poll\"][\"votes_count\"])")" = "1" ]' \ && ok "alice's vote counts on Mitra" || ko "alice's vote never counted on Mitra" echo " edits and deletions" mi_json PUT "/api/v1/statuses/$mi_post_id" "{\"status\":\"a Mitra post $run, edited\"}" >/dev/null until_true 45 '[ "$(p_status $mi_on_p_post content | grep -c edited)" = "1" ]' && ok "mitrauser's edit reaches PrivaPub" || ko "mitrauser's edit never arrived" curl -s -o /dev/null -X PUT -H "$PH" "$P/api/v1/statuses/$p_post_id" -d "status=a PrivaPub post for Mitra $run, edited" until_true 45 '[ "$(mi_status_of $p_on_mi | j "print(\"edited\" in d[\"content\"])")" = "True" ]' && ok "alice's edit reaches Mitra" || ko "alice's edit never reached Mitra" gone=$(mi_json POST /api/v1/statuses "{\"status\":\"a Mitra post to delete $run\",\"visibility\":\"public\"}" | j "print(d['id'])") until_true 45 '[ -n "$(p_home_has "a Mitra post to delete $run")" ]' gone_on_p=$(p_home_has "a Mitra post to delete $run") mi -o /dev/null -X DELETE "$MI/api/v1/statuses/$gone" until_true 45 '[ "$(curl -s -o /dev/null -w "%{http_code}" -H "$PH" "$P/api/v1/statuses/$gone_on_p")" = "404" ]' \ && ok "mitrauser's deletion reaches PrivaPub" || ko "mitrauser's deleted post still shows on PrivaPub" curl -s -o /dev/null -X DELETE -H "$PH" "$P/api/v1/statuses/$p_post_id" until_true 45 '[ "$(mi -o /dev/null -w "%{http_code}" "$MI/api/v1/statuses/$p_on_mi")" = "404" ]' \ && ok "alice's deletion reaches Mitra" || ko "alice's deleted post still on Mitra" echo " direct messages" mi_json POST /api/v1/statuses "{\"status\":\"@alice_mitra@privapub.test a Mitra secret $run\",\"visibility\":\"direct\"}" >/dev/null until_true 45 'curl -s -H "$PH" "$P/api/v1/conversations" | grep -q "a Mitra secret $run"' && ok "mitrauser's DM arrives" || ko "mitrauser's DM never arrived" curl -s -o /dev/null -X POST -H "$PH" $P/api/v1/statuses -d "status=@mitrauser@mitra.test a PrivaPub secret $run&visibility=direct" until_true 45 'mi "$MI/api/v1/timelines/direct" "$MI/api/v1/conversations" | grep -q "a PrivaPub secret $run"' && ok "alice's DM reaches Mitra" || ko "alice's DM never reached Mitra" echo " unfollow" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$mi_on_p/unfollow" until_true 45 '[ "$(mi "$MI/api/v1/accounts/relationships?id[]=$alice_on_mi" | j "print(d[0][\"followed_by\"])")" = "False" ]' \ && ok "alice's unfollow reaches Mitra" || ko "Mitra still counts alice as a follower" echo " statistics" stats_check mitra.test mitra