jinxapi_github/v1_1_4/request/
pulls_create_review_comment.rs

1//! Create a review comment for a pull request
2//! 
3//! Creates a review comment in the pull request diff. To add a regular comment to a pull request timeline, see "[Create an issue comment](https://docs.github.com/rest/reference/issues#create-an-issue-comment)." We recommend creating a review comment using `line`, `side`, and optionally `start_line` and `start_side` if your comment applies to more than one line in the pull request diff.
4//! 
5//! The `position` parameter is deprecated. If you use `position`, the `line`, `side`, `start_line`, and `start_side` parameters are not required.
6//! 
7//! **Note:** The position value equals the number of lines down from the first "@@" hunk header in the file you want to add a comment. The line just below the "@@" line is position 1, the next line is position 2, and so on. The position in the diff continues to increase through lines of whitespace and additional hunks until the beginning of a new file.
8//! 
9//! This endpoint triggers [notifications](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/about-notifications). Creating content too quickly using this endpoint may result in secondary rate limiting. See "[Secondary rate limits](https://docs.github.com/rest/overview/resources-in-the-rest-api#secondary-rate-limits)" and "[Dealing with secondary rate limits](https://docs.github.com/rest/guides/best-practices-for-integrators#dealing-with-secondary-rate-limits)" for details.
10//! 
11//! [API method documentation](https://docs.github.com/rest/reference/pulls#create-a-review-comment-for-a-pull-request)
12
13pub struct Content<Body>
14{
15    body: Body,
16    content_type_value: Option<::std::borrow::Cow<'static, [u8]>>,
17}
18
19impl<Body> Content<Body> {
20    pub fn new(body: Body) -> Self {
21        Self { body, content_type_value: None }
22    }
23
24    #[must_use]
25    pub fn with_content_type(mut self, content_type: impl Into<::std::borrow::Cow<'static, [u8]>>) -> Self {
26        self.content_type_value = Some(content_type.into());
27        self
28    }
29
30    fn content_type(&self) -> Option<&[u8]> {
31        self.content_type_value.as_deref()
32    }
33
34    fn into_body(self) -> Body {
35        self.body
36    }
37}
38
39fn url_string(
40    base_url: &str,
41    p_owner: &str,
42    p_repo: &str,
43    p_pull_number: i64,
44) -> Result<String, crate::v1_1_4::ApiError> {
45    let trimmed = if base_url.is_empty() {
46        "https://api.github.com"
47    } else {
48        base_url.trim_end_matches('/')
49    };
50    let mut url = String::with_capacity(trimmed.len() + 43);
51    url.push_str(trimmed);
52    url.push_str("/repos/");
53    ::querylizer::Simple::extend(&mut url, &p_owner, false, &::querylizer::encode_path)?;
54    url.push('/');
55    ::querylizer::Simple::extend(&mut url, &p_repo, false, &::querylizer::encode_path)?;
56    url.push_str("/pulls/");
57    ::querylizer::Simple::extend(&mut url, &p_pull_number, false, &::querylizer::encode_path)?;
58    url.push_str("/comments");
59    Ok(url)
60}
61
62#[cfg(feature = "hyper")]
63pub fn http_builder(
64    base_url: &str,
65    p_owner: &str,
66    p_repo: &str,
67    p_pull_number: i64,
68    h_user_agent: &str,
69    h_accept: ::std::option::Option<&str>,
70) -> Result<::http::request::Builder, crate::v1_1_4::ApiError> {
71    let url = url_string(
72        base_url,
73        p_owner,
74        p_repo,
75        p_pull_number,
76    )?;
77    let mut builder = ::http::request::Request::post(url);
78    builder = builder.header(
79        "User-Agent",
80        &::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?
81    );
82    if let Some(value) = &h_accept {
83        builder = builder.header(
84            "Accept",
85            &::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?
86        );
87    }
88    Ok(builder)
89}
90
91#[cfg(feature = "hyper")]
92pub fn hyper_request(
93    mut builder: ::http::request::Builder,
94    content: Content<::hyper::Body>,
95) -> Result<::http::request::Request<::hyper::Body>, crate::v1_1_4::ApiError>
96{
97    if let Some(content_type) = content.content_type() {
98        builder = builder.header(::http::header::CONTENT_TYPE, content_type);
99    }
100    Ok(builder.body(content.into_body())?)
101}
102
103#[cfg(feature = "hyper")]
104impl From<::hyper::Body> for Content<::hyper::Body> {
105    fn from(body: ::hyper::Body) -> Self {
106        Self::new(body)
107    }
108}
109
110#[cfg(feature = "reqwest")]
111pub fn reqwest_builder(
112    base_url: &str,
113    p_owner: &str,
114    p_repo: &str,
115    p_pull_number: i64,
116    h_user_agent: &str,
117    h_accept: ::std::option::Option<&str>,
118) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
119    let url = url_string(
120        base_url,
121        p_owner,
122        p_repo,
123        p_pull_number,
124    )?;
125    let reqwest_url = ::reqwest::Url::parse(&url)?;
126    let mut request = ::reqwest::Request::new(::reqwest::Method::POST, reqwest_url);
127    let headers = request.headers_mut();
128    headers.append(
129        "User-Agent",
130        ::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
131    );
132    if let Some(value) = &h_accept {
133        headers.append(
134            "Accept",
135            ::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
136        );
137    }
138    Ok(request)
139}
140
141#[cfg(feature = "reqwest")]
142pub fn reqwest_request(
143    mut builder: ::reqwest::Request,
144    content: Content<::reqwest::Body>,
145) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
146    if let Some(content_type) = content.content_type() {
147        builder.headers_mut().append(
148            ::reqwest::header::HeaderName::from_static("content-type"),
149            ::reqwest::header::HeaderValue::try_from(content_type)?,
150        );
151    }
152    *builder.body_mut() = Some(content.into_body());
153    Ok(builder)
154}
155
156#[cfg(feature = "reqwest")]
157impl From<::reqwest::Body> for Content<::reqwest::Body> {
158    fn from(body: ::reqwest::Body) -> Self {
159        Self::new(body)
160    }
161}
162
163#[cfg(feature = "reqwest-blocking")]
164pub fn reqwest_blocking_builder(
165    base_url: &str,
166    p_owner: &str,
167    p_repo: &str,
168    p_pull_number: i64,
169    h_user_agent: &str,
170    h_accept: ::std::option::Option<&str>,
171) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
172    let url = url_string(
173        base_url,
174        p_owner,
175        p_repo,
176        p_pull_number,
177    )?;
178    let reqwest_url = ::reqwest::Url::parse(&url)?;
179    let mut request = ::reqwest::blocking::Request::new(::reqwest::Method::POST, reqwest_url);
180    let headers = request.headers_mut();
181    headers.append(
182        "User-Agent",
183        ::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
184    );
185    if let Some(value) = &h_accept {
186        headers.append(
187            "Accept",
188            ::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
189        );
190    }
191    Ok(request)
192}
193
194#[cfg(feature = "reqwest-blocking")]
195pub fn reqwest_blocking_request(
196    mut builder: ::reqwest::blocking::Request,
197    content: Content<::reqwest::blocking::Body>,
198) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
199    if let Some(content_type) = content.content_type() {
200        builder.headers_mut().append(
201            ::reqwest::header::HeaderName::from_static("content-type"),
202            ::reqwest::header::HeaderValue::try_from(content_type)?,
203        );
204    }
205    *builder.body_mut() = Some(content.into_body());
206    Ok(builder)
207}
208
209#[cfg(feature = "reqwest-blocking")]
210impl From<::reqwest::blocking::Body> for Content<::reqwest::blocking::Body> {
211    fn from(body: ::reqwest::blocking::Body) -> Self {
212        Self::new(body)
213    }
214}
215
216/// Types for body parameter in [`super::pulls_create_review_comment`]
217pub mod body {
218    #[allow(non_snake_case)]
219    #[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
220    pub struct Json<'a> {
221        /// The text of the review comment.
222        pub body: ::std::borrow::Cow<'a, str>,
223
224        /// The SHA of the commit needing a comment. Not using the latest commit SHA may render your comment outdated if a subsequent commit modifies the line you specify as the `position`.
225        #[serde(skip_serializing_if = "Option::is_none", default)]
226        pub commit_id: ::std::option::Option<::std::borrow::Cow<'a, str>>,
227
228        /// The relative path to the file that necessitates a comment.
229        #[serde(skip_serializing_if = "Option::is_none", default)]
230        pub path: ::std::option::Option<::std::borrow::Cow<'a, str>>,
231
232        /// **This paramter is deprecated. Use `line` instead**. The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. For help finding the position value, read the note above.
233        #[serde(skip_serializing_if = "Option::is_none", default)]
234        pub position: ::std::option::Option<i64>,
235
236        /// In a split diff view, the side of the diff that the pull request's changes appear on. Can be `LEFT` or `RIGHT`. Use `LEFT` for deletions that appear in red. Use `RIGHT` for additions that appear in green or unchanged lines that appear in white and are shown for context. For a multi-line comment, side represents whether the last line of the comment range is a deletion or addition. For more information, see "[Diff view options](https://docs.github.com/en/articles/about-comparing-branches-in-pull-requests#diff-view-options)" in the GitHub Help documentation.
237        #[serde(skip_serializing_if = "Option::is_none", default)]
238        pub side: ::std::option::Option<::std::borrow::Cow<'a, str>>,
239
240        /// The line of the blob in the pull request diff that the comment applies to. For a multi-line comment, the last line of the range that your comment applies to.
241        #[serde(skip_serializing_if = "Option::is_none", default)]
242        pub line: ::std::option::Option<i64>,
243
244        /// **Required when using multi-line comments unless using `in_reply_to`**. The `start_line` is the first line in the pull request diff that your multi-line comment applies to. To learn more about multi-line comments, see "[Commenting on a pull request](https://docs.github.com/en/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)" in the GitHub Help documentation.
245        #[serde(skip_serializing_if = "Option::is_none", default)]
246        pub start_line: ::std::option::Option<i64>,
247
248        /// **Required when using multi-line comments unless using `in_reply_to`**. The `start_side` is the starting side of the diff that the comment applies to. Can be `LEFT` or `RIGHT`. To learn more about multi-line comments, see "[Commenting on a pull request](https://docs.github.com/en/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)" in the GitHub Help documentation. See `side` in this table for additional context.
249        #[serde(skip_serializing_if = "Option::is_none", default)]
250        pub start_side: ::std::option::Option<::std::borrow::Cow<'a, str>>,
251
252        /// The ID of the review comment to reply to. To find the ID of a review comment with ["List review comments on a pull request"](#list-review-comments-on-a-pull-request). When specified, all parameters other than `body` in the request body are ignored.
253        /// 
254        /// # Example
255        /// 
256        /// ```json
257        /// 2
258        /// ```
259        #[serde(skip_serializing_if = "Option::is_none", default)]
260        pub in_reply_to: ::std::option::Option<i64>,
261
262        #[serde(flatten)]
263        pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
264    }
265
266    #[cfg(feature = "hyper")]
267    impl<'a> TryFrom<&Json<'a>> for super::Content<::hyper::Body> {
268        type Error = crate::v1_1_4::ApiError;
269
270        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
271            Ok(
272                Self::new(::serde_json::to_vec(value)?.into())
273                .with_content_type(&b"application/json"[..])
274            )
275        }
276    }
277
278    #[cfg(feature = "reqwest")]
279    impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::Body> {
280        type Error = crate::v1_1_4::ApiError;
281
282        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
283            Ok(
284                Self::new(::serde_json::to_vec(value)?.into())
285                .with_content_type(&b"application/json"[..])
286            )
287        }
288    }
289
290    #[cfg(feature = "reqwest-blocking")]
291    impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::blocking::Body> {
292        type Error = crate::v1_1_4::ApiError;
293
294        fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
295            Ok(
296                Self::new(::serde_json::to_vec(value)?.into())
297                .with_content_type(&b"application/json"[..])
298            )
299        }
300    }
301}