PeerTube puts canReply on a video whose comments wait for approval, and answers each comment with ApproveReply. A persona's reply to such a post now waits (privapub.approval: pending), its Create going to the author alone; the author's ApproveReply, signed by the author and naming the post answered, lets it out to its audience with replyApproval, and RejectReply leaves it ours. A null canReply (PeerTube's open comments) says nothing; an empty one refuses. The PeerTube scenario holds a comment for review and approves it through PeerTube's API (28 checks). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
120 lines
9.9 KiB
Bash
120 lines
9.9 KiB
Bash
# PeerTube 8.3: a persona follows a channel; the channel's video arrives as a playable post, its file streamed through
|
|
# PrivaPub's media proxy with byte ranges; comments both ways thread; a comment on a video whose comments are moderated
|
|
# waits for the owner's approval (FEP-5624); a like counts and its undo too; the video's edit
|
|
# and its deletion reach PrivaPub; statistics. PeerTube's users follow channels and accounts of PeerTube-like servers
|
|
# only, so nothing here has PeerTube following a persona.
|
|
PTB=https://peertube.test:6443
|
|
# PeerTube checks the Host against its own name, without the port
|
|
pcurl() { curl -sk --resolve peertube.test:6443:127.0.0.1 -H "Host: peertube.test" "$@"; }
|
|
PTROOT=$(cat "$here/.state/peertube.token" 2>/dev/null)
|
|
PTPASS=Peertube-Pasture-User-1
|
|
# a user's token through the instance's own OAuth client
|
|
pt_token() {
|
|
local client
|
|
client=$(pcurl "$PTB/api/v1/oauth-clients/local")
|
|
pcurl -X POST "$PTB/api/v1/users/token" \
|
|
--data-urlencode "client_id=$(echo "$client" | j "print(d['client_id'])")" \
|
|
--data-urlencode "client_secret=$(echo "$client" | j "print(d['client_secret'])")" \
|
|
--data-urlencode grant_type=password --data-urlencode "username=$1" --data-urlencode "password=$2" | j "print(d['access_token'])"
|
|
}
|
|
# a PrivaPub status in alice_peertube's home whose text or title has the given words; a channel shares its videos by
|
|
# boosting them, so it is the boosted status
|
|
p_home_id() { curl -s -H "$PH" "$P/api/v1/timelines/home?limit=40" | j "print(next((o['id'] for o in ((s.get('reblog') or s) for s in d) if '$1' in (o['content'] or '') or '$1' in ((o.get('privapub') or {}).get('title') or '')), ''))"; }
|
|
|
|
echo "peertube"
|
|
[ -n "$PTROOT" ] && ok "PeerTube root token" || { ko "PeerTube root token"; return 1; }
|
|
pcurl -o /dev/null -X POST -H "Authorization: Bearer $PTROOT" -H 'Content-Type: application/json' "$PTB/api/v1/users" \
|
|
-d "{\"username\":\"ptuser\",\"password\":\"$PTPASS\",\"email\":\"ptuser@peertube.test\",\"role\":2,\"videoQuota\":-1,\"videoQuotaDaily\":-1}"
|
|
TT=$(pt_token ptuser "$PTPASS")
|
|
TH="Authorization: Bearer $TT"
|
|
[ -n "$TT" ] && ok "PeerTube token for ptuser" || { ko "PeerTube token for ptuser"; return 1; }
|
|
channel=$(pcurl -H "$TH" "$PTB/api/v1/users/me" | j "print(d['videoChannels'][0]['name'])")
|
|
channel_id=$(pcurl -H "$TH" "$PTB/api/v1/users/me" | j "print(d['videoChannels'][0]['id'])")
|
|
PT=$(privapub_token alice_peertube)
|
|
PH="Authorization: Bearer $PT"
|
|
[ -n "$PT" ] && ok "PrivaPub token for alice_peertube" || { ko "PrivaPub token for alice_peertube"; return 1; }
|
|
|
|
echo " discovery and follows"
|
|
channel_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=$channel@peertube.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
|
|
[ -n "$channel_on_p" ] && ok "PrivaPub resolves the channel @$channel@peertube.test" || ko "PrivaPub cannot resolve the channel"
|
|
[ "$(curl -s -H "$PH" "$P/api/v1/accounts/$channel_on_p" | j "print(d['group'])")" = "True" ] && ok "the channel is a group account" || ko "the channel is not shown as a group"
|
|
account_on_p=$(curl -s -H "$PH" "$P/api/v2/search?q=ptuser@peertube.test&resolve=true&type=accounts" | j "print(d['accounts'][0]['id'])")
|
|
[ -n "$account_on_p" ] && ok "PrivaPub resolves the account @ptuser@peertube.test" || ko "PrivaPub cannot resolve the account"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$channel_on_p/follow"
|
|
until_true 30 '[ "$(curl -s -H "$PH" "$P/api/v1/accounts/relationships?id[]=$channel_on_p" | j "print(d[0][\"following\"])")" = "True" ]' \
|
|
&& ok "alice_peertube follows the channel (Accept arrived)" || ko "the channel's Accept never arrived"
|
|
until_true 30 '[ "$(pcurl -H "$TH" "$PTB/api/v1/video-channels/$channel/followers" | j "print(d[\"total\"])")" -ge 1 ]' \
|
|
&& ok "PeerTube lists alice_peertube among the channel's followers" || ko "PeerTube does not list the follower"
|
|
|
|
echo " videos"
|
|
run=$(date +%s)
|
|
video=$(pcurl -X POST -H "$TH" "$PTB/api/v1/videos/upload" -F "videofile=@$here/town/media/tiny.mp4;type=video/mp4" \
|
|
-F "channelId=$channel_id" -F "name=Hello PrivaPub from PeerTube $run" -F "description=a tiny test video" -F privacy=1 -F commentsPolicy=1 -F waitTranscoding=false)
|
|
video_id=$(echo "$video" | j "print(d['video']['shortUUID'])")
|
|
[ -n "$video_id" ] && ok "ptuser uploads a video" || ko "upload refused: $(echo "$video" | head -c 200)"
|
|
until_true 60 '[ -n "$(p_home_id "Hello PrivaPub from PeerTube $run")" ]' && ok "the video reaches alice_peertube's home, boosted by its channel" || ko "the video never arrived"
|
|
v_on_p=$(p_home_id "Hello PrivaPub from PeerTube $run")
|
|
v_status=$(curl -s -H "$PH" "$P/api/v1/statuses/$v_on_p")
|
|
[ "$(echo "$v_status" | j "print(d['media_attachments'][0]['type'])")" = "video" ] && ok "the video is a playable attachment" || ko "no video attachment: $(echo "$v_status" | j "print(d['media_attachments'])" | head -c 200)"
|
|
v_file=$(echo "$v_status" | j "print(d['media_attachments'][0]['url'])")
|
|
case "$v_file" in
|
|
*privapub.test/*) ok "its file is served through PrivaPub's proxy" ;;
|
|
*) ko "its file is not proxied: $v_file" ;;
|
|
esac
|
|
range=$(pfetch -s -o /dev/null -w '%{http_code} %{size_download}' -H 'Range: bytes=0-99' "$v_file")
|
|
[ "$range" = "206 100" ] && ok "the proxy answers a byte range (206, 100 bytes)" || ko "the proxy did not answer the range: $range"
|
|
|
|
echo " comments"
|
|
curl -s -o /dev/null -X POST -H "$PH" $P/api/v1/statuses -d "status=@ptuser@peertube.test lovely video&in_reply_to_id=$v_on_p&visibility=public"
|
|
until_true 30 '[ "$(pcurl "$PTB/api/v1/videos/$video_id/comment-threads" | j "print(any(\"lovely video\" in c[\"text\"] for c in d[\"data\"]))")" = "True" ]' \
|
|
&& ok "alice_peertube's reply is a comment on the video" || ko "the reply never became a comment"
|
|
thread=$(pcurl "$PTB/api/v1/videos/$video_id/comment-threads" | j "print(next(c['id'] for c in d['data'] if 'lovely video' in c['text']))")
|
|
pcurl -o /dev/null -X POST -H "$TH" -H 'Content-Type: application/json' "$PTB/api/v1/videos/$video_id/comments/$thread" -d '{"text":"thank you from PeerTube"}'
|
|
until_true 30 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$v_on_p/context" | j "print(any(\"thank you from PeerTube\" in s[\"content\"] for s in d[\"descendants\"]))")" = "True" ]' \
|
|
&& ok "ptuser's answer threads under the video on PrivaPub" || ko "PeerTube's answer missing from the thread"
|
|
|
|
echo " moderated comments"
|
|
# a video whose comments wait for approval (FEP-5624's canReply): alice's comment waits, goes to PeerTube alone, and is let
|
|
# in by ptuser's approval (ApproveReply), after which PeerTube shows it
|
|
held=$(date +%s)
|
|
mvideo=$(pcurl -X POST -H "$TH" "$PTB/api/v1/videos/upload" -F "videofile=@$here/town/media/tiny.mp4;type=video/mp4" \
|
|
-F "channelId=$channel_id" -F "name=A moderated video $held" -F "description=comments wait here" -F privacy=1 -F commentsPolicy=3 -F waitTranscoding=false \
|
|
| j "print(d['video']['shortUUID'])")
|
|
until_true 60 '[ -n "$(p_home_id "A moderated video $held")" ]' >/dev/null
|
|
m_on_p=$(p_home_id "A moderated video $held")
|
|
m_reply=$(curl -s -X POST -H "$PH" $P/api/v1/statuses -d "status=@ptuser@peertube.test a comment to approve $held&in_reply_to_id=$m_on_p&visibility=public" | j "print(d['id'])")
|
|
[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$m_reply" | j "print((d.get('privapub') or {}).get('approval'))")" = "pending" ] \
|
|
&& ok "alice's comment on a moderated video waits for its approval" || ko "alice's comment on a moderated video does not wait"
|
|
# (its owner sees it in the video's threads, held for review; PeerTube 8.3's list of held comments answers 500)
|
|
pt_held() { pcurl -H "$TH" "$PTB/api/v1/videos/$mvideo/comment-threads" | j "print(next((c['id'] for c in d['data'] if c.get('heldForReview') and 'approve $held' in c['text']), ''))"; }
|
|
until_true 30 '[ -n "$(pt_held)" ]' && ok "PeerTube holds it for review" || ko "PeerTube never held alice's comment"
|
|
held_id=$(pt_held)
|
|
pcurl -o /dev/null -X POST -H "$TH" "$PTB/api/v1/videos/$mvideo/comments/$held_id/approve"
|
|
until_true 30 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$m_reply" | j "print((d.get(\"privapub\") or {}).get(\"approval\"))")" = "None" ]' \
|
|
&& ok "ptuser's approval (ApproveReply) lets alice's comment in" || ko "the approval never reached PrivaPub"
|
|
[ "$(pcurl "$PTB/api/v1/videos/$mvideo/comment-threads" | j "print(any('a comment to approve $held' in c['text'] for c in d['data']))")" = "True" ] \
|
|
&& ok "PeerTube shows the approved comment" || ko "PeerTube does not show the approved comment"
|
|
pcurl -o /dev/null -X DELETE -H "$TH" "$PTB/api/v1/videos/$mvideo"
|
|
|
|
echo " likes"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$v_on_p/favourite"
|
|
until_true 30 '[ "$(pcurl "$PTB/api/v1/videos/$video_id" | j "print(d[\"likes\"])")" = "1" ]' && ok "alice_peertube's like counts on PeerTube" || ko "like not counted on PeerTube"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/statuses/$v_on_p/unfavourite"
|
|
until_true 30 '[ "$(pcurl "$PTB/api/v1/videos/$video_id" | j "print(d[\"likes\"])")" = "0" ]' && ok "alice_peertube's unlike reaches PeerTube" || ko "unlike not applied on PeerTube"
|
|
|
|
echo " edits and deletes"
|
|
pcurl -o /dev/null -X PUT -H "$TH" -H 'Content-Type: application/json' "$PTB/api/v1/videos/$video_id" -d '{"name":"Hello again from PeerTube","description":"renamed"}'
|
|
until_true 30 '[ "$(curl -s -H "$PH" "$P/api/v1/statuses/$v_on_p" | j "print(\"Hello again from PeerTube\" in json.dumps(d))")" = "True" ]' \
|
|
&& ok "the video's new name reaches PrivaPub" || ko "the edit never arrived"
|
|
pcurl -o /dev/null -X DELETE -H "$TH" "$PTB/api/v1/videos/$video_id"
|
|
until_true 30 '[ "$(curl -s -o /dev/null -w "%{http_code}" -H "$PH" "$P/api/v1/statuses/$v_on_p")" = "404" ]' \
|
|
&& ok "the video's deletion reaches PrivaPub" || ko "the deleted video is still on PrivaPub"
|
|
|
|
echo " unfollow"
|
|
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$channel_on_p/unfollow"
|
|
until_true 30 '[ "$(pcurl -H "$TH" "$PTB/api/v1/video-channels/$channel/followers" | j "print(d[\"total\"])")" = "0" ]' \
|
|
&& ok "the unfollow reaches PeerTube" || ko "PeerTube still lists alice_peertube"
|
|
|
|
echo " statistics"
|
|
stats_check peertube.test peertube
|