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 "github.com/posthog/posthog-go"
12 "tangled.sh/tangled.sh/core/api/tangled"
13 "tangled.sh/tangled.sh/core/appview"
14 "tangled.sh/tangled.sh/core/appview/db"
15 "tangled.sh/tangled.sh/core/appview/pages"
16)
17
18func (s *State) Star(w http.ResponseWriter, r *http.Request) {
19 currentUser := s.oauth.GetUser(r)
20
21 subject := r.URL.Query().Get("subject")
22 if subject == "" {
23 log.Println("invalid form")
24 return
25 }
26
27 subjectUri, err := syntax.ParseATURI(subject)
28 if err != nil {
29 log.Println("invalid form")
30 return
31 }
32
33 client, err := s.oauth.AuthorizedClient(r)
34 if err != nil {
35 log.Println("failed to authorize client", err)
36 return
37 }
38
39 switch r.Method {
40 case http.MethodPost:
41 createdAt := time.Now().Format(time.RFC3339)
42 rkey := appview.TID()
43 resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
44 Collection: tangled.FeedStarNSID,
45 Repo: currentUser.Did,
46 Rkey: rkey,
47 Record: &lexutil.LexiconTypeDecoder{
48 Val: &tangled.FeedStar{
49 Subject: subjectUri.String(),
50 CreatedAt: createdAt,
51 }},
52 })
53 if err != nil {
54 log.Println("failed to create atproto record", err)
55 return
56 }
57
58 err = db.AddStar(s.db, currentUser.Did, subjectUri, rkey)
59 if err != nil {
60 log.Println("failed to star", err)
61 return
62 }
63
64 starCount, err := db.GetStarCount(s.db, subjectUri)
65 if err != nil {
66 log.Println("failed to get star count for ", subjectUri)
67 }
68
69 log.Println("created atproto record: ", resp.Uri)
70
71 s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{
72 IsStarred: true,
73 RepoAt: subjectUri,
74 Stats: db.RepoStats{
75 StarCount: starCount,
76 },
77 })
78
79 if !s.config.Core.Dev {
80 err = s.posthog.Enqueue(posthog.Capture{
81 DistinctId: currentUser.Did,
82 Event: "star",
83 Properties: posthog.Properties{"repo_at": subjectUri.String()},
84 })
85 if err != nil {
86 log.Println("failed to enqueue posthog event:", err)
87 }
88 }
89
90 return
91 case http.MethodDelete:
92 // find the record in the db
93 star, err := db.GetStar(s.db, currentUser.Did, subjectUri)
94 if err != nil {
95 log.Println("failed to get star relationship")
96 return
97 }
98
99 _, err = client.RepoDeleteRecord(r.Context(), &comatproto.RepoDeleteRecord_Input{
100 Collection: tangled.FeedStarNSID,
101 Repo: currentUser.Did,
102 Rkey: star.Rkey,
103 })
104
105 if err != nil {
106 log.Println("failed to unstar")
107 return
108 }
109
110 err = db.DeleteStarByRkey(s.db, currentUser.Did, star.Rkey)
111 if err != nil {
112 log.Println("failed to delete star from DB")
113 // this is not an issue, the firehose event might have already done this
114 }
115
116 starCount, err := db.GetStarCount(s.db, subjectUri)
117 if err != nil {
118 log.Println("failed to get star count for ", subjectUri)
119 return
120 }
121
122 s.pages.RepoActionsFragment(w, pages.RepoActionsFragmentParams{
123 IsStarred: false,
124 RepoAt: subjectUri,
125 Stats: db.RepoStats{
126 StarCount: starCount,
127 },
128 })
129
130 if !s.config.Core.Dev {
131 err = s.posthog.Enqueue(posthog.Capture{
132 DistinctId: currentUser.Did,
133 Event: "unstar",
134 Properties: posthog.Properties{"repo_at": subjectUri.String()},
135 })
136 if err != nil {
137 log.Println("failed to enqueue posthog event:", err)
138 }
139 }
140
141 return
142 }
143
144}