Expand description
A typed client for Advent of Code.
It downloads puzzle inputs and samples, reads how many stars an account has
earned, and submits answers. The site has no API, so every reply is a page
meant for a browser; recognising them is parse’s job and nothing else’s.
use aoc_api::{Part, Puzzle, Session, Verdict};
let session = Session::new("53616c7465645f5f...", "github.com/my-username/my-repo by me@example.com")?;
let puzzle = Puzzle::at(2024, 7)?;
let input = session.input_text(puzzle).await?;
match session.submit(puzzle, Part::One, "3749").await? {
Verdict::Correct => println!("gold star"),
verdict => println!("{verdict}"),
}§Shape
Sessionholds the cookie and the one HTTP client built from it. Which puzzle a call is about is an argument, so one session serves a whole event.- Every endpoint is also a free function over a
http::Transport-session::input_text,session::submitand the rest - for a caller that already keeps a transport in a type of its own and does not want a second wrapper around it.Session’s methods are those functions with the transport filled in. Puzzle,Year,DayandPartare validated newtypes, so an out-of-range coordinate cannot become a request.http::Transportis the seam everything external sits behind.http::fake::FakeTransportreplays canned replies, which is how this crate’s own tests run without a network or a cookie - and how a tool built on it can do the same.Erroris the union of the typed errors each module owns.
§Runtime
The API is asynchronous and brings no runtime of its own: it runs on
whichever executor the caller already has, including a current-thread
tokio runtime driven to completion, which is how a synchronous program
should use it.
§Automation etiquette
This crate follows the Advent of Code automation guidelines. Two of them are settled here, and two are deliberately left to you:
- Identification. Every request carries a
User-Agentwith the identification you provide when the HTTP client is built, whether that isSession::neworhttp::ReqwestTransport::new. It is baked into the client’s default headers, so no request can go out without it. - No hidden traffic. A request happens when you call an endpoint, and never otherwise. Nothing polls, retries or prefetches.
- Throttling is yours. This crate does not sleep between requests,
because a library cannot know how a program is being driven and a hidden
delay in someone else’s process is a poor surprise. Space out your calls;
aoc-runtimeis one example of doing it, with a persisted minimum gap. - Caching is yours. Inputs are personal, permanent and unchanging, so download one once and keep it. This crate returns the body and forgets it.
Re-exports§
pub use error::Error;pub use parse::Hint;pub use puzzle::Day;pub use puzzle::Part;pub use puzzle::Puzzle;pub use puzzle::PuzzleError;pub use puzzle::Year;pub use session::Session;pub use session::Verdict;