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}