A third party ATProto appview
at main 4.1 kB view raw
1#!/bin/bash 2 3# A script to authenticate with Bluesky and fetch the user's timeline. 4# This version automatically discovers the user's PDS. 5# 6# USAGE: 7# ./fetch_timeline.sh your-handle.bsky.social your-app-password 8# 9# DEPENDENCIES: 10# - curl: For making HTTP requests. 11# - jq: For parsing JSON responses. (Install with: sudo apt-get install jq / brew install jq) 12 13set -e # Exit immediately if any command fails 14 15# --- CONFIGURATION --- 16# The AppView to fetch the timeline from. 17# Set this to your custom AppView for testing or leave as the official one. 18APPVIEW_HOST="https://appview.dollspace.gay" 19 20# --- 1. CHECK DEPENDENCIES & ARGUMENTS --- 21 22# Check for jq 23if ! command -v jq &> /dev/null; then 24 echo "Error: 'jq' is not installed. Please install it to proceed." 25 echo "e.g., sudo apt-get install jq or brew install jq" 26 exit 1 27fi 28 29# Check for curl 30if ! command -v curl &> /dev/null; then 31 echo "Error: 'curl' is not installed. Please install it to proceed." 32 exit 1 33fi 34 35# Check for command-line arguments 36if [ "$#" -ne 2 ]; then 37 echo "Usage: $0 <handle> <app-password>" 38 exit 1 39fi 40 41HANDLE=$1 42APP_PASSWORD=$2 43 44# --- 2. RESOLVE HANDLE TO FIND PDS --- 45 46echo "🔎 Resolving handle '$HANDLE' to find user's PDS..." 47 48# Step 2a: Resolve the handle to get the user's DID 49# This asks a public server (bsky.social) what DID corresponds to the handle. 50DID_RESPONSE=$(curl -s "https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=$HANDLE") 51DID=$(echo "$DID_RESPONSE" | jq -r '.did') 52 53if [ "$DID" == "null" ] || [ -z "$DID" ]; then 54 echo "❌ Error: Could not resolve handle '$HANDLE' to a DID." 55 echo "Server response:" 56 echo "$DID_RESPONSE" | jq . 57 exit 1 58fi 59 60echo "✅ Found DID: $DID" 61 62# Step 2b: Use the DID to look up the user's DID Document from the PLC directory 63# The DID Document contains the user's actual PDS address. 64DID_DOC=$(curl -s "https://plc.directory/$DID") 65PDS_HOST=$(echo "$DID_DOC" | jq -r '.service[] | select(.id == "#atproto_pds") | .serviceEndpoint') 66 67if [ "$PDS_HOST" == "null" ] || [ -z "$PDS_HOST" ]; then 68 echo "❌ Error: Could not find PDS host in DID document for $DID." 69 echo "DID Document:" 70 echo "$DID_DOC" | jq . 71 exit 1 72fi 73 74echo "✅ Found PDS Host: $PDS_HOST" 75 76# --- 3. AUTHENTICATE AND GET TOKEN --- 77 78echo "🔐 Authenticating with PDS: $PDS_HOST..." 79 80# Capture the full JSON response from the server first for better error handling 81SESSION_RESPONSE=$(curl -s -X POST \ 82 -H "Content-Type: application/json" \ 83 -d "{\"identifier\": \"$HANDLE\", \"password\": \"$APP_PASSWORD\"}" \ 84 "$PDS_HOST/xrpc/com.atproto.server.createSession") 85 86# Now, extract the access token from the response 87TOKEN=$(echo "$SESSION_RESPONSE" | jq -r '.accessJwt' || echo "null") 88 89# Verify that we got a token 90if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then 91 echo "❌ Authentication failed. Server response:" 92 echo "$SESSION_RESPONSE" | jq . 93 echo "Please check your handle and app password." 94 exit 1 95fi 96 97echo "✅ Successfully obtained access token." 98 99# --- 3a. DECODE TOKEN FOR DEBUGGING --- 100# This part is useful for verifying the contents of the token itself. 101# The 'sub' field should match the DID we found earlier. 102echo "--- DEBUG: Decoding Access Token Payload ---" 103DECODED_PAYLOAD=$(echo "$TOKEN" | jq -R 'split(".") | .[1] | @base64d | fromjson' 2>/dev/null || echo "{}") 104echo "$DECODED_PAYLOAD" | jq . 105echo "------------------------------------------" 106 107 108# --- 4. FETCH THE TIMELINE --- 109 110echo "📄 Fetching timeline from AppView: $APPVIEW_HOST..." 111 112# Use the captured token in the Authorization header to make an authenticated request. 113TIMELINE_RESPONSE=$(curl -s -H "Authorization: Bearer $TOKEN" \ 114 "$APPVIEW_HOST/xrpc/app.bsky.feed.getTimeline?limit=25") 115 116 117# --- 5. OUTPUT THE RESULT --- 118 119echo "--- TIMELINE RESPONSE ---" 120# Pipe the response to jq for pretty-printing if it's valid JSON 121if echo "$TIMELINE_RESPONSE" | jq . &> /dev/null; then 122 echo "$TIMELINE_RESPONSE" | jq . 123else 124 echo "❌ Failed to fetch timeline or response was not valid JSON:" 125 echo "$TIMELINE_RESPONSE" 126fi