aoc-lib 1.0.3

A library that lets you focus on problem-solving rather than boilerplate when doing Advent of Code
Documentation
use std::fs::File;
use std::io::Write;
use std::path::Path;

use reqwest::header::COOKIE;

use crate::input_path::{get_day_path, INPUT_DIR};
use crate::input_type::InputType;

fn read_session_cookie() -> String {
    let filename = home::home_dir()
        .expect("Failed to find home directory")
        .join(".aoc.cookie");
    std::fs::read_to_string(&filename)
        .unwrap_or_else(|_| panic!("Failed to read from session cookie file: {:?}", filename))
        .trim()
        .to_string()
}

pub(crate) struct AocClient {
    year: u16,
    session_token: String,
    client: reqwest::blocking::Client,
}

impl AocClient {
    pub fn new(year: u16) -> Self {
        let _ = std::fs::create_dir(Path::new(INPUT_DIR));
        Self {
            year,
            session_token: read_session_cookie(),
            client: reqwest::blocking::Client::new(),
        }
    }

    pub fn get_input(&self, day: u8) -> String {
        let input = std::fs::read_to_string(get_day_path(self.year, day, InputType::Real))
            .unwrap_or(self.download_input(day));
        self.cache_input(day, &input);
        input
    }

    fn cache_input(&self, day: u8, input: &str) {
        File::create(get_day_path(self.year, day, InputType::Real))
            .expect("Failed to create input file")
            .write_all(input.as_bytes())
            .expect("Failed to write input file");
    }

    fn download_input(&self, day: u8) -> String {
        self.client
            .get(format!(
                "https://adventofcode.com/{}/day/{}/input",
                self.year, day
            ))
            .header(COOKIE, format!("session={}", self.session_token))
            .send()
            .expect("Failed to sent input request to server")
            .error_for_status()
            .expect("Got error from server")
            .text()
            .expect("Failed to parse response from server")
    }
}