A community based topic aggregation platform built on atproto
at main 6.2 kB view raw
1//go:build ignore 2 3package main 4 5import ( 6 "database/sql" 7 "fmt" 8 "log" 9 "math/rand" 10 "time" 11 12 _ "github.com/lib/pq" 13) 14 15const ( 16 postURI = "at://did:plc:hcuo3qx2lr7h7dquusbeobht/social.coves.community.post/3m56mowhbuk22" 17 postCID = "bafyreibml4midgt7ojq7dnabnku5ikzro4erfvdux6mmiqeat7pci2gy4u" 18 communityDID = "did:plc:hcuo3qx2lr7h7dquusbeobht" 19) 20 21type User struct { 22 DID string 23 Handle string 24 Name string 25} 26 27type Comment struct { 28 URI string 29 CID string 30 RKey string 31 DID string 32 RootURI string 33 RootCID string 34 ParentURI string 35 ParentCID string 36 Content string 37 CreatedAt time.Time 38} 39 40// Escalating conversation between two users 41var deepThreadConversation = []string{ 42 "Wait, I just realized - if they both get suspended for this, their fantasy managers are SCREWED 😂", 43 "Bro imagine being in a league where you have BOTH Duren brothers and they both get suspended for fighting EACH OTHER", 44 "That's actually hilarious. 'Dear commissioner, my players got suspended for fighting... with each other'", 45 "The fantasy implications are wild. Do you get negative points for your players fighting your other players? 🤔", 46 "New fantasy category: Family Feuds. Duren brothers leading the league in FFD (Family Fight Disqualifications)", 47 "I'm dying 💀 FFD should absolutely be a stat. The Morris twins would've been unstoppable in that category", 48 "Don't forget the Plumlees! Those boys used to scrap in college practices. FFD Hall of Famers", 49 "Okay but serious question: has there EVER been brothers fighting each other in an NBA game before this? This has to be a first", 50 "I've been watching the NBA for 30 years and I can't think of a single time. This might genuinely be historic family beef", 51 "So we're witnessing NBA history right now. Not the good kind, but history nonetheless. Their mom is SO proud 😂", 52} 53 54var userHandles = []string{ 55 "deep_thread_guy_1.bsky.social", 56 "deep_thread_guy_2.bsky.social", 57} 58 59func generateTID() string { 60 now := time.Now().UnixMicro() 61 return fmt.Sprintf("%d%04d", now, rand.Intn(10000)) 62} 63 64func createUser(db *sql.DB, handle string, idx int) (*User, error) { 65 did := fmt.Sprintf("did:plc:deepthread%d%d", time.Now().Unix(), idx) 66 user := &User{ 67 DID: did, 68 Handle: handle, 69 Name: handle, 70 } 71 72 query := ` 73 INSERT INTO users (did, handle, pds_url, created_at, updated_at) 74 VALUES ($1, $2, $3, NOW(), NOW()) 75 ON CONFLICT (did) DO NOTHING 76 ` 77 78 _, err := db.Exec(query, user.DID, user.Handle, "http://localhost:3001") 79 if err != nil { 80 return nil, fmt.Errorf("failed to create user: %w", err) 81 } 82 83 log.Printf("Created user: %s (%s)", user.Handle, user.DID) 84 return user, nil 85} 86 87func createComment(db *sql.DB, user *User, content, parentURI, parentCID string, createdAt time.Time) (*Comment, error) { 88 rkey := generateTID() 89 uri := fmt.Sprintf("at://%s/social.coves.community.comment/%s", user.DID, rkey) 90 cid := fmt.Sprintf("bafy%s", rkey) 91 92 comment := &Comment{ 93 URI: uri, 94 CID: cid, 95 RKey: rkey, 96 DID: user.DID, 97 RootURI: postURI, 98 RootCID: postCID, 99 ParentURI: parentURI, 100 ParentCID: parentCID, 101 Content: content, 102 CreatedAt: createdAt, 103 } 104 105 query := ` 106 INSERT INTO comments ( 107 uri, cid, rkey, commenter_did, root_uri, root_cid, 108 parent_uri, parent_cid, content, created_at, indexed_at 109 ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW()) 110 ON CONFLICT (uri) DO NOTHING 111 RETURNING id 112 ` 113 114 var id int64 115 err := db.QueryRow(query, 116 comment.URI, comment.CID, comment.RKey, comment.DID, 117 comment.RootURI, comment.RootCID, comment.ParentURI, comment.ParentCID, 118 comment.Content, comment.CreatedAt, 119 ).Scan(&id) 120 if err != nil { 121 return nil, fmt.Errorf("failed to create comment: %w", err) 122 } 123 124 log.Printf("Level %d: %s", getCurrentLevel(parentURI), content) 125 return comment, nil 126} 127 128func getCurrentLevel(parentURI string) int { 129 if parentURI == postURI { 130 return 1 131 } 132 // Count how many times we've nested (rough estimate) 133 return 2 // Will be incremented as we go 134} 135 136func updateCommentCount(db *sql.DB, parentURI string, isPost bool) error { 137 if isPost { 138 _, err := db.Exec(` 139 UPDATE posts 140 SET comment_count = comment_count + 1 141 WHERE uri = $1 142 `, parentURI) 143 return err 144 } 145 146 _, err := db.Exec(` 147 UPDATE comments 148 SET reply_count = reply_count + 1 149 WHERE uri = $1 150 `, parentURI) 151 return err 152} 153 154func main() { 155 dbURL := "postgres://dev_user:dev_password@localhost:5435/coves_dev?sslmode=disable" 156 db, err := sql.Open("postgres", dbURL) 157 if err != nil { 158 log.Fatalf("Failed to connect to database: %v", err) 159 } 160 defer db.Close() 161 162 if err := db.Ping(); err != nil { 163 log.Fatalf("Failed to ping database: %v", err) 164 } 165 166 log.Println("Connected to database successfully!") 167 log.Println("Creating 10-level deep comment thread...") 168 169 rand.Seed(time.Now().UnixNano()) 170 171 // Create two users who will have the back-and-forth 172 user1, err := createUser(db, userHandles[0], 1) 173 if err != nil { 174 log.Fatalf("Failed to create user 1: %v", err) 175 } 176 177 user2, err := createUser(db, userHandles[1], 2) 178 if err != nil { 179 log.Fatalf("Failed to create user 2: %v", err) 180 } 181 182 baseTime := time.Now().Add(-30 * time.Minute) 183 184 // Create the 10-level deep thread 185 parentURI := postURI 186 parentCID := postCID 187 isPost := true 188 189 for i, content := range deepThreadConversation { 190 // Alternate between users 191 user := user1 192 if i%2 == 1 { 193 user = user2 194 } 195 196 createdAt := baseTime.Add(time.Duration(i*2) * time.Minute) 197 198 comment, err := createComment(db, user, content, parentURI, parentCID, createdAt) 199 if err != nil { 200 log.Fatalf("Failed to create comment at level %d: %v", i+1, err) 201 } 202 203 // Update parent's reply count 204 if err := updateCommentCount(db, parentURI, isPost); err != nil { 205 log.Printf("Warning: Failed to update comment count: %v", err) 206 } 207 208 // Set this comment as the parent for the next iteration 209 parentURI = comment.URI 210 parentCID = comment.CID 211 isPost = false 212 213 time.Sleep(10 * time.Millisecond) 214 } 215 216 log.Println("\n=== Summary ===") 217 log.Printf("Created 10-level deep comment thread") 218 log.Printf("Thread participants: %s and %s", user1.Handle, user2.Handle) 219 log.Println("Done! Check the NBACentral post for the deep thread.") 220}