github_heatmap/
lib.rs

1mod heatmap;
2mod utils;
3
4use std::error;
5use reqwest::StatusCode;
6use scraper::Html;
7pub use heatmap::{Heatmap, ContributionWeek, Contribution};
8pub use utils::args::{Args, ColorValues};
9pub use utils::errors::{HeatmapError, GithubError};
10pub use utils::parsers::{parse_slug, parse_year};
11
12const PROFILE_URL: &str = "https://github.com";
13
14pub fn run(args: &Args) -> Result<(), Box<dyn error::Error>> {
15    let profile_url = match &args.year {
16        Some(year) => format!("{PROFILE_URL}/{slug}?from={year}-01-01", slug = args.slug),
17        None => format!("{PROFILE_URL}/{slug}", slug = args.slug)
18    };
19
20    let profile = get_github_profile(&profile_url)?;
21    let heatmap = Heatmap::from_document(&profile)?;
22    heatmap.render(&args.color);
23
24    Ok(())
25}
26
27fn get_github_profile(profile_url: &str) -> Result<Html, GithubError> {
28    let response = reqwest::blocking::get(profile_url).unwrap();
29
30    let body = match response.status() {
31        StatusCode::OK => Ok(response.text().map_err(|_| GithubError::BadRequest)?),
32        StatusCode::NOT_FOUND => Err(GithubError::ProfileNotFound(profile_url.to_string())),
33        status => Err(GithubError::ScrapeFailure(status))
34    }?;
35
36    Ok(Html::parse_document(&body))
37}