Monorepo for Tangled
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 129 lines 3.5 kB view raw
1package state 2 3import ( 4 "net/http" 5 "time" 6 7 comatproto "github.com/bluesky-social/indigo/api/atproto" 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 lexutil "github.com/bluesky-social/indigo/lex/util" 10 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) React(w http.ResponseWriter, r *http.Request) { 19 l := s.logger.With("handler", "React") 20 currentUser := s.oauth.GetMultiAccountUser(r) 21 22 subject := r.URL.Query().Get("subject") 23 if subject == "" { 24 l.Warn("invalid form") 25 return 26 } 27 28 subjectUri, err := syntax.ParseATURI(subject) 29 if err != nil { 30 l.Warn("invalid form", "subject", subject, "err", err) 31 return 32 } 33 34 reactionKind, ok := models.ParseReactionKind(r.URL.Query().Get("kind")) 35 if !ok { 36 l.Warn("invalid reaction kind", "kind", r.URL.Query().Get("kind")) 37 return 38 } 39 40 client, err := s.oauth.AuthorizedClient(r) 41 if err != nil { 42 l.Error("failed to authorize client", "err", err) 43 return 44 } 45 46 switch r.Method { 47 case http.MethodPost: 48 createdAt := time.Now().Format(time.RFC3339) 49 rkey := tid.TID() 50 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 51 Collection: tangled.FeedReactionNSID, 52 Repo: currentUser.Active.Did, 53 Rkey: rkey, 54 Record: &lexutil.LexiconTypeDecoder{ 55 Val: &tangled.FeedReaction{ 56 Subject: subjectUri.String(), 57 Reaction: reactionKind.String(), 58 CreatedAt: createdAt, 59 }, 60 }, 61 }) 62 if err != nil { 63 l.Error("failed to create atproto record", "err", err) 64 return 65 } 66 67 err = db.AddReaction(s.db, currentUser.Active.Did, subjectUri, reactionKind, rkey) 68 if err != nil { 69 l.Error("failed to react", "err", err) 70 return 71 } 72 73 reactionMap, err := db.GetReactionMap(s.db, 20, subjectUri) 74 if err != nil { 75 l.Error("failed to get reactions", "subjectUri", subjectUri, "err", err) 76 } 77 78 l.Info("created atproto record", "uri", resp.Uri) 79 80 s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{ 81 ThreadAt: subjectUri, 82 Kind: reactionKind, 83 Count: reactionMap[reactionKind].Count, 84 Users: reactionMap[reactionKind].Users, 85 IsReacted: true, 86 }) 87 88 return 89 case http.MethodDelete: 90 reaction, err := db.GetReaction(s.db, currentUser.Active.Did, subjectUri, reactionKind) 91 if err != nil { 92 l.Error("failed to get reaction relationship", "did", currentUser.Active.Did, "subjectUri", subjectUri, "err", err) 93 return 94 } 95 96 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 97 Collection: tangled.FeedReactionNSID, 98 Repo: currentUser.Active.Did, 99 Rkey: reaction.Rkey, 100 }) 101 102 if err != nil { 103 l.Error("failed to remove reaction", "err", err) 104 return 105 } 106 107 err = db.DeleteReactionByRkey(s.db, currentUser.Active.Did, reaction.Rkey) 108 if err != nil { 109 l.Warn("failed to delete reaction from DB", "err", err) 110 // this is not an issue, the firehose event might have already done this 111 } 112 113 reactionMap, err := db.GetReactionMap(s.db, 20, subjectUri) 114 if err != nil { 115 l.Error("failed to get reactions", "subjectUri", subjectUri, "err", err) 116 return 117 } 118 119 s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{ 120 ThreadAt: subjectUri, 121 Kind: reactionKind, 122 Count: reactionMap[reactionKind].Count, 123 Users: reactionMap[reactionKind].Users, 124 IsReacted: false, 125 }) 126 127 return 128 } 129}