forked from
tangled.org/core
Monorepo for Tangled
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 "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/orm"
15 "tangled.org/core/tid"
16)
17
18func (s *State) Star(w http.ResponseWriter, r *http.Request) {
19 l := s.logger.With("handler", "Star")
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 client, err := s.oauth.AuthorizedClient(r)
35 if err != nil {
36 l.Error("failed to authorize client", "err", err)
37 return
38 }
39
40 repoName := r.URL.Query().Get("repoName")
41
42 switch r.Method {
43 case http.MethodPost:
44 createdAt := time.Now().Format(time.RFC3339)
45 rkey := tid.TID()
46
47 subjectStr := subjectUri.String()
48 starRecord := &tangled.FeedStar{
49 CreatedAt: createdAt,
50 Subject: &subjectStr,
51 }
52 repo, err := db.GetRepo(s.db, orm.FilterEq("at_uri", subjectUri.String()))
53 if err == nil && repo.RepoDid != "" {
54 starRecord.SubjectDid = &repo.RepoDid
55 }
56
57 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
58 Collection: tangled.FeedStarNSID,
59 Repo: currentUser.Did,
60 Rkey: rkey,
61 Record: &lexutil.LexiconTypeDecoder{Val: starRecord},
62 })
63 if err != nil {
64 l.Error("failed to create atproto record", "err", err)
65 return
66 }
67 l.Info("created atproto record", "uri", resp.Uri)
68
69 star := &models.Star{
70 Did: currentUser.Did,
71 RepoAt: subjectUri,
72 Rkey: rkey,
73 }
74
75 err = db.AddStar(s.db, star)
76 if err != nil {
77 l.Error("failed to star", "err", err)
78 return
79 }
80
81 starCount, err := db.GetStarCount(s.db, subjectUri)
82 if err != nil {
83 l.Error("failed to get star count", "subjectUri", subjectUri, "err", err)
84 }
85
86 s.notifier.NewStar(r.Context(), star)
87
88 s.pages.StarBtnFragment(w, pages.StarBtnFragmentParams{
89 IsStarred: true,
90 SubjectAt: subjectUri,
91 StarCount: starCount,
92 RepoName: repoName,
93 })
94
95 return
96 case http.MethodDelete:
97 // find the record in the db
98 star, err := db.GetStar(s.db, currentUser.Did, subjectUri)
99 if err != nil {
100 l.Error("failed to get star relationship", "err", err)
101 return
102 }
103
104 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{
105 Collection: tangled.FeedStarNSID,
106 Repo: currentUser.Did,
107 Rkey: star.Rkey,
108 })
109
110 if err != nil {
111 l.Error("failed to unstar", "err", err)
112 return
113 }
114
115 err = db.DeleteStarByRkey(s.db, currentUser.Did, star.Rkey)
116 if err != nil {
117 l.Warn("failed to delete star from DB", "err", err)
118 // this is not an issue, the firehose event might have already done this
119 }
120
121 starCount, err := db.GetStarCount(s.db, subjectUri)
122 if err != nil {
123 l.Error("failed to get star count", "subjectUri", subjectUri, "err", err)
124 return
125 }
126
127 s.notifier.DeleteStar(r.Context(), star)
128
129 s.pages.StarBtnFragment(w, pages.StarBtnFragmentParams{
130 IsStarred: false,
131 SubjectAt: subjectUri,
132 StarCount: starCount,
133 RepoName: repoName,
134 })
135
136 return
137 }
138
139}