Monorepo for Tangled tangled.org
2

Configure Feed

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

at icy/yovxsu 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.FormValue("subject-uri") 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 // override collection NSID to new one 35 subjectUri = models.NormalizeReactionSubject(subjectUri) 36 37 reactionKind, ok := models.ParseReactionKind(r.URL.Query().Get("kind")) 38 if !ok { 39 l.Warn("invalid reaction kind", "kind", r.URL.Query().Get("kind")) 40 return 41 } 42 43 client, err := s.oauth.AuthorizedClient(r) 44 if err != nil { 45 l.Error("failed to authorize client", "err", err) 46 return 47 } 48 49 switch r.Method { 50 case http.MethodPost: 51 createdAt := time.Now() 52 rkey := tid.TID() 53 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 54 Collection: tangled.FeedReactionNSID, 55 Repo: currentUser.Did, 56 Rkey: rkey, 57 Record: &lexutil.LexiconTypeDecoder{ 58 Val: &tangled.FeedReaction{ 59 Subject: subjectUri.String(), 60 Reaction: reactionKind.String(), 61 CreatedAt: createdAt.Format(time.RFC3339), 62 }, 63 }, 64 }) 65 if err != nil { 66 l.Error("failed to create atproto record", "err", err) 67 return 68 } 69 70 err = db.AddReaction(s.db, currentUser.Did, subjectUri, reactionKind, rkey, createdAt) 71 if err != nil { 72 l.Error("failed to react", "err", err) 73 return 74 } 75 76 reactionMap, err := db.GetReactionMap(s.db, 20, subjectUri) 77 if err != nil { 78 l.Error("failed to get reactions", "subjectUri", subjectUri, "err", err) 79 } 80 81 l.Info("created atproto record", "uri", resp.Uri) 82 83 s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{ 84 Kind: reactionKind, 85 Count: reactionMap[reactionKind].Count, 86 Users: reactionMap[reactionKind].Users, 87 IsReacted: true, 88 }) 89 90 return 91 case http.MethodDelete: 92 reaction, err := db.GetReaction(s.db, currentUser.Did, subjectUri, reactionKind) 93 if err != nil { 94 l.Error("failed to get reaction relationship", "did", currentUser.Did, "subjectUri", subjectUri, "err", err) 95 return 96 } 97 98 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 99 Collection: tangled.FeedReactionNSID, 100 Repo: currentUser.Did, 101 Rkey: reaction.Rkey, 102 }) 103 104 if err != nil { 105 l.Error("failed to remove reaction", "err", err) 106 return 107 } 108 109 err = db.DeleteReactionByRkey(s.db, currentUser.Did, reaction.Rkey) 110 if err != nil { 111 l.Warn("failed to delete reaction from DB", "err", err) 112 // this is not an issue, the firehose event might have already done this 113 } 114 115 reactionMap, err := db.GetReactionMap(s.db, 20, subjectUri) 116 if err != nil { 117 l.Error("failed to get reactions", "subjectUri", subjectUri, "err", err) 118 return 119 } 120 121 s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{ 122 Kind: reactionKind, 123 Count: reactionMap[reactionKind].Count, 124 Users: reactionMap[reactionKind].Users, 125 IsReacted: false, 126 }) 127 128 return 129 } 130}