Monorepo for Aesthetic.Computer
aesthetic.computer
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()