Monorepo for Tangled
at e949a86d926b049287187fad78915dbc05492253 131 lines 3.3 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 lexutil "github.com/bluesky-social/indigo/lex/util" 10 "tangled.org/core/api/tangled" 11 "tangled.org/core/appview/db" 12 "tangled.org/core/appview/models" 13 "tangled.org/core/appview/pages" 14 "tangled.org/core/tid" 15) 16 17func (s *State) Follow(w http.ResponseWriter, r *http.Request) { 18 currentUser := s.oauth.GetMultiAccountUser(r) 19 20 subject := r.URL.Query().Get("subject") 21 if subject == "" { 22 log.Println("invalid form") 23 return 24 } 25 26 subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject) 27 if err != nil { 28 log.Println("failed to follow, invalid did") 29 return 30 } 31 32 if currentUser.Active.Did == subjectIdent.DID.String() { 33 log.Println("cant follow or unfollow yourself") 34 return 35 } 36 37 client, err := s.oauth.AuthorizedClient(r) 38 if err != nil { 39 log.Println("failed to authorize client") 40 return 41 } 42 43 switch r.Method { 44 case http.MethodPost: 45 createdAt := time.Now().Format(time.RFC3339) 46 rkey := tid.TID() 47 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 48 Collection: tangled.GraphFollowNSID, 49 Repo: currentUser.Active.Did, 50 Rkey: rkey, 51 Record: &lexutil.LexiconTypeDecoder{ 52 Val: &tangled.GraphFollow{ 53 Subject: subjectIdent.DID.String(), 54 CreatedAt: createdAt, 55 }}, 56 }) 57 if err != nil { 58 log.Println("failed to create atproto record", err) 59 return 60 } 61 62 log.Println("created atproto record: ", resp.Uri) 63 64 follow := &models.Follow{ 65 UserDid: currentUser.Active.Did, 66 SubjectDid: subjectIdent.DID.String(), 67 Rkey: rkey, 68 } 69 70 err = db.AddFollow(s.db, follow) 71 if err != nil { 72 log.Println("failed to follow", err) 73 return 74 } 75 76 s.notifier.NewFollow(r.Context(), follow) 77 78 followStats, err := db.GetFollowerFollowingCount(s.db, subjectIdent.DID.String()) 79 if err != nil { 80 log.Println("failed to get follow stats", err) 81 } 82 83 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 84 UserDid: subjectIdent.DID.String(), 85 FollowStatus: models.IsFollowing, 86 FollowersCount: followStats.Followers, 87 }) 88 89 return 90 case http.MethodDelete: 91 // find the record in the db 92 follow, err := db.GetFollow(s.db, currentUser.Active.Did, subjectIdent.DID.String()) 93 if err != nil { 94 log.Println("failed to get follow relationship") 95 return 96 } 97 98 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 99 Collection: tangled.GraphFollowNSID, 100 Repo: currentUser.Active.Did, 101 Rkey: follow.Rkey, 102 }) 103 104 if err != nil { 105 log.Println("failed to unfollow") 106 return 107 } 108 109 err = db.DeleteFollowByRkey(s.db, currentUser.Active.Did, follow.Rkey) 110 if err != nil { 111 log.Println("failed to delete follow from DB") 112 // this is not an issue, the firehose event might have already done this 113 } 114 115 followStats, err := db.GetFollowerFollowingCount(s.db, subjectIdent.DID.String()) 116 if err != nil { 117 log.Println("failed to get follow stats", err) 118 } 119 120 s.pages.FollowFragment(w, pages.FollowFragmentParams{ 121 UserDid: subjectIdent.DID.String(), 122 FollowStatus: models.IsNotFollowing, 123 FollowersCount: followStats.Followers, 124 }) 125 126 s.notifier.DeleteFollow(r.Context(), follow) 127 128 return 129 } 130 131}