Skip to content

Commit

Permalink
gists+examples: Extend GistsHandler through star(...), `unstar(..…
Browse files Browse the repository at this point in the history
….)`, `is_starred(...)` (#330)

* gists+examples: Extend `GistsHandler` by adding `star(...)`

The `star(...)` function takes a `gist_id` and 'stars' it. Has no
observable effect on the gist if it is already starred.

* gists+examples: Extend `GistsHandler` by adding `unstar(...)`

The `unstar(...)` function takes a `gist_id` and removes a 'star' from
it. Has no observable effect on the gist if it is not starred.

* examples: Rename star_a_gist -> star_unstar_a_gist

* gists: Add function to check if a gist is starred

Create `GistsHandler::is_starred`. This acceepts a `gist_id` and
returns if a gist is starred.

* examples: Extend the `star_unstar_a_gist` example

This fully demonstrates how to:

- Check if a gist is starred
- Star a gist
- Unstar a gist
  • Loading branch information
envp authored Apr 10, 2023
1 parent 775936c commit 756784d
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 0 deletions.
72 changes: 72 additions & 0 deletions examples/star_unstar_a_gist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use octocrab::Octocrab;

struct ProgramArguments {
gist_id: String,
star: bool,
}

/// Rudimentary CLI interface. Tries to be nice to the caller without too
/// much bloat on the example.
fn parse_argv_or_exit() -> ProgramArguments {
const USAGE: &str = r#"Usage:
<program> (--star | --unstar) GIST_ID"#;
let star = if let Some(param) = std::env::args().nth(1) {
if param == "--star" {
true
} else if param == "--unstar" {
false
} else {
eprintln!("error: Need (--star | --unstar) as first argument.");
eprintln!("{}", USAGE);
std::process::exit(1);
}
} else {
eprintln!("error: Need (--star | --unstar) as first argument.");
eprintln!("{}", USAGE);
std::process::exit(1);
};

let gist_id = if let Some(gist_id) = std::env::args().nth(2) {
gist_id
} else {
eprintln!("error: Need GIST_ID as second argument.");
eprintln!("{}", USAGE);
std::process::exit(1);
};
ProgramArguments { gist_id, star }
}

/// This example tries to demonstrate interacting with a gists' 'stars'.
/// It does so by making a program that takes two CLI arguments:
///
/// 1) `--star` or `--unstar` to either star/unstar a gist
/// 2) A `GIST_ID` to identify which gist to operate on
///
/// The example will check if a gist is already starred / unstarred, before
/// performing the operation.
#[tokio::main]
async fn main() -> octocrab::Result<()> {
let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required");
let args = parse_argv_or_exit();
let octocrab = Octocrab::builder().personal_token(token).build()?;
let gists_handler = octocrab.gists();
let is_starred = gists_handler.is_starred(&args.gist_id).await?;

if is_starred && args.star {
println!("{gist_id} is already starred.", gist_id = &args.gist_id);
return Ok(());
}
if !is_starred && !args.star {
println!("{gist_id} is already un-starred.", gist_id = &args.gist_id);
return Ok(());
}

if args.star {
gists_handler.star(&args.gist_id).await?;
println!("Starred {gist_id}.", gist_id = &args.gist_id)
} else {
gists_handler.unstar(&args.gist_id).await?;
println!("Un-starred {gist_id}.", gist_id = &args.gist_id)
}
Ok(())
}
74 changes: 74 additions & 0 deletions src/api/gists.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The gist API
mod list_commits;

use http::StatusCode;
use serde::Serialize;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -122,6 +123,79 @@ impl<'octo> GistsHandler<'octo> {
pub fn list_commits(&self, gist_id: impl Into<String>) -> list_commits::ListCommitsBuilder {
list_commits::ListCommitsBuilder::new(self, gist_id.into())
}

/// Check if the given is gist is already starred by the authenticated user.
/// See [GitHub API Documentation][docs] more information about response
/// data.
///
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// let is_starred: bool = octocrab::instance()
/// .gists()
/// .is_starred("00000000000000000000000000000000")
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// [docs]: https://docs.github.com/en/rest/gists/gists?apiVersion=2022-11-28#check-if-a-gist-is-starred
pub async fn is_starred(&self, gist_id: impl AsRef<str>) -> Result<bool> {
let gist_id = gist_id.as_ref();
let response = self
.crab
._get(format!("/gists/{gist_id}/star"))
.await?;
// Gist API returns 204 (NO CONTENT) if a gist is starred
Ok(response.status() == StatusCode::NO_CONTENT)
}

/// Star the given gist. See [GitHub API Documentation][docs] more
/// information about response data.
///
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// octocrab::instance()
/// .gists()
/// .star("00000000000000000000000000000000")
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// [docs]: https://docs.github.com/en/rest/gists/gists?apiVersion=2022-11-28#star-a-gist
pub async fn star(&self, gist_id: impl AsRef<str>) -> Result<()> {
let gist_id = gist_id.as_ref();
// PUT here returns an empty body, ignore it since it doesn't make
// sense to deserialize it as JSON.
self.crab
._put(format!("/gists/{gist_id}/star"), None::<&()>)
.await
.map(|_| ())
}

/// Unstar the given gist. See [GitHub API Documentation][docs] more
/// information about response data.
///
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// octocrab::instance()
/// .gists()
/// .unstar("00000000000000000000000000000000")
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// [docs]: https://docs.github.com/en/rest/gists/gists?apiVersion=2022-11-28#unstar-a-gist
pub async fn unstar(&self, gist_id: impl AsRef<str>) -> Result<()> {
let gist_id = gist_id.as_ref();
// DELETE here returns an empty body, ignore it since it doesn't make
// sense to deserialize it as JSON.
self.crab
._delete(format!("/gists/{gist_id}/star"), None::<&()>)
.await
.map(|_| ())
}
}

#[derive(Debug)]
Expand Down

0 comments on commit 756784d

Please sign in to comment.