Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

1package pulls 2 3import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 "time" 8 9 "tangled.org/core/api/tangled" 10 "tangled.org/core/appview/db" 11 "tangled.org/core/appview/models" 12 "tangled.org/core/appview/pages" 13 "tangled.org/core/appview/reporesolver" 14 "tangled.org/core/tid" 15 16 comatproto "github.com/bluesky-social/indigo/api/atproto" 17 lexutil "github.com/bluesky-social/indigo/lex/util" 18 "github.com/go-chi/chi/v5" 19) 20 21func (s *Pulls) PullComment(w http.ResponseWriter, r *http.Request) { 22 l := s.logger.With("handler", "PullComment") 23 24 user := s.oauth.GetMultiAccountUser(r) 25 if user != nil { 26 l = l.With("user", user.Did) 27 } 28 29 f, err := s.repoResolver.Resolve(r) 30 if err != nil { 31 l.Error("failed to get repo and knot", "err", err) 32 return 33 } 34 35 pull, ok := r.Context().Value("pull").(*models.Pull) 36 if !ok { 37 l.Error("failed to get pull") 38 s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.") 39 return 40 } 41 l = l.With("pull_id", pull.PullId, "pull_owner", pull.OwnerDid) 42 43 roundNumberStr := chi.URLParam(r, "round") 44 roundNumber, err := strconv.Atoi(roundNumberStr) 45 if err != nil || roundNumber >= len(pull.Submissions) { 46 http.Error(w, "bad round id", http.StatusBadRequest) 47 l.Error("failed to parse round id", "err", err, "round_number_str", roundNumberStr) 48 return 49 } 50 51 switch r.Method { 52 case http.MethodGet: 53 s.pages.PullNewCommentFragment(w, pages.PullNewCommentParams{ 54 LoggedInUser: user, 55 RepoInfo: s.repoResolver.GetRepoInfo(r, user), 56 Pull: pull, 57 RoundNumber: roundNumber, 58 }) 59 return 60 case http.MethodPost: 61 body := r.FormValue("body") 62 if body == "" { 63 s.pages.Notice(w, "pull", "Comment body is required") 64 return 65 } 66 67 mentions, references := s.mentionsResolver.Resolve(r.Context(), body) 68 69 // Start a transaction 70 tx, err := s.db.BeginTx(r.Context(), nil) 71 if err != nil { 72 l.Error("failed to start transaction", "err", err) 73 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 74 return 75 } 76 defer tx.Rollback() 77 78 createdAt := time.Now().Format(time.RFC3339) 79 80 client, err := s.oauth.AuthorizedClient(r) 81 if err != nil { 82 l.Error("failed to get authorized client", "err", err) 83 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 84 return 85 } 86 atResp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 87 Collection: tangled.RepoPullCommentNSID, 88 Repo: user.Did, 89 Rkey: tid.TID(), 90 Record: &lexutil.LexiconTypeDecoder{ 91 Val: &tangled.RepoPullComment{ 92 Pull: pull.AtUri().String(), 93 Body: body, 94 CreatedAt: createdAt, 95 }, 96 }, 97 }) 98 if err != nil { 99 l.Error("failed to create pull comment", "err", err) 100 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 101 return 102 } 103 104 comment := &models.PullComment{ 105 OwnerDid: user.Did, 106 RepoDid: string(f.RepoDid), 107 PullId: pull.PullId, 108 Body: body, 109 CommentAt: atResp.Uri, 110 SubmissionId: pull.Submissions[roundNumber].ID, 111 Mentions: mentions, 112 References: references, 113 } 114 115 // Create the pull comment in the database with the commentAt field 116 commentId, err := db.NewPullComment(tx, comment) 117 if err != nil { 118 l.Error("failed to create pull comment in database", "err", err) 119 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 120 return 121 } 122 123 // Commit the transaction 124 if err = tx.Commit(); err != nil { 125 l.Error("failed to commit transaction", "err", err) 126 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 127 return 128 } 129 130 s.notifier.NewPullComment(r.Context(), comment, mentions) 131 132 ownerSlashRepo := reporesolver.GetBaseRepoPath(r, f) 133 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d#comment-%d", ownerSlashRepo, pull.PullId, commentId)) 134 return 135 } 136}