feat: download cli command
This commit is contained in:
		@@ -1,3 +1,5 @@
 | 
				
			|||||||
[alias]
 | 
					[alias]
 | 
				
			||||||
prepare = "run --bin prepare --"
 | 
					prepare = "run --bin prepare --"
 | 
				
			||||||
 | 
					download = "run --bin download --"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
solve = "run --bin"
 | 
					solve = "run --bin"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.env.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					TOKEN=secret
 | 
				
			||||||
 | 
					YEAR=2022
 | 
				
			||||||
							
								
								
									
										999
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										999
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -8,4 +8,8 @@ default-run = "aoc"
 | 
				
			|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					# framework
 | 
				
			||||||
 | 
					dotenv = "0.15.0"
 | 
				
			||||||
pico-args = "0.5.0"
 | 
					pico-args = "0.5.0"
 | 
				
			||||||
 | 
					reqwest = { version = "0.11.13", features = ["blocking"] }
 | 
				
			||||||
 | 
					# for solving
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							@@ -16,6 +16,21 @@ cargo prepare <day>
 | 
				
			|||||||
# 🎄 Type `cargo solve 01` to run your solution.
 | 
					# 🎄 Type `cargo solve 01` to run your solution.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Download input
 | 
				
			||||||
 | 
					prepare `.env` file
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					cp .env.example .env
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					set `YEAR` to whichever year you are solving for and `TOKEN` to AoC session Cookie.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					# example: `cargo download 1`
 | 
				
			||||||
 | 
					cargo download <day>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# output:
 | 
				
			||||||
 | 
					# Downloaded input file "src/inputs/01.txt"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Solve
 | 
					### Solve
 | 
				
			||||||
```sh
 | 
					```sh
 | 
				
			||||||
# example: `cargo solve 01`
 | 
					# example: `cargo solve 01`
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								src/bin/download.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/bin/download.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					use dotenv::dotenv;
 | 
				
			||||||
 | 
					use reqwest::blocking::Client;
 | 
				
			||||||
 | 
					use reqwest::header;
 | 
				
			||||||
 | 
					use std::{env, fs::OpenOptions, io::Write, process};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
					    let day: u8 = match aoc::parse_args() {
 | 
				
			||||||
 | 
					        Ok(day) => day,
 | 
				
			||||||
 | 
					        Err(_) => {
 | 
				
			||||||
 | 
					            eprintln!("Need to specify a day (as integer). example: `cargo download 7`");
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    dotenv().ok();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let day_padded = format!("{:02}", day);
 | 
				
			||||||
 | 
					    let token = env::var("TOKEN").expect("$TOKEN is not set");
 | 
				
			||||||
 | 
					    let year = env::var("YEAR")
 | 
				
			||||||
 | 
					        .expect("$YEAR is not set")
 | 
				
			||||||
 | 
					        .parse::<u32>()
 | 
				
			||||||
 | 
					        .expect("$YEAR must be a number");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut headers = header::HeaderMap::new();
 | 
				
			||||||
 | 
					    let mut session_header = header::HeaderValue::from_str(format!("session={}", token).as_str())
 | 
				
			||||||
 | 
					        .expect("Error building cookie header");
 | 
				
			||||||
 | 
					    session_header.set_sensitive(true);
 | 
				
			||||||
 | 
					    headers.insert(header::COOKIE, session_header);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let client = Client::builder().default_headers(headers).build().unwrap();
 | 
				
			||||||
 | 
					    let res = client
 | 
				
			||||||
 | 
					        .get(format!(
 | 
				
			||||||
 | 
					            "https://adventofcode.com/{}/day/{}/input",
 | 
				
			||||||
 | 
					            year, day
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					        .send()
 | 
				
			||||||
 | 
					        .unwrap()
 | 
				
			||||||
 | 
					        .text()
 | 
				
			||||||
 | 
					        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let input_path = format!("src/inputs/{}.txt", day_padded);
 | 
				
			||||||
 | 
					    let mut file = match OpenOptions::new()
 | 
				
			||||||
 | 
					        .write(true)
 | 
				
			||||||
 | 
					        .create(true)
 | 
				
			||||||
 | 
					        .open(&input_path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Ok(file) => file,
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to create module file: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    match file.write_all(res.as_bytes()) {
 | 
				
			||||||
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            println!("Downloaded input file \"{}\"", &input_path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Err(e) => {
 | 
				
			||||||
 | 
					            eprintln!("Failed to write module contents: {}", e);
 | 
				
			||||||
 | 
					            process::exit(1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -35,11 +35,6 @@ mod tests {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
"###;
 | 
					"###;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn parse_args() -> Result<u8, pico_args::Error> {
 | 
					 | 
				
			||||||
    let mut args = pico_args::Arguments::from_env();
 | 
					 | 
				
			||||||
    args.free_from_str()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
 | 
					fn safe_create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			||||||
    OpenOptions::new().write(true).create_new(true).open(path)
 | 
					    OpenOptions::new().write(true).create_new(true).open(path)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -49,7 +44,7 @@ fn create_file(path: &str) -> Result<File, std::io::Error> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    let day = match parse_args() {
 | 
					    let day = match aoc::parse_args() {
 | 
				
			||||||
        Ok(day) => day,
 | 
					        Ok(day) => day,
 | 
				
			||||||
        Err(_) => {
 | 
					        Err(_) => {
 | 
				
			||||||
            eprintln!("Need to specify a day (as integer). example: `cargo prepare 7`");
 | 
					            eprintln!("Need to specify a day (as integer). example: `cargo prepare 7`");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,11 @@ fn parse_time(val: &str, postfix: &str) -> f64 {
 | 
				
			|||||||
    val.split(postfix).next().unwrap().parse().unwrap()
 | 
					    val.split(postfix).next().unwrap().parse().unwrap()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn parse_args() -> Result<u8, pico_args::Error> {
 | 
				
			||||||
 | 
					    let mut args = pico_args::Arguments::from_env();
 | 
				
			||||||
 | 
					    args.free_from_str()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn parse_exec_time(output: &str) -> f64 {
 | 
					pub fn parse_exec_time(output: &str) -> f64 {
 | 
				
			||||||
    output.lines().fold(0_f64, |acc, l| {
 | 
					    output.lines().fold(0_f64, |acc, l| {
 | 
				
			||||||
        if !l.contains("elapsed:") {
 | 
					        if !l.contains("elapsed:") {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user