Skip to content

Instantly share code, notes, and snippets.

@chapuzzo
Created December 1, 2022 19:27
Show Gist options
  • Select an option

  • Save chapuzzo/eede7e89f4fef52954a1e136457a5695 to your computer and use it in GitHub Desktop.

Select an option

Save chapuzzo/eede7e89f4fef52954a1e136457a5695 to your computer and use it in GitHub Desktop.

Revisions

  1. chapuzzo created this gist Dec 1, 2022.
    95 changes: 95 additions & 0 deletions dw.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    use clap::Parser;
    use reqwest::Client;
    use select::predicate::{Name, Predicate};
    use std::env;
    use std::fs::{create_dir_all, File};
    use std::io::Write;
    use std::path::Path;
    use std::time::Duration;

    #[derive(PartialEq)]
    enum Kind {
    Snippets,
    Input,
    }

    #[derive(Parser, Debug)]
    #[command(author, version, about, long_about)]
    struct Args {
    #[arg()]
    day: u8,

    #[arg(default_value = "2022")]
    year: u16,

    #[arg(long, short = 'i')]
    input: bool,
    }

    #[tokio::main]
    async fn main() {
    dotenv::dotenv().ok();

    let args = Args::parse();
    let kind = if args.input {
    Kind::Input
    } else {
    Kind::Snippets
    };

    download(args.year, args.day, kind)
    .await
    .expect("download failed");
    }

    async fn download(year: u16, day: u8, kind: Kind) -> Result<(), anyhow::Error> {
    let client = Client::builder()
    .timeout(Duration::from_secs(3))
    .build()
    .expect("cannot build http client");

    let suffix = if kind == Kind::Input { "/input" } else { "" };

    let url = format!("https://adventofcode.com/{year}/day/{day}{suffix}");

    let cookie = env::var("COOKIE")
    .expect("must set a valid session cookie in .env");

    let ua = env::var("UA")
    .expect("must set a valid user agent to perform requests");

    let response = client
    .get(url)
    .header(reqwest::header::USER_AGENT, ua)
    .header(reqwest::header::COOKIE, cookie)
    .send()
    .await?
    .text()
    .await?;

    let cwd = env::current_dir().expect("cannot get cwd");
    let destination = cwd.join(Path::new(format!("{}/{:0>2}", year, day).as_str()));
    create_dir_all(destination.clone()).expect("could not create folder for download");

    match kind {
    Kind::Snippets => {
    let doc = select::document::Document::from(response.as_str());

    let fragments = doc.find(Name("pre").descendant(Name("code")));

    for (id, fragment) in fragments.enumerate() {
    let mut file = File::create(destination.join(format!("snippet_{:0>2}.txt", id)))
    .expect("could not create file for storing");
    write!(file, "{}", fragment.text()).expect("could not write file");
    }
    }
    Kind::Input => {
    let mut file = File::create(destination.join("input.txt"))
    .expect("could not create file for storing");

    write!(file, "{}", response)?;
    }
    };

    Ok(())
    }