1use chrono::{DateTime, TimeZone, Utc};
2
3pub enum Error {
4 ChallengeNotReady {
5 time_till_ready: std::time::Duration,
6 },
7 Other(anyhow::Error),
8}
9
10impl<E> From<E> for Error
11where
12 E: Into<anyhow::Error>,
13{
14 fn from(e: E) -> Self {
15 Error::Other(e.into())
16 }
17}
18
19fn release_time(year: usize, day: usize) -> DateTime<Utc> {
22 let est = chrono::FixedOffset::west_opt(5 * 60 * 60).unwrap();
23
24 let hour = 0;
25 let minute = 0;
26 let second = 0;
27 est.with_ymd_and_hms(year as i32, 12, day as u32, hour, minute, second)
28 .unwrap()
29 .into()
30}
31
32pub fn to_approx_std_duration(d: chrono::Duration) -> std::time::Duration {
33 std::time::Duration::from_secs(d.num_seconds().try_into().unwrap_or(0))
34}
35
36pub fn get_input(session_token: &str, year: usize, day: usize) -> Result<String, Error> {
37 let release_time = release_time(year, day);
38 let now = Utc::now();
39 if now < release_time {
40 let time_till_ready = to_approx_std_duration(release_time - now);
41 return Err(Error::ChallengeNotReady { time_till_ready });
42 }
43
44 let input = reqwest::blocking::Client::new()
45 .get(format!(
46 "https://adventofcode.com/{}/day/{}/input",
47 year, day
48 ))
49 .header("Cookie", format!("session={}", session_token))
50 .header(
51 "User-Agent",
53 "github.com/bddap/bddap-aoc by andrew@dirksen.com",
54 )
55 .send()?
56 .error_for_status()?
57 .text()?;
58 Ok(input)
59}