← back to Tiktok Oauth Catcher

fire-test-post.sh

42 lines

#!/usr/bin/env bash
# Fires ONE real SELF_ONLY (private) TikTok post to @designerwallcoverings via the
# Content Posting API FILE_UPLOAD flow — the App Review demo material.
# Steve runs this himself (the outbound publish is a Steve-only gate).
set -euo pipefail

V="${1:-$HOME/Videos/designerwallcoverings-promo-short-square/renders/video.mp4}"
AT=$(grep -E '^TIKTOK_ACCESS_TOKEN=' "$HOME/Projects/secrets-manager/.env" | head -1 | cut -d= -f2- | tr -d '"'"'"' \r')
[ -n "$AT" ] || { echo "No TIKTOK_ACCESS_TOKEN in secrets .env"; exit 1; }
SIZE=$(stat -f%z "$V" 2>/dev/null || wc -c < "$V")
echo "video: $V  ($SIZE bytes)"

echo "== 1) init =="
INIT=$(curl -s -X POST "https://open.tiktokapis.com/v2/post/publish/video/init/" \
  -H "Authorization: Bearer $AT" -H "Content-Type: application/json; charset=UTF-8" \
  -d "{\"post_info\":{\"title\":\"Designer Wallcoverings — sandbox test\",\"privacy_level\":\"SELF_ONLY\",\"disable_comment\":true,\"disable_duet\":true,\"disable_stitch\":true},\"source_info\":{\"source\":\"FILE_UPLOAD\",\"video_size\":$SIZE,\"chunk_size\":$SIZE,\"total_chunk_count\":1}}")
echo "$INIT"
UURL=$(python3 -c "import json,sys;print((json.loads('''$INIT''').get('data') or {}).get('upload_url',''))")
PID=$(python3 -c "import json,sys;print((json.loads('''$INIT''').get('data') or {}).get('publish_id',''))")
[ -n "$UURL" ] || { echo "no upload_url — stop"; exit 1; }
echo "publish_id: $PID"

echo "== 2) upload bytes =="
curl -s -X PUT "$UURL" \
  -H "Content-Type: video/mp4" \
  -H "Content-Range: bytes 0-$((SIZE-1))/$SIZE" \
  --data-binary "@$V" -o /dev/null -w "  upload HTTP %{http_code}\n"

echo "== 3) poll status (up to ~60s) =="
for i in $(seq 1 12); do
  sleep 5
  ST=$(curl -s -X POST "https://open.tiktokapis.com/v2/post/publish/status/fetch/" \
    -H "Authorization: Bearer $AT" -H "Content-Type: application/json; charset=UTF-8" \
    -d "{\"publish_id\":\"$PID\"}")
  S=$(python3 -c "import json;print((json.loads('''$ST''').get('data') or {}).get('status',''))")
  echo "  [$i] status: $S"
  case "$S" in
    PUBLISH_COMPLETE) echo "✅ POSTED (SELF_ONLY / private) to @designerwallcoverings"; break;;
    FAILED) echo "❌ failed: $ST"; break;;
  esac
done