Monorepo for Aesthetic.Computer aesthetic.computer
at main 111 lines 2.9 kB view raw
1#!/usr/bin/env node 2 3/** 4 * Delete All Bluesky Posts 5 * 6 * Delete all posts from the @aesthetic.computer Bluesky account. 7 * 8 * Usage: 9 * node delete-all-posts.mjs 10 * node delete-all-posts.mjs --confirm 11 */ 12 13import { AtpAgent } from '@atproto/api' 14import { config } from 'dotenv' 15 16config() 17 18const BSKY_SERVICE = process.env.BSKY_SERVICE || 'https://bsky.social' 19const BSKY_IDENTIFIER = process.env.BSKY_IDENTIFIER 20const BSKY_APP_PASSWORD = process.env.BSKY_APP_PASSWORD 21 22const args = process.argv.slice(2) 23const confirmed = args.includes('--confirm') 24 25async function deleteAllPosts() { 26 if (!BSKY_IDENTIFIER || !BSKY_APP_PASSWORD) { 27 console.error('❌ Error: Missing Bluesky credentials') 28 process.exit(1) 29 } 30 31 console.log(`\n🗑️ Delete All Posts from @${BSKY_IDENTIFIER}\n`) 32 console.log('═'.repeat(50) + '\n') 33 34 const agent = new AtpAgent({ service: BSKY_SERVICE }) 35 36 try { 37 // Login 38 console.log('🔐 Logging in...') 39 await agent.login({ 40 identifier: BSKY_IDENTIFIER, 41 password: BSKY_APP_PASSWORD 42 }) 43 console.log('✅ Logged in successfully\n') 44 45 // Fetch all posts 46 console.log('📥 Fetching all posts...') 47 const feed = await agent.getAuthorFeed({ 48 actor: BSKY_IDENTIFIER, 49 limit: 100 // Bluesky max 50 }) 51 52 const posts = feed.data.feed 53 console.log(`✅ Found ${posts.length} posts\n`) 54 55 if (posts.length === 0) { 56 console.log('✨ No posts to delete!') 57 return 58 } 59 60 // Show preview 61 console.log('📋 Posts to delete:\n') 62 posts.forEach((item, i) => { 63 const post = item.post 64 const text = post.record.text.substring(0, 60) 65 console.log(` ${i + 1}. ${text}${post.record.text.length > 60 ? '...' : ''}`) 66 }) 67 console.log() 68 69 if (!confirmed) { 70 console.log('⚠️ DRY RUN MODE') 71 console.log('💡 Run with --confirm to actually delete posts') 72 console.log(`\n node delete-all-posts.mjs --confirm\n`) 73 return 74 } 75 76 // Confirm deletion 77 console.log('🚨 DELETING POSTS...\n') 78 79 let deleted = 0 80 let failed = 0 81 82 for (let i = 0; i < posts.length; i++) { 83 const item = posts[i] 84 const uri = item.post.uri 85 86 try { 87 await agent.deletePost(uri) 88 console.log(` ✅ [${i + 1}/${posts.length}] Deleted: ${uri.split('/').pop()}`) 89 deleted++ 90 91 // Small delay to avoid rate limits 92 await new Promise(resolve => setTimeout(resolve, 200)) 93 } catch (error) { 94 console.error(` ❌ [${i + 1}/${posts.length}] Failed: ${error.message}`) 95 failed++ 96 } 97 } 98 99 console.log('\n' + '═'.repeat(50)) 100 console.log('✨ Summary\n') 101 console.log(`✅ Deleted: ${deleted}`) 102 console.log(`❌ Failed: ${failed}`) 103 console.log(`📊 Total: ${posts.length}\n`) 104 105 } catch (error) { 106 console.error('\n💥 Error:', error.message) 107 process.exit(1) 108 } 109} 110 111deleteAllPosts()