summaryrefslogtreecommitdiffstats
path: root/src/github.rs
blob: 9a62994fabd5cd83bf2bb66070cd142674dada11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use failure::{Error, ResultExt};
use reqwest::header::{self, HeaderValue};
use reqwest::{Client, Method, RequestBuilder};
use std::borrow::Cow;

static API_BASE: &str = "https://api.github.com/";
static TOKEN_VAR: &str = "GITHUB_TOKEN";

#[derive(serde::Deserialize)]
pub(crate) struct User {
    pub(crate) login: String,
    pub(crate) name: Option<String>,
    pub(crate) email: Option<String>,
}

pub(crate) struct GitHubApi {
    http: Client,
    token: String,
}

impl GitHubApi {
    pub(crate) fn new() -> Result<Self, Error> {
        let token = std::env::var(TOKEN_VAR)
            .with_context(|_| format!("missing environment variable {}", TOKEN_VAR))?;
        Ok(GitHubApi {
            http: Client::new(),
            token: token.to_string(),
        })
    }

    fn prepare(&self, method: Method, url: &str) -> Result<RequestBuilder, Error> {
        let url = if url.starts_with("https://") {
            Cow::Borrowed(url)
        } else {
            Cow::Owned(format!("{}{}", API_BASE, url))
        };
        Ok(self.http.request(method, url.as_ref()).header(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("token {}", self.token))?,
        ))
    }

    pub(crate) fn user(&self, login: &str) -> Result<User, Error> {
        Ok(self
            .prepare(Method::GET, &format!("users/{}", login))?
            .send()?
            .error_for_status()?
            .json()?)
    }
}