1// Copyright 2013 The go-github AUTHORS. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style 4// license that can be found in the LICENSE file. 5 6package github 7 8import ( 9 "context" 10 "fmt" 11 "strings" 12 "time" 13) 14 15// PullRequestComment represents a comment left on a pull request. 16type PullRequestComment struct { 17 ID *int64 `json:"id,omitempty"` 18 NodeID *string `json:"node_id,omitempty"` 19 InReplyTo *int64 `json:"in_reply_to_id,omitempty"` 20 Body *string `json:"body,omitempty"` 21 Path *string `json:"path,omitempty"` 22 DiffHunk *string `json:"diff_hunk,omitempty"` 23 PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` 24 Position *int `json:"position,omitempty"` 25 OriginalPosition *int `json:"original_position,omitempty"` 26 StartLine *int `json:"start_line,omitempty"` 27 Line *int `json:"line,omitempty"` 28 OriginalLine *int `json:"original_line,omitempty"` 29 OriginalStartLine *int `json:"original_start_line,omitempty"` 30 Side *string `json:"side,omitempty"` 31 StartSide *string `json:"start_side,omitempty"` 32 CommitID *string `json:"commit_id,omitempty"` 33 OriginalCommitID *string `json:"original_commit_id,omitempty"` 34 User *User `json:"user,omitempty"` 35 Reactions *Reactions `json:"reactions,omitempty"` 36 CreatedAt *time.Time `json:"created_at,omitempty"` 37 UpdatedAt *time.Time `json:"updated_at,omitempty"` 38 // AuthorAssociation is the comment author's relationship to the pull request's repository. 39 // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". 40 AuthorAssociation *string `json:"author_association,omitempty"` 41 URL *string `json:"url,omitempty"` 42 HTMLURL *string `json:"html_url,omitempty"` 43 PullRequestURL *string `json:"pull_request_url,omitempty"` 44} 45 46func (p PullRequestComment) String() string { 47 return Stringify(p) 48} 49 50// PullRequestListCommentsOptions specifies the optional parameters to the 51// PullRequestsService.ListComments method. 52type PullRequestListCommentsOptions struct { 53 // Sort specifies how to sort comments. Possible values are: created, updated. 54 Sort string `url:"sort,omitempty"` 55 56 // Direction in which to sort comments. Possible values are: asc, desc. 57 Direction string `url:"direction,omitempty"` 58 59 // Since filters comments by time. 60 Since time.Time `url:"since,omitempty"` 61 62 ListOptions 63} 64 65// ListComments lists all comments on the specified pull request. Specifying a 66// pull request number of 0 will return all comments on all pull requests for 67// the repository. 68// 69// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#list-review-comments-on-a-pull-request 70// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#list-review-comments-in-a-repository 71func (s *PullRequestsService) ListComments(ctx context.Context, owner, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { 72 var u string 73 if number == 0 { 74 u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) 75 } else { 76 u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) 77 } 78 u, err := addOptions(u, opts) 79 if err != nil { 80 return nil, nil, err 81 } 82 83 req, err := s.client.NewRequest("GET", u, nil) 84 if err != nil { 85 return nil, nil, err 86 } 87 88 // TODO: remove custom Accept header when this API fully launches. 89 acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} 90 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 91 92 var comments []*PullRequestComment 93 resp, err := s.client.Do(ctx, req, &comments) 94 if err != nil { 95 return nil, resp, err 96 } 97 98 return comments, resp, nil 99} 100 101// GetComment fetches the specified pull request comment. 102// 103// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#get-a-review-comment-for-a-pull-request 104func (s *PullRequestsService) GetComment(ctx context.Context, owner, repo string, commentID int64) (*PullRequestComment, *Response, error) { 105 u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) 106 req, err := s.client.NewRequest("GET", u, nil) 107 if err != nil { 108 return nil, nil, err 109 } 110 111 // TODO: remove custom Accept header when this API fully launches. 112 acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} 113 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 114 115 comment := new(PullRequestComment) 116 resp, err := s.client.Do(ctx, req, comment) 117 if err != nil { 118 return nil, resp, err 119 } 120 121 return comment, resp, nil 122} 123 124// CreateComment creates a new comment on the specified pull request. 125// 126// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#create-a-review-comment-for-a-pull-request 127func (s *PullRequestsService) CreateComment(ctx context.Context, owner, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { 128 u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) 129 req, err := s.client.NewRequest("POST", u, comment) 130 if err != nil { 131 return nil, nil, err 132 } 133 // TODO: remove custom Accept headers when their respective API fully launches. 134 acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} 135 req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) 136 137 c := new(PullRequestComment) 138 resp, err := s.client.Do(ctx, req, c) 139 if err != nil { 140 return nil, resp, err 141 } 142 143 return c, resp, nil 144} 145 146// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment. 147// 148// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#create-a-review-comment-for-a-pull-request 149func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { 150 comment := &struct { 151 Body string `json:"body,omitempty"` 152 InReplyTo int64 `json:"in_reply_to,omitempty"` 153 }{ 154 Body: body, 155 InReplyTo: commentID, 156 } 157 u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) 158 req, err := s.client.NewRequest("POST", u, comment) 159 if err != nil { 160 return nil, nil, err 161 } 162 163 c := new(PullRequestComment) 164 resp, err := s.client.Do(ctx, req, c) 165 if err != nil { 166 return nil, resp, err 167 } 168 169 return c, resp, nil 170} 171 172// EditComment updates a pull request comment. 173// A non-nil comment.Body must be provided. Other comment fields should be left nil. 174// 175// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#update-a-review-comment-for-a-pull-request 176func (s *PullRequestsService) EditComment(ctx context.Context, owner, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { 177 u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) 178 req, err := s.client.NewRequest("PATCH", u, comment) 179 if err != nil { 180 return nil, nil, err 181 } 182 183 c := new(PullRequestComment) 184 resp, err := s.client.Do(ctx, req, c) 185 if err != nil { 186 return nil, resp, err 187 } 188 189 return c, resp, nil 190} 191 192// DeleteComment deletes a pull request comment. 193// 194// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls/#delete-a-review-comment-for-a-pull-request 195func (s *PullRequestsService) DeleteComment(ctx context.Context, owner, repo string, commentID int64) (*Response, error) { 196 u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) 197 req, err := s.client.NewRequest("DELETE", u, nil) 198 if err != nil { 199 return nil, err 200 } 201 return s.client.Do(ctx, req, nil) 202} 203