# Castopod 1.15.5: alice follows the podcast @pod; an episode published through its REST API reaches her with its audio; # her like, reply and boost land on it there; the unfollow; statistics (from NodeInfo2, all Castopod publishes). The # episode's sound is made with ffmpeg; Castopod's own fediverse tables (cp_fediverse_*) say what it holds. . "$here/peers/castopod.sh" CP=https://castopod.test:6443 cpc() { site castopod.test -s -u "$CASTOPOD_API" "$@"; } cp_sql() { podman exec pasture-mysql mysql -upasture -ppasture castopod -Nse "$1" 2>/dev/null; } 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 '') or '$1' in (((s.get('reblog') or s).get('privapub') or {}).get('title') or '')), ''))"; } p_status() { curl -s -H "$PH" "$P/api/v1/statuses/$1" | j "print(d.get('$2'))"; } echo "castopod" [ "$(cpc "$CP/api/rest/v1/podcasts" | j "print(next((p['handle'] for p in d), ''))")" = "pod" ] && ok "Castopod's REST API and the podcast @pod" \ || { ko "Castopod's REST API ($(cpc "$CP/api/rest/v1/podcasts" | head -c 200))"; return 1; } PT=$(privapub_token alice_castopod) PH="Authorization: Bearer $PT" [ -n "$PT" ] && ok "PrivaPub token for alice_castopod" || { ko "PrivaPub token for alice_castopod"; return 1; } run=$(date +%s) echo " follows" pod_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=pod@castopod.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])") [ -n "$pod_on_p" ] && ok "PrivaPub resolves the podcast @pod" || ko "PrivaPub cannot resolve @pod" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$pod_on_p/follow" until_true 60 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$pod_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \ && ok "alice follows @pod (Accept arrived)" || ko "Castopod's Accept never arrived" echo " episodes" mp3="$here/.state/castopod/episode.mp3" [ -s "$mp3" ] || ffmpeg -loglevel error -f lavfi -i "sine=frequency=440:duration=4" -q:a 9 "$mp3" episode=$(cpc -X POST "$CP/api/rest/v1/episodes" -F created_by=1 -F updated_by=1 -F podcast_id=1 -F "title=A pasture episode $run" \ -F "slug=a-pasture-episode-$run" -F "description=Listen to the meadow $run" -F type=full -F parental_advisory=clean -F location_name= \ -F custom_rss= -F "audio_file=@$mp3;type=audio/mpeg" | j "print(d.get('id', ''))") [ -n "$episode" ] && ok "Castopod makes the episode" || ko "Castopod refused the episode" cpc -o /dev/null -X POST "$CP/api/rest/v1/episodes/$episode/publish" -F created_by=1 -F publication_method=now -F client_timezone=UTC castopod_spark fediverse:broadcast >/dev/null 2>&1 until_true 90 '[ -n "$(p_home_has "A pasture episode $run")" ] || [ -n "$(p_home_has "Listen to the meadow $run")" ]' \ && ok "the episode reaches alice's home" || ko "the episode never reached alice" ep_on_p=$(p_home_has "A pasture episode $run"); [ -n "$ep_on_p" ] || ep_on_p=$(p_home_has "Listen to the meadow $run") [ "$(curl -s -H "$PH" "$P/api/v1/statuses/$ep_on_p" | j "print(any(m['type'] == 'audio' for m in d['media_attachments']) or bool((d.get('privapub') or {}).get('audio')))")" = "True" ] \ && ok "with its audio" || ko "the episode arrived without its audio ($(curl -s -H "$PH" "$P/api/v1/statuses/$ep_on_p" | head -c 300))" ep_uri=$(p_status "$ep_on_p" uri) echo " alice answers" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$ep_on_p/favourite" until_true 60 '[ "$(cp_sql "select count(*) from cp_fediverse_favourites f join cp_fediverse_actors a on a.id = f.actor_id where a.uri like '"'%alice_castopod%'"'")" -ge 1 ]' \ && ok "alice's like lands on Castopod" || ko "alice's like never reached Castopod" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$ep_on_p/reblog" until_true 60 '[ "$(cp_sql "select count(*) from cp_fediverse_posts p join cp_fediverse_actors a on a.id = p.actor_id where a.uri like '"'%alice_castopod%'"' and p.reblog_of_id is not null")" -ge 1 ]' \ && ok "alice's boost lands on Castopod" || ko "alice's boost never reached Castopod" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses" -d "status=@pod@castopod.test a PrivaPub comment $run&in_reply_to_id=$ep_on_p&visibility=public" until_true 60 '[ "$(cp_sql "select count(*) from cp_fediverse_posts where message like '"'%a PrivaPub comment $run%'"' and in_reply_to_id is not null")" -ge 1 ]' \ && ok "alice's comment threads under the episode" || ko "alice's comment never reached Castopod" echo " unfollow" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$pod_on_p/unfollow" until_true 60 '[ "$(cp_sql "select count(*) from cp_fediverse_follows f join cp_fediverse_actors a on a.id = f.actor_id where a.uri like '"'%alice_castopod%'"'")" = "0" ]' \ && ok "alice's unfollow reaches Castopod" || ko "Castopod still counts alice" echo " statistics" stats_check castopod.test castopod