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