#!/usr/bin/env perl # # Make sure you place this file somewhere in your $PATH # use strict; use warnings; use autodie; use v5.32; use Term::ANSIColor; use Scalar::Util qw(looks_like_number); use File::HomeDir; use File::Spec::Functions; use Mojo::UserAgent; my $AOC_FIRST_YEAR = 15; # first event was in 2015 my $HOME = File::HomeDir->my_home; my $DOMAIN = 'adventofcode.com'; # # User-defined constants: ############################################################################## my $PATH_FROM_HOME = "programs"; my $DIR_PREFIX = "aoc20"; # store your browser cookie session ID in the environment variable # `$SESSIONID`: # $ export SESSIONID="8374....907d" ############################################################################## # sub invalid_arguments { die "Usage (with two-digit year and two-digit day): $0 ", colored( '[year]', 'underline'), ' ', colored( '[day]', 'underline'); } sub process_arguments { my @arguments = @{ shift() }; invalid_arguments if ( scalar @arguments != 2 ); my ( $year, $day ) = @arguments; invalid_arguments unless ( looks_like_number( $year ) && looks_like_number( $day ) ); invalid_arguments if ( $year < $AOC_FIRST_YEAR or $year > (localtime)[5] % 100 ); invalid_arguments if ( $day < 1 or $day > 24 ); $day = '0' . $day if ( $day =~ m/^\d$/ ); return ( $year, $day ); } sub create_year_directory { my $year_directory = shift; if ( -e $year_directory ) { say "$year_directory already exists"; } else { say "creating $year_directory..."; mkdir $year_directory, 0755 or die "Cannot create directory $year_directory: $!"; } } sub create_day_subdirectory { my $day_subdir = shift; if ( -e -d $day_subdir ) { say "$day_subdir already exists."; } else { say "creating $day_subdir..."; mkdir $day_subdir, 0755 or die "Cannot create directory $day_subdir: $!"; } } sub read_boilerplate { my ( $year, $day ) = @_; ( my $boilerplate = qq[ #!/usr/local/bin/perl # day 20$year-$day use strict; use warnings; use v5.32; \@ARGV = "input" unless \@ARGV; chomp( my \$input = do { local \$/; <> } ); ] ) =~ s/^ {8}//mg; # remove leading 8 spaces $boilerplate =~ s/\A\n//; # remove leading line break return $boilerplate; } sub create_boilerplate_file { my ( $day_file, $boilerplate ) = @_; say "creating boilerplate file..."; if ( -e $day_file ) { # don't overwrite existing file warn "solution file for this day already exists"; return; } open my $bp_file, '>', $day_file; say $bp_file $boilerplate; close $bp_file; chmod 0755, $day_file; } sub download_input { my ( $year, $day, $day_subdir ) = @_; $day =~ s/^0//; # remove leading 0 my $ua = Mojo::UserAgent->new; my $url = "https://$DOMAIN/20$year/day/$day/input"; $ua->cookie_jar->add( Mojo::Cookie::Response->new( name => 'session', value => $ENV{SESSIONID}, domain => $DOMAIN, path => '/' ) ); say "downloading input file..."; my $res = $ua->get( $url )->result; if ($res->is_success) { my $filename = catfile( $day_subdir, 'input' ); if ( -e $filename ) { # don't overwrite existing file die "input file for this day already exists."; } open my $input_fh, '>', $filename; say $input_fh $res->body; close $input_fh; } elsif ($res->is_error) { say "unable to dowload input file.\n", $res->message; } elsif ($res->code == 301) { say "input file not found.\n", $res->headers->location; } else { say 'unexpected error encountered while downloading input file.'; } } my ( $year, $day ) = process_arguments( \@ARGV ); my $year_directory = "$HOME/$PATH_FROM_HOME/$DIR_PREFIX$year"; my $day_subdir = catfile( $year_directory, "day" . $day ); my $day_file = catfile( $day_subdir, "day". $day . ".pl" ); my $boilerplate = read_boilerplate( $year, $day ); create_year_directory ( $year_directory ); create_day_subdirectory( $day_subdir ); create_boilerplate_file( $day_file, $boilerplate ); download_input ( $year, $day, $day_subdir );