#!/bin/sh # shared helpers for the dev bootstrap scripts. source, don't run. : "${PDS_URL:?PDS_URL must be set}" PASSWORD="${PASSWORD:-password}" CREATED_AT="${CREATED_AT:-2025-09-22T11:14:35+01:00}" # resolve_handle HANDLE → DID on stdout resolve_handle() { resp=$(curl -sS -w '\n%{http_code}' \ "${PDS_URL}/xrpc/com.atproto.identity.resolveHandle?handle=$1") body=$(printf '%s\n' "$resp" | sed '$d') status=$(printf '%s\n' "$resp" | tail -n1) case "$status" in 200) printf '%s\n' "$body" | jq -er '.did' ;; 400) : ;; # not found — expected *) printf 'resolveHandle %s: HTTP %s: %s\n' "$1" "$status" "$body" >&2; return 1 ;; esac } # login DID/Handle → access JWT on stdout login() { curl -fsS -H "Content-Type: application/json" \ -d "{\"identifier\":\"$1\",\"password\":\"${PASSWORD}\"}" \ "${PDS_URL}/xrpc/com.atproto.server.createSession" \ | jq -er '.accessJwt' } # service_token JWT LXM → service auth JWT for the knot, on stdout. service_token() { : "${KNOT_HOSTNAME:?KNOT_HOSTNAME must be set}" aud="did:web:$(printf '%s' "$KNOT_HOSTNAME" | sed 's/:/%3A/g')" curl -fsS -H "Authorization: Bearer $1" \ "${PDS_URL}/xrpc/com.atproto.server.getServiceAuth?aud=${aud}&lxm=$2&exp=$(( $(date +%s) + 240 ))" \ | jq -er '.token' } # put_record at://DID/COLLECTION/RKEY RECORD_JSON # → the record's cid on stdout, for use in a strongRef (comment subject, replyTo). # callers that don't need it can ignore stdout. put_record() { case "$1" in at://did:*/*/*) ;; *) printf 'put_record: expected at://DID/COLLECTION/RKEY, got %s\n' "$1" >&2; return 1 ;; esac rest=${1#at://} did=${rest%%/*} rest=${rest#*/} collection=${rest%%/*} rkey=${rest#*/} record="$2" # one login per record — the dev PDS runs with rate limits disabled jwt=$(login "$did") payload=$(jq -nc \ --arg repo "$did" \ --arg collection "$collection" \ --arg rkey "$rkey" \ --argjson record "$record" \ '{repo:$repo, collection:$collection, rkey:$rkey, record:$record}') resp=$(curl -fsS \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${jwt}" \ -d "$payload" \ "${PDS_URL}/xrpc/com.atproto.repo.putRecord") printf '[record] %s\n' "$1" >&2 printf '%s\n' "$resp" | jq -er '.cid' # -e: fail loudly if the cid is absent }