From b60ad5be27abe060c52d4ff2f796ea12162ebf93 Mon Sep 17 00:00:00 2001 From: Vaibhav Yenamandra <3663231+envp@users.noreply.github.com> Date: Fri, 7 Apr 2023 22:57:15 -0400 Subject: [PATCH 1/3] current: Add function `list_gists_for_authenticated_user` Add a new function to `CurrentAuthHandler` that allows paginating through the authenticated user's gists. --- src/api/current.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/src/api/current.rs b/src/api/current.rs index 7e292790..45ecc6ab 100644 --- a/src/api/current.rs +++ b/src/api/current.rs @@ -1,7 +1,7 @@ //! Get data about the currently authenticated user. use crate::{ - models::{self, Repository}, + models::{self, gists::Gist, Repository}, Octocrab, Page, Result, }; use chrono::{DateTime, Utc}; @@ -79,6 +79,45 @@ impl<'octo> CurrentAuthHandler<'octo> { pub fn list_repos_for_authenticated_user(&self) -> ListReposForAuthenticatedUserBuilder<'octo> { ListReposForAuthenticatedUserBuilder::new(self.crab) } + + /// List gists for the current authenticated user. + /// + /// # Examples + /// + /// 1. The following snippet retrieves the most recent gist: + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// octocrab::instance() + /// .current() + /// .list_gists_for_authenticated_user() + /// .per_page(1) + /// .page(1) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// 2. This retrieves the first 100 gists, which is maximum number that + /// can be fetched in a single page: + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// octocrab::instance() + /// .current() + /// .list_gists_for_authenticated_user() + /// .per_page(100) + /// .page(1) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + /// + /// [See the GitHub API documentation](https://docs.github.com/en/rest/gists/gists?apiVersion=latest#list-gists-for-the-authenticated-user) + pub fn list_gists_for_authenticated_user(&self) -> ListGistsForAuthenticatedUserBuilder<'octo> { + // self.crab.get("/gists", None::<&()>).await + ListGistsForAuthenticatedUserBuilder::new(self.crab) + } } /// A builder pattern struct for listing starred repositories. @@ -289,3 +328,66 @@ impl<'octo> ListReposForAuthenticatedUserBuilder<'octo> { self.crab.get("/user/repos", (&self).into()).await } } + +/// A builder struct for initializing query parameters for use with the +/// `/gists` endpoint. +/// +/// Created by: [`CurrentAuthHandler::list_gists_for_authenticated_user`]. +/// +/// [`CurrentAuthHandler::list_repos_starred_by_authenticated_user`]: ./struct.CurrentAuthHandler.html#method.list_gists_for_authenticated_user +#[derive(serde::Serialize)] +pub struct ListGistsForAuthenticatedUserBuilder<'octo> { + /// Client under use for building the request. + #[serde(skip)] + crab: &'octo Octocrab, + + /// Only show gists that were updated after the given ISO 8601 UTC timestamp. + #[serde(skip_serializing_if = "Option::is_none")] + since: Option>, + + /// The number of results per page (max 100). + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + + /// Page number of the results to fetch, starting at 1. + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, +} + +impl<'octo> ListGistsForAuthenticatedUserBuilder<'octo> { + /// Create a new builder using the given client and default options as + /// described in GitHub's API docs. + /// + /// [See the GitHub API documentation](https://docs.github.com/en/rest/gists/gists?apiVersion=latest#list-gists-for-the-authenticated-user) + pub fn new(crab: &'octo Octocrab) -> Self { + Self { + crab, + since: None, + per_page: None, + page: None, + } + } + + /// Only show gists that were updated after the given ISO 8601 UTC timestamp. + pub fn since(mut self, last_updated: DateTime) -> Self { + self.since = Some(last_updated); + self + } + + /// The number of results per page (max 100). + pub fn per_page(mut self, count: u8) -> Self { + self.per_page = Some(count); + self + } + + /// Page number of the results to fetch, starting at 1. + pub fn page(mut self, page_num: u32) -> Self { + self.page = Some(page_num); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result> { + self.crab.get("/gists", Some(&self)).await + } +} From fe5c096d683d70095e85292fa6a17061a55f0549 Mon Sep 17 00:00:00 2001 From: Vaibhav Yenamandra <3663231+envp@users.noreply.github.com> Date: Fri, 7 Apr 2023 23:08:47 -0400 Subject: [PATCH 2/3] gists: bugfix: `content`, `truncated` are optional The aren't always sent as a part of the response, per the [schema][1]. [1]: https://docs.github.com/en/rest/gists/gists?apiVersion=latest#list-gists-for-the-authenticated-user --- src/models/gists.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/models/gists.rs b/src/models/gists.rs index 76262171..edf7f636 100644 --- a/src/models/gists.rs +++ b/src/models/gists.rs @@ -23,13 +23,13 @@ pub struct Gist { #[non_exhaustive] #[derive(Debug, Deserialize)] pub struct GistFile { - pub content: String, + pub content: Option, pub filename: String, pub language: Option, pub r#type: String, pub raw_url: Url, pub size: u64, - pub truncated: bool, + pub truncated: Option, } #[non_exhaustive] From 75fb7b5263b8495dbbe3972989bc67b1b47633cf Mon Sep 17 00:00:00 2001 From: Vaibhav Yenamandra <3663231+envp@users.noreply.github.com> Date: Fri, 7 Apr 2023 23:11:58 -0400 Subject: [PATCH 3/3] examples: Add example 'list_gists_for_token_holder' This example demonstrates using the gists API to paginate through the gists of the authenticated user and printing them in a tabular form. --- examples/list_gists_for_token_holder.rs | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 examples/list_gists_for_token_holder.rs diff --git a/examples/list_gists_for_token_holder.rs b/examples/list_gists_for_token_holder.rs new file mode 100644 index 00000000..daf6f966 --- /dev/null +++ b/examples/list_gists_for_token_holder.rs @@ -0,0 +1,42 @@ +use octocrab::Octocrab; + +#[tokio::main] +async fn main() -> octocrab::Result<()> { + let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); + + let octocrab = Octocrab::builder().personal_token(token).build()?; + let current_user_name = octocrab.current().user().await?.login; + let mut current_gist_page = octocrab + .current() + .list_gists_for_authenticated_user() + .per_page(1) + .send() + .await?; + + let mut gists = current_gist_page.take_items(); + while let Ok(Some(mut new_page)) = octocrab.get_page(¤t_gist_page.next).await { + gists.extend(new_page.take_items()); + current_gist_page = new_page; + } + + println!( + "User '{username}' has {count} gists:", + username = current_user_name, + count = gists.len() + ); + println!("id | url | [files...] | description"); + for gist in gists { + println!( + "{id} | {url} | [{files}] | {description}", + id = gist.id, + url = gist.html_url.to_string(), + files = gist.files.into_keys().collect::>().join(", "), + description = gist + .description + .unwrap_or("".into()) + .escape_default(), + ); + } + + Ok(()) +}