add unfollow bits
MODIFIED
appview/db/db.go
MODIFIED
appview/db/db.go
@@ -43,6 +43,7 @@ );create table if not exists follows (user_did text not null,subject_did text not null,+ at_uri text not null,followed_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),primary key (user_did, subject_did),check (user_did <> subject_did)
MODIFIED
appview/db/follow.go
MODIFIED
appview/db/follow.go
@@ -1,7 +1,48 @@package db-func (d *DB) AddFollow(userDid, subjectDid string) error {- query := `insert into follows (user_did, subject_did) values (?, ?)`- _, err := d.db.Exec(query, userDid, subjectDid)+import (+ "log"+ "time"+)++type Follow struct {+ UserDid string+ SubjectDid string+ FollowedAt *time.Time+ AtUri string+}++func (d *DB) AddFollow(userDid, subjectDid, atUri string) error {+ query := `insert into follows (user_did, subject_did, at_uri) values (?, ?, ?)`+ _, err := d.db.Exec(query, userDid, subjectDid, atUri)+ return err+}++// Get a follow record+func (d *DB) GetFollow(userDid, subjectDid string) (*Follow, error) {+ query := `select user_did, subject_did, followed_at, at_uri from follows where user_did = ? and subject_did = ?`+ row := d.db.QueryRow(query, userDid, subjectDid)++ var follow Follow+ var followedAt string+ err := row.Scan(&follow.UserDid, &follow.SubjectDid, &followedAt, &follow.AtUri)+ if err != nil {+ return nil, err+ }++ followedAtTime, err := time.Parse(time.RFC3339, followedAt)+ if err != nil {+ log.Println("unable to determine followed at time")+ follow.FollowedAt = nil+ } else {+ follow.FollowedAt = &followedAtTime+ }++ return &follow, nil+}++// Get a follow record+func (d *DB) DeleteFollow(userDid, subjectDid string) error {+ _, err := d.db.Exec(`delete from follows where user_did = ? and subject_did = ?`, userDid, subjectDid)return err}
MODIFIED
appview/state/state.go
MODIFIED
appview/state/state.go
@@ -531,38 +531,87 @@ })}func (s *State) Follow(w http.ResponseWriter, r *http.Request) {- subject := r.FormValue("subject")+ currentUser := s.auth.GetUser(r)+ subject := r.URL.Query().Get("subject")if subject == "" {log.Println("invalid form")return}subjectIdent, err := s.resolver.ResolveIdent(r.Context(), subject)- currentUser := s.auth.GetUser(r)+ if err != nil {+ log.Println("failed to follow, invalid did")+ }++ if currentUser.Did == subjectIdent.DID.String() {+ log.Println("cant follow or unfollow yourself")+ return+ }client, _ := s.auth.AuthorizedClient(r)- createdAt := time.Now().Format(time.RFC3339)- resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{- Collection: tangled.GraphFollowNSID,- Repo: currentUser.Did,- Rkey: s.TID(),- Record: &lexutil.LexiconTypeDecoder{- Val: &tangled.GraphFollow{- Subject: subjectIdent.DID.String(),- CreatedAt: createdAt,- }},- })++ switch r.Method {+ case http.MethodPost:+ createdAt := time.Now().Format(time.RFC3339)+ resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{+ Collection: tangled.GraphFollowNSID,+ Repo: currentUser.Did,+ Rkey: s.TID(),+ Record: &lexutil.LexiconTypeDecoder{+ Val: &tangled.GraphFollow{+ Subject: subjectIdent.DID.String(),+ CreatedAt: createdAt,+ }},+ })+ if err != nil {+ log.Println("failed to create atproto record", err)+ return+ }++ err = s.db.AddFollow(currentUser.Did, subjectIdent.DID.String(), resp.Uri)+ if err != nil {+ log.Println("failed to follow", err)+ return+ }++ log.Println("created atproto record: ", resp.Uri)++ return+ case http.MethodDelete:+ // find the record in the db++ follow, err := s.db.GetFollow(currentUser.Did, subjectIdent.DID.String())+ if err != nil {+ log.Println("failed to get follow relationship")+ return+ }++ existingRecordUri, _ := syntax.ParseATURI(follow.AtUri)++ resp, err := comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{+ Collection: tangled.GraphFollowNSID,+ Repo: currentUser.Did,+ Rkey: existingRecordUri.RecordKey().String(),+ })++ log.Println(resp.Commit.Cid)++ if err != nil {+ log.Println("failed to unfollow")+ return+ }++ err = s.db.DeleteFollow(currentUser.Did, subjectIdent.DID.String())+ if err != nil {+ log.Println("failed to delete follow from DB")+ // this is not an issue, the firehose event might have already done this+ }- err = s.db.AddFollow(currentUser.Did, subjectIdent.DID.String())- if err != nil {- log.Println("failed to follow", err)+ w.WriteHeader(http.StatusNoContent)return}- log.Println("created atproto record: ", resp.Uri)-- return}func (s *State) Router() http.Handler {@@ -655,7 +704,10 @@ })// r.Post("/import", s.ImportRepo)})- r.With(AuthMiddleware(s)).Put("/follow", s.Follow)+ r.With(AuthMiddleware(s)).Route("/follow", func(r chi.Router) {+ r.Post("/", s.Follow)+ r.Delete("/", s.Follow)+ })r.Route("/settings", func(r chi.Router) {r.Use(AuthMiddleware(s))