1package state
2
3import (
4 "log"
5 "net/http"
6 "time"
7
8 comatproto "github.com/bluesky-social/indigo/api/atproto"
9 "github.com/bluesky-social/indigo/atproto/syntax"
10 lexutil "github.com/bluesky-social/indigo/lex/util"
11 "tangled.sh/tangled.sh/core/api/tangled"
12 "tangled.sh/tangled.sh/core/appview/db"
13 "tangled.sh/tangled.sh/core/appview/pages"
14 "tangled.sh/tangled.sh/core/tid"
15)
16
17func (s *State) Star(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 subjectUri, err := syntax.ParseATURI(subject)
27 if err != nil {
28 log.Println("invalid form")
29 return
30 }
31
32 client, err := s.oauth.AuthorizedClient(r)
33 if err != nil {
34 log.Println("failed to authorize client", err)
35 return
36 }
37
38 switch r.Method {
39 case http.MethodPost:
40 createdAt := time.Now().Format(time.RFC3339)
41 rkey := tid.TID()
42 resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
43 Collection: tangled.FeedStarNSID,
44 Repo: currentUser.Did,
45 Rkey: rkey,
46 Record: &lexutil.LexiconTypeDecoder{
47 Val: &tangled.FeedStar{
48 Subject: subjectUri.String(),
49 CreatedAt: createdAt,
50 }},
51 })
52 if err != nil {
53 log.Println("failed to create atproto record", err)
54 return
55 }
56 log.Println("created atproto record: ", resp.Uri)
57
58 star := &db.Star{
59 StarredByDid: currentUser.Did,
60 RepoAt: subjectUri,
61 Rkey: rkey,
62 }
63
64 err = db.AddStar(s.db, star)
65 if err != nil {
66 log.Println("failed to star", err)
67 return
68 }
69
70 starCount, err := db.GetStarCount(s.db, subjectUri)
71 if err != nil {
72 log.Println("failed to get star count for ", subjectUri)
73 }
74
75 s.notifier.NewStar(r.Context(), star)
76
77 s.pages.RepoStarFragment(w, pages.RepoStarFragmentParams{
78 IsStarred: true,
79 RepoAt: subjectUri,
80 Stats: db.RepoStats{
81 StarCount: starCount,
82 },
83 })
84
85 return
86 case http.MethodDelete:
87 // find the record in the db
88 star, err := db.GetStar(s.db, currentUser.Did, subjectUri)
89 if err != nil {
90 log.Println("failed to get star relationship")
91 return
92 }
93
94 _, err = client.RepoDeleteRecord(r.Context(), &comatproto.RepoDeleteRecord_Input{
95 Collection: tangled.FeedStarNSID,
96 Repo: currentUser.Did,
97 Rkey: star.Rkey,
98 })
99
100 if err != nil {
101 log.Println("failed to unstar")
102 return
103 }
104
105 err = db.DeleteStarByRkey(s.db, currentUser.Did, star.Rkey)
106 if err != nil {
107 log.Println("failed to delete star from DB")
108 // this is not an issue, the firehose event might have already done this
109 }
110
111 starCount, err := db.GetStarCount(s.db, subjectUri)
112 if err != nil {
113 log.Println("failed to get star count for ", subjectUri)
114 return
115 }
116
117 s.notifier.DeleteStar(r.Context(), star)
118
119 s.pages.RepoStarFragment(w, pages.RepoStarFragmentParams{
120 IsStarred: false,
121 RepoAt: subjectUri,
122 Stats: db.RepoStats{
123 StarCount: starCount,
124 },
125 })
126
127 return
128 }
129
130}