A vibe coded tangled fork which supports pijul.
at sl/spindle-adapters 152 lines 3.8 kB view raw
1package state 2 3import ( 4 "log" 5 "net/http" 6 "time" 7 8 comatproto "github.com/bluesky-social/indigo/api/atproto" 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 lexutil "github.com/bluesky-social/indigo/lex/util" 11 "tangled.org/core/api/tangled" 12 "tangled.org/core/appview/db" 13 "tangled.org/core/appview/models" 14 "tangled.org/core/appview/pages" 15 "tangled.org/core/tid" 16) 17 18func (s *State) Star(w http.ResponseWriter, r *http.Request) { 19 currentUser := s.oauth.GetMultiAccountUser(r) 20 21 subject := r.URL.Query().Get("subject") 22 if subject == "" { 23 log.Println("invalid form") 24 return 25 } 26 27 subjectUri, err := syntax.ParseATURI(subject) 28 if err != nil { 29 log.Println("invalid form") 30 return 31 } 32 33 client, err := s.oauth.AuthorizedClient(r) 34 if err != nil { 35 log.Println("failed to authorize client", err) 36 return 37 } 38 39 switch r.Method { 40 case http.MethodPost: 41 star := models.Star{ 42 Did: currentUser.Active.Did, 43 Rkey: tid.TID(), 44 RepoAt: subjectUri, 45 Created: time.Now(), 46 } 47 48 tx, err := s.db.BeginTx(r.Context(), nil) 49 if err != nil { 50 s.logger.Error("failed to start transaction", "err", err) 51 return 52 } 53 defer tx.Rollback() 54 55 if err := db.UpsertStar(tx, star); err != nil { 56 s.logger.Error("failed to star", "err", err) 57 return 58 } 59 60 record := star.AsRecord() 61 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 62 Collection: tangled.FeedStarNSID, 63 Repo: currentUser.Active.Did, 64 Rkey: star.Rkey, 65 Record: &lexutil.LexiconTypeDecoder{ 66 Val: &record, 67 }, 68 }) 69 if err != nil { 70 log.Println("failed to create atproto record", err) 71 return 72 } 73 log.Println("created atproto record: ", resp.Uri) 74 75 if err := tx.Commit(); err != nil { 76 s.logger.Error("failed to commit transaction", "err", err) 77 // DB op failed but record is created in PDS. Ingester will backfill the missed operation 78 } 79 80 s.notifier.NewStar(r.Context(), &star) 81 82 starCount, err := db.GetStarCount(s.db, subjectUri) 83 if err != nil { 84 log.Println("failed to get star count for ", subjectUri) 85 } 86 87 s.pages.StarBtnFragment(w, pages.StarBtnFragmentParams{ 88 IsStarred: true, 89 SubjectAt: subjectUri, 90 StarCount: starCount, 91 }) 92 93 return 94 case http.MethodDelete: 95 tx, err := s.db.BeginTx(r.Context(), nil) 96 if err != nil { 97 s.logger.Error("failed to start transaction", "err", err) 98 } 99 defer tx.Rollback() 100 101 stars, err := db.DeleteStar(tx, syntax.DID(currentUser.Active.Did), subjectUri) 102 if err != nil { 103 s.logger.Error("failed to delete stars from db", "err", err) 104 return 105 } 106 107 var writes []*comatproto.RepoApplyWrites_Input_Writes_Elem 108 for _, starAt := range stars { 109 writes = append(writes, &comatproto.RepoApplyWrites_Input_Writes_Elem{ 110 RepoApplyWrites_Delete: &comatproto.RepoApplyWrites_Delete{ 111 Collection: tangled.FeedStarNSID, 112 Rkey: starAt.RecordKey().String(), 113 }, 114 }) 115 } 116 _, err = comatproto.RepoApplyWrites(r.Context(), client, &comatproto.RepoApplyWrites_Input{ 117 Repo: currentUser.Active.Did, 118 Writes: writes, 119 }) 120 if err != nil { 121 s.logger.Error("failed to delete stars from PDS", "err", err) 122 return 123 } 124 125 if err := tx.Commit(); err != nil { 126 s.logger.Error("failed to commit transaction", "err", err) 127 // DB op failed but record is created in PDS. Ingester will backfill the missed operation 128 } 129 130 s.notifier.DeleteStar(r.Context(), &models.Star{ 131 Did: currentUser.Active.Did, 132 RepoAt: subjectUri, 133 // Rkey 134 // Created 135 }) 136 137 starCount, err := db.GetStarCount(s.db, subjectUri) 138 if err != nil { 139 log.Println("failed to get star count for ", subjectUri) 140 return 141 } 142 143 s.pages.StarBtnFragment(w, pages.StarBtnFragmentParams{ 144 IsStarred: false, 145 SubjectAt: subjectUri, 146 StarCount: starCount, 147 }) 148 149 return 150 } 151 152}