1package state
2
3import (
4 "fmt"
5 "log"
6 "net/http"
7 "time"
8
9 comatproto "github.com/bluesky-social/indigo/api/atproto"
10 lexutil "github.com/bluesky-social/indigo/lex/util"
11 tangled "github.com/sotangled/tangled/api/tangled"
12 "github.com/sotangled/tangled/appview/db"
13)
14
15func (s *State) Follow(w http.ResponseWriter, r *http.Request) {
16 currentUser := s.auth.GetUser(r)
17
18 subject := r.URL.Query().Get("subject")
19 if subject == "" {
20 log.Println("invalid form")
21 return
22 }
23
24 subjectIdent, err := s.resolver.ResolveIdent(r.Context(), subject)
25 if err != nil {
26 log.Println("failed to follow, invalid did")
27 }
28
29 if currentUser.Did == subjectIdent.DID.String() {
30 log.Println("cant follow or unfollow yourself")
31 return
32 }
33
34 client, _ := s.auth.AuthorizedClient(r)
35
36 switch r.Method {
37 case http.MethodPost:
38 createdAt := time.Now().Format(time.RFC3339)
39 rkey := s.TID()
40 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
41 Collection: tangled.GraphFollowNSID,
42 Repo: currentUser.Did,
43 Rkey: rkey,
44 Record: &lexutil.LexiconTypeDecoder{
45 Val: &tangled.GraphFollow{
46 Subject: subjectIdent.DID.String(),
47 CreatedAt: createdAt,
48 }},
49 })
50 if err != nil {
51 log.Println("failed to create atproto record", err)
52 return
53 }
54
55 err = db.AddFollow(s.db, currentUser.Did, subjectIdent.DID.String(), rkey)
56 if err != nil {
57 log.Println("failed to follow", err)
58 return
59 }
60
61 log.Println("created atproto record: ", resp.Uri)
62
63 w.Write([]byte(fmt.Sprintf(`
64 <button id="followBtn"
65 class="btn mt-2 w-full"
66 hx-delete="/follow?subject=%s"
67 hx-trigger="click"
68 hx-target="#followBtn"
69 hx-swap="outerHTML">
70 Unfollow
71 </button>
72 `, subjectIdent.DID.String())))
73
74 return
75 case http.MethodDelete:
76 // find the record in the db
77 follow, err := db.GetFollow(s.db, currentUser.Did, subjectIdent.DID.String())
78 if err != nil {
79 log.Println("failed to get follow relationship")
80 return
81 }
82
83 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{
84 Collection: tangled.GraphFollowNSID,
85 Repo: currentUser.Did,
86 Rkey: follow.RKey,
87 })
88
89 if err != nil {
90 log.Println("failed to unfollow")
91 return
92 }
93
94 err = db.DeleteFollow(s.db, currentUser.Did, subjectIdent.DID.String())
95 if err != nil {
96 log.Println("failed to delete follow from DB")
97 // this is not an issue, the firehose event might have already done this
98 }
99
100 w.Write([]byte(fmt.Sprintf(`
101 <button id="followBtn"
102 class="btn mt-2 w-full"
103 hx-post="/follow?subject=%s"
104 hx-trigger="click"
105 hx-target="#followBtn"
106 hx-swap="outerHTML">
107 Follow
108 </button>
109 `, subjectIdent.DID.String())))
110 return
111 }
112
113}