use crate::github::error::{GitHubError, GitHubResult};
use jsonwebtoken::EncodingKey;
use octocrab::{Octocrab, models::AppId};
use std::sync::Arc;
mod issues;
mod pull_requests;
mod repositories;
mod users;
mod security;
mod releases;
mod experimental;
#[derive(Clone, Debug)]
pub struct GitHubClient {
inner: Arc<Octocrab>,
}
impl GitHubClient {
#[must_use]
pub fn builder() -> GitHubClientBuilder {
GitHubClientBuilder::new()
}
pub fn with_token(token: impl Into<String>) -> GitHubResult<Self> {
Self::builder().personal_token(token).build()
}
#[must_use]
pub fn inner(&self) -> &Arc<Octocrab> {
&self.inner
}
}
pub struct GitHubClientBuilder {
token: Option<String>,
app_auth: Option<(AppId, String)>,
base_uri: Option<String>,
}
impl GitHubClientBuilder {
#[must_use]
pub fn new() -> Self {
Self {
token: None,
app_auth: None,
base_uri: None,
}
}
pub fn personal_token(mut self, token: impl Into<String>) -> Self {
self.token = Some(token.into());
self
}
pub fn app(mut self, app_id: AppId, private_key: impl Into<String>) -> Self {
self.app_auth = Some((app_id, private_key.into()));
self
}
pub fn base_uri(mut self, uri: impl Into<String>) -> Self {
self.base_uri = Some(uri.into());
self
}
pub fn build(self) -> GitHubResult<GitHubClient> {
let mut builder = Octocrab::builder();
if let Some(token) = self.token {
builder = builder.personal_token(token);
} else if let Some((app_id, private_key)) = self.app_auth {
let key = EncodingKey::from_rsa_pem(private_key.as_bytes())
.map_err(|e| GitHubError::ClientSetup(format!("Invalid RSA key: {e}")))?;
builder = builder.app(app_id, key);
}
if let Some(uri) = self.base_uri {
builder = builder
.base_uri(&uri)
.map_err(|e| GitHubError::ClientSetup(e.to_string()))?;
}
let octocrab = builder
.build()
.map_err(|e| GitHubError::ClientSetup(e.to_string()))?;
Ok(GitHubClient {
inner: Arc::new(octocrab),
})
}
}
impl Default for GitHubClientBuilder {
fn default() -> Self {
Self::new()
}
}