use reqwest::{blocking::Client, cookie::Jar}; use std::{env, error::Error, fs, path::PathBuf, sync::Arc}; const BASE_URL: &str = "https://adventofcode.com"; #[macro_export] macro_rules! input { () => {{ let stem = std::path::Path::new(file!()) .file_stem() .unwrap() .to_string_lossy(); let (year, day) = stem.split_once('-').unwrap(); $crate::get_day(year, day).unwrap() }}; } pub fn get_day(year: &str, day: &str) -> Result> { let path = PathBuf::from(format!("input/{year}/day{day}.txt")); fs::create_dir_all(path.parent().unwrap())?; if let Ok(input) = fs::read_to_string(&path) { Ok(input) } else { // get session token let file = fs::read_to_string(".env").unwrap_or(String::new()); let session = file .lines() .filter_map(|line| line.split_once('=')) .map(|(key, value)| (key.to_string(), value.to_string())) .chain(env::vars()) .find_map(|(k, v)| (k == "SESSION").then_some(v)) .ok_or( "SESSION environment variable not set, retrieve it from https://adventofcode.com", )?; // create session cookie let cookie = format!("session={session}"); // setup client let jar = Arc::new(Jar::default()); jar.add_cookie_str(&cookie, &BASE_URL.parse()?); let client = Client::builder().cookie_provider(jar).build()?; // download until day fails let url = format!("{BASE_URL}/{year}/day/{day}/input"); let text = client.get(url).send()?.text()?; fs::create_dir_all(path.parent().unwrap())?; fs::write(path, &text)?; Ok(text) } }