A community based topic aggregation platform built on atproto
1#!/bin/bash
2
3# Script: setup-kagi-aggregator.sh
4# Purpose: Complete setup script for Kagi News RSS aggregator
5#
6# This is a reference implementation showing automated setup for a specific aggregator.
7# Other aggregator developers can use this as a template.
8
9set -e
10
11echo "================================================"
12echo "Kagi News RSS Aggregator - Automated Setup"
13echo "================================================"
14echo ""
15
16# Configuration for Kagi aggregator
17AGGREGATOR_NAME="kagi-news-bot"
18DISPLAY_NAME="Kagi News RSS"
19DESCRIPTION="Aggregates tech news from Kagi RSS feeds and posts to relevant communities"
20SOURCE_URL="https://github.com/coves-social/kagi-aggregator"
21
22# Check if config already exists
23if [ -f "kagi-aggregator-config.env" ]; then
24 echo "Configuration file already exists. Loading existing configuration..."
25 source kagi-aggregator-config.env
26 SKIP_ACCOUNT_CREATION=true
27else
28 SKIP_ACCOUNT_CREATION=false
29fi
30
31# Get runtime configuration
32if [ "$SKIP_ACCOUNT_CREATION" = false ]; then
33 read -p "Enter PDS URL (default: https://bsky.social): " PDS_URL
34 PDS_URL=${PDS_URL:-https://bsky.social}
35
36 read -p "Enter email for bot account: " EMAIL
37 read -sp "Enter password for bot account: " PASSWORD
38 echo ""
39
40 # Generate handle
41 TIMESTAMP=$(date +%s)
42 HANDLE="$AGGREGATOR_NAME-$TIMESTAMP.bsky.social"
43
44 echo ""
45 echo "Creating PDS account..."
46 echo "Handle: $HANDLE"
47
48 # Create account
49 RESPONSE=$(curl -s -X POST "$PDS_URL/xrpc/com.atproto.server.createAccount" \
50 -H "Content-Type: application/json" \
51 -d "{
52 \"handle\": \"$HANDLE\",
53 \"email\": \"$EMAIL\",
54 \"password\": \"$PASSWORD\"
55 }")
56
57 if echo "$RESPONSE" | jq -e '.error' > /dev/null 2>&1; then
58 echo "✗ Error creating account:"
59 echo "$RESPONSE" | jq '.'
60 exit 1
61 fi
62
63 DID=$(echo "$RESPONSE" | jq -r '.did')
64 ACCESS_JWT=$(echo "$RESPONSE" | jq -r '.accessJwt')
65 REFRESH_JWT=$(echo "$RESPONSE" | jq -r '.refreshJwt')
66
67 echo "✓ Account created: $DID"
68
69 # Save configuration
70 cat > kagi-aggregator-config.env <<EOF
71# Kagi Aggregator Configuration
72AGGREGATOR_DID="$DID"
73AGGREGATOR_HANDLE="$HANDLE"
74AGGREGATOR_PDS_URL="$PDS_URL"
75AGGREGATOR_EMAIL="$EMAIL"
76AGGREGATOR_PASSWORD="$PASSWORD"
77AGGREGATOR_ACCESS_JWT="$ACCESS_JWT"
78AGGREGATOR_REFRESH_JWT="$REFRESH_JWT"
79EOF
80
81 echo "✓ Configuration saved to kagi-aggregator-config.env"
82fi
83
84# Get domain and Coves instance
85read -p "Enter aggregator domain (e.g., kagi-news.example.com): " DOMAIN
86read -p "Enter Coves instance URL (default: https://api.coves.social): " COVES_URL
87COVES_URL=${COVES_URL:-https://api.coves.social}
88
89# Setup .well-known
90echo ""
91echo "Setting up .well-known/atproto-did..."
92mkdir -p .well-known
93echo "$DID" > .well-known/atproto-did
94echo "✓ Created .well-known/atproto-did"
95
96echo ""
97echo "================================================"
98echo "IMPORTANT: Manual Step Required"
99echo "================================================"
100echo ""
101echo "Upload the .well-known directory to your web server at:"
102echo " https://$DOMAIN/.well-known/atproto-did"
103echo ""
104read -p "Press Enter when the file is uploaded and accessible..."
105
106# Verify .well-known
107echo ""
108echo "Verifying .well-known/atproto-did..."
109WELLKNOWN_CONTENT=$(curl -s "https://$DOMAIN/.well-known/atproto-did" || echo "ERROR")
110
111if [ "$WELLKNOWN_CONTENT" != "$DID" ]; then
112 echo "✗ Error: .well-known/atproto-did not accessible or contains wrong DID"
113 echo " Expected: $DID"
114 echo " Got: $WELLKNOWN_CONTENT"
115 exit 1
116fi
117
118echo "✓ .well-known/atproto-did verified"
119
120# Register with Coves
121echo ""
122echo "Registering with Coves instance..."
123RESPONSE=$(curl -s -X POST "$COVES_URL/xrpc/social.coves.aggregator.register" \
124 -H "Content-Type: application/json" \
125 -d "{
126 \"did\": \"$DID\",
127 \"domain\": \"$DOMAIN\"
128 }")
129
130if echo "$RESPONSE" | jq -e '.error' > /dev/null 2>&1; then
131 echo "✗ Registration failed:"
132 echo "$RESPONSE" | jq '.'
133 exit 1
134fi
135
136echo "✓ Registered with Coves"
137
138# Create service declaration
139echo ""
140echo "Creating service declaration..."
141SERVICE_RECORD=$(cat <<EOF
142{
143 "\$type": "social.coves.aggregator.service",
144 "did": "$DID",
145 "displayName": "$DISPLAY_NAME",
146 "description": "$DESCRIPTION",
147 "sourceUrl": "$SOURCE_URL",
148 "createdAt": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
149}
150EOF
151)
152
153RESPONSE=$(curl -s -X POST "$PDS_URL/xrpc/com.atproto.repo.createRecord" \
154 -H "Authorization: Bearer $ACCESS_JWT" \
155 -H "Content-Type: application/json" \
156 -d "{
157 \"repo\": \"$DID\",
158 \"collection\": \"social.coves.aggregator.service\",
159 \"rkey\": \"self\",
160 \"record\": $SERVICE_RECORD
161 }")
162
163if echo "$RESPONSE" | jq -e '.error' > /dev/null 2>&1; then
164 echo "✗ Failed to create service declaration:"
165 echo "$RESPONSE" | jq '.'
166 exit 1
167fi
168
169RECORD_URI=$(echo "$RESPONSE" | jq -r '.uri')
170echo "✓ Service declaration created: $RECORD_URI"
171
172# Save final configuration
173cat >> kagi-aggregator-config.env <<EOF
174
175# Setup completed on $(date)
176AGGREGATOR_DOMAIN="$DOMAIN"
177COVES_INSTANCE_URL="$COVES_URL"
178SERVICE_DECLARATION_URI="$RECORD_URI"
179EOF
180
181echo ""
182echo "================================================"
183echo "✓ Kagi Aggregator Setup Complete!"
184echo "================================================"
185echo ""
186echo "Configuration saved to: kagi-aggregator-config.env"
187echo ""
188echo "Your aggregator is now registered and ready to use."
189echo ""
190echo "Next steps:"
191echo "1. Start your aggregator bot: npm start (or appropriate command)"
192echo "2. Community moderators can authorize your aggregator"
193echo "3. Once authorized, your bot can start posting"
194echo ""
195echo "See docs/aggregators/SETUP_GUIDE.md for more information"