advent-of-code/src/lib.rs

53 lines
1.7 KiB
Rust

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<String, Box<dyn Error>> {
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)
}
}