diff options
author | Nathan <nathan.leniz@mongodb.com> | 2021-03-29 02:11:46 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-29 08:11:46 +0200 |
commit | 8bd8e1581214d79f056dea660674bba67172bfed (patch) | |
tree | 070bde08d5bf74ebac66d4afa1e78fdd2bd04ffa | |
parent | 88f622371425d29e18889a90430b7dcf93ea743b (diff) |
List comments for repo and pr (#82)
Adds functionality to list comments for a repo and a
pr. As part of this, a Comment model was added, as
well as a comments::Sort param enum.
-rw-r--r-- | src/api/pulls.rs | 26 | ||||
-rw-r--r-- | src/api/pulls/comment.rs | 113 | ||||
-rw-r--r-- | src/models/pulls.rs | 39 | ||||
-rw-r--r-- | src/params.rs | 11 |
4 files changed, 189 insertions, 0 deletions
diff --git a/src/api/pulls.rs b/src/api/pulls.rs index 5dcd929..24d65d2 100644 --- a/src/api/pulls.rs +++ b/src/api/pulls.rs @@ -1,5 +1,6 @@ //! The pull request API. +mod comment; mod create; mod list; mod merge; @@ -214,6 +215,31 @@ impl<'octo> PullRequestHandler<'octo> { self.http_get(url, None::<&()>).await } + /// Creates a new `ListCommentsBuilder` that can be configured to list and + /// filter `Comments` for a particular pull request. If no pull request is + /// specified, lists comments for the whole repo. + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// # let octocrab = octocrab::Octocrab::default(); + /// use octocrab::params; + /// + /// let page = octocrab.pulls("owner", "repo").list_comments(Some(5)) + /// // Optional Parameters + /// .sort(params::pulls::comments::Sort::Created) + /// .direction(params::Direction::Ascending) + /// .per_page(100) + /// .page(5u32) + /// .since(chrono::Utc::now() - chrono::Duration::days(1)) + /// // Send the request + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn list_comments(&self, pr: Option<u64>) -> comment::ListCommentsBuilder { + comment::ListCommentsBuilder::new(self, pr) + } + /// Creates a new `MergePullRequestsBuilder` that can be configured used to /// merge a pull request. /// ```no_run diff --git a/src/api/pulls/comment.rs b/src/api/pulls/comment.rs new file mode 100644 index 0000000..d639ff2 --- /dev/null +++ b/src/api/pulls/comment.rs @@ -0,0 +1,113 @@ +use super::*; + +/// A builder pattern struct for listing comments. +/// +/// created by [`PullRequestHandler::list_comments`] +/// +/// [`PullRequestHandler::list_comments`]: ./struct.PullRequestHandler.html#method.list_comments +#[derive(serde::Serialize)] +pub struct ListCommentsBuilder<'octo, 'b> { + #[serde(skip)] + handler: &'b PullRequestHandler<'octo>, + #[serde(skip)] + pr: Option<u64>, + #[serde(skip_serializing_if = "Option::is_none")] + sort: Option<crate::params::pulls::comments::Sort>, + #[serde(skip_serializing_if = "Option::is_none")] + direction: Option<crate::params::Direction>, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option<u8>, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option<u32>, + #[serde(skip_serializing_if = "Option::is_none")] + since: Option<chrono::DateTime<chrono::Utc>>, +} + +impl<'octo, 'b> ListCommentsBuilder<'octo, 'b> { + pub(crate) fn new(handler: &'b PullRequestHandler<'octo>, pr: Option<u64>) -> Self { + Self { + handler, + pr, + sort: None, + direction: None, + per_page: None, + page: None, + since: None, + } + } + + /// What to sort results by. Can be either `created` or `updated`, + pub fn sort(mut self, sort: impl Into<crate::params::pulls::comments::Sort>) -> Self { + self.sort = Some(sort.into()); + self + } + + /// The direction of the sort. Can be either ascending or descending. + /// Default: descending when sort is `created` or sort is not specified, + /// otherwise ascending sort. + pub fn direction(mut self, direction: impl Into<crate::params::Direction>) -> Self { + self.direction = Some(direction.into()); + self + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into<u8>) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into<u32>) -> Self { + self.page = Some(page.into()); + self + } + + /// Only show notifications updated after the given time. + pub fn since(mut self, since: impl Into<chrono::DateTime<chrono::Utc>>) -> Self { + self.since = Some(since.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result<Page<crate::models::pulls::Comment>> { + let url = format!( + "repos/{owner}/{repo}/pulls/{pr}comments", + owner = self.handler.owner, + repo = self.handler.repo, + pr = if let Some(pr) = self.pr { + pr.to_string() + "/" + } else { + "".into() + }, + ); + self.handler.http_get(url, Some(&self)).await + } +} + +#[cfg(test)] +mod tests { + #[tokio::test] + async fn serialize() { + let octocrab = crate::Octocrab::default(); + let handler = octocrab.pulls("rust-lang", "rust"); + let yesterday = chrono::Utc::now() - chrono::Duration::days(1); + let list = handler + .list_comments(Some(1)) + .sort(crate::params::pulls::comments::Sort::Updated) + .direction(crate::params::Direction::Ascending) + .since(yesterday) + .per_page(100) + .page(1u8); + + assert_eq!( + serde_json::to_value(list).unwrap(), + serde_json::json!({ + "sort": "updated", + "direction": "asc", + "per_page": 100, + "page": 1, + "since": yesterday + }) + ) + } +} diff --git a/src/models/pulls.rs b/src/models/pulls.rs index c9c1070..340ac99 100644 --- a/src/models/pulls.rs +++ b/src/models/pulls.rs @@ -112,6 +112,9 @@ pub struct Links { pub commits_link: Option<CommitsLink>, #[serde(skip_serializing_if = "Option::is_none")] pub statuses_link: Option<StatusesLink>, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "pull_request")] + pub pull_request_link: Option<PullRequestLink>, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -164,6 +167,11 @@ pub struct StatusesLink { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[non_exhaustive] +pub struct PullRequestLink { + pub href: Url, +} +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[non_exhaustive] pub struct Review { pub id: u64, pub node_id: String, @@ -194,6 +202,37 @@ pub enum ReviewState { Commented, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[non_exhaustive] +pub struct Comment { + pub url: Url, + pub pull_request_review_id: u64, + pub id: u64, + pub node_id: String, + pub diff_hunk: String, + pub path: String, + pub position: Option<u64>, + pub original_position: Option<u64>, + pub commit_id: String, + pub original_commit_id: String, + #[serde(default)] + pub in_reply_to_id: Option<u64>, + pub user: User, + pub body: String, + pub created_at: chrono::DateTime<chrono::Utc>, + pub updated_at: chrono::DateTime<chrono::Utc>, + pub html_url: String, + pub author_association: String, + #[serde(rename = "_links")] + pub links: Links, + pub start_line: Option<u64>, + pub original_start_line: Option<u64>, + pub start_side: Option<String>, + pub line: Option<u64>, + pub original_line: Option<u64>, + pub side: Option<String>, +} + // This is rather annoying, but Github uses both SCREAMING_SNAKE_CASE and snake_case // for the review state, it's uppercase when coming from an API request, but // lowercase when coming from a webhook payload, so we need to deserialize both, diff --git a/src/params.rs b/src/params.rs index e69fcd5..ca53ea9 100644 --- a/src/params.rs +++ b/src/params.rs @@ -220,6 +220,17 @@ pub mod pulls { Squash, Rebase, } + + pub mod comments { + /// What to sort results by. Can be either `created` or `updated`. + #[derive(Debug, Clone, Copy, serde::Serialize)] + #[serde(rename_all = "snake_case")] + #[non_exhaustive] + pub enum Sort { + Created, + Updated, + } + } } pub mod repos { |