use crate::http::request;
use anyhow::{Context as _, Result};
use hyper::{
header::HeaderValue,
header::{ACCEPT, AUTHORIZATION},
Request,
};
use serde::Deserialize;
use syn::parse::Parse;
pub(crate) fn issue_closed(input: OrgRepoIssue) -> Result<Option<String>> {
#[derive(Deserialize, Debug)]
struct Issue {
closed_at: Option<String>,
}
let OrgRepoIssue {
org,
repo,
issue: issue_number,
} = input;
let issue = request::<Issue>(github_request(
Request::builder()
.uri(format!(
"https://api.github.com/repos/{}/{}/issues/{}",
org, repo, issue_number
))
.body(())
.unwrap(),
)?)?;
if issue.closed_at.is_some() {
Ok(Some(format!(
"{}/{}#{} is closed. Time to act on this!",
org, repo, issue_number
)))
} else {
Ok(None)
}
}
#[derive(Deserialize, Debug)]
struct PullRequest {
state: String,
}
pub(crate) fn pr_closed(input: OrgRepoIssue) -> Result<Option<String>> {
let OrgRepoIssue {
org,
repo,
issue: issue_number,
} = input;
let pr = request::<PullRequest>(github_request(
Request::builder()
.uri(format!(
"https://api.github.com/repos/{}/{}/pulls/{}",
org, repo, issue_number
))
.body(())
.unwrap(),
)?)?;
if pr.state == "closed" {
Ok(Some(format!(
"{}/{}#{} is closed. Time to act on this!",
org, repo, issue_number
)))
} else {
Ok(None)
}
}
fn github_request<B>(mut request: Request<B>) -> Result<Request<B>> {
request.headers_mut().insert(
ACCEPT,
HeaderValue::from_static("application/vnd.github.v3+json"),
);
if let Some(auth_token) = auth_token() {
request.headers_mut().insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {}", auth_token))
.context("GitHub auth token contained invalid header value")?,
);
}
Ok(request)
}
fn auth_token() -> Option<String> {
std::env::var("TODO_OR_DIE_GITHUB_TOKEN")
.ok()
.or_else(|| std::env::var("GITHUB_TOKEN").ok())
}
pub(crate) struct OrgRepoIssue {
org: String,
repo: String,
issue: u64,
}
impl Parse for OrgRepoIssue {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let org = input.parse::<syn::LitStr>()?.value();
input.parse::<syn::token::Comma>()?;
let repo = input.parse::<syn::LitStr>()?.value();
input.parse::<syn::token::Comma>()?;
let issue = input.parse::<syn::LitInt>()?.base10_parse()?;
input.parse::<syn::token::Comma>().ok();
Ok(Self { org, repo, issue })
}
}
#[allow(dead_code)]
fn tests() {}