aocinit

Perl utility to initialize directories and files for the Advent of Code
git clone git://git.samirparikh.com/aocinit
Log | Files | Refs | README | LICENSE

aocinit (4527B) - raw


      1 #!/usr/bin/env perl
      2 
      3 #
      4 # Make sure you place this file somewhere in your $PATH
      5 #
      6 
      7 use strict;
      8 use warnings;
      9 use autodie;
     10 use v5.32;
     11 use Term::ANSIColor;
     12 use Scalar::Util qw(looks_like_number);
     13 use File::HomeDir;
     14 use File::Spec::Functions;
     15 use Mojo::UserAgent;
     16 
     17 my $AOC_FIRST_YEAR = 15; # first event was in 2015
     18 my $HOME           = File::HomeDir->my_home;
     19 my $DOMAIN         = 'adventofcode.com';
     20 
     21 #
     22 # User-defined constants:
     23 ##############################################################################
     24 my $PATH_FROM_HOME = "programs";
     25 my $DIR_PREFIX     = "aoc20";
     26 # store your browser cookie session ID in the environment variable
     27 # `$SESSIONID`:
     28 # $ export SESSIONID="8374....907d"
     29 ##############################################################################
     30 #
     31 
     32 sub invalid_arguments {
     33     die "Usage (with two-digit year and two-digit day): $0 ",
     34         colored( '[year]', 'underline'), ' ',
     35         colored( '[day]',  'underline');
     36 }
     37 
     38 sub process_arguments {
     39     my @arguments = @{ shift() };
     40     invalid_arguments if ( scalar @arguments != 2 );
     41     my ( $year, $day ) = @arguments;
     42     invalid_arguments unless ( looks_like_number( $year ) &&
     43                                looks_like_number( $day ) );
     44     invalid_arguments if ( $year < $AOC_FIRST_YEAR or
     45                            $year > (localtime)[5] % 100 );
     46     invalid_arguments if ( $day < 1 or $day > 24 );
     47     $day = '0' . $day if ( $day =~ m/^\d$/ );
     48     return ( $year, $day );
     49 }
     50 
     51 sub create_year_directory {
     52     my $year_directory = shift;
     53     if ( -e $year_directory ) {
     54         say "$year_directory already exists";
     55     } else {
     56         say "creating $year_directory...";
     57         mkdir $year_directory, 0755 or
     58             die "Cannot create directory $year_directory: $!";
     59     }
     60 }
     61 
     62 sub create_day_subdirectory {
     63     my $day_subdir = shift;
     64     if ( -e -d $day_subdir ) {
     65         say "$day_subdir already exists.";
     66     } else {
     67         say "creating $day_subdir...";
     68         mkdir $day_subdir, 0755 or
     69             die "Cannot create directory $day_subdir: $!";
     70     }
     71 }
     72 
     73 sub read_boilerplate {
     74     my ( $year, $day )  = @_;
     75     ( my $boilerplate = qq[
     76         #!/usr/local/bin/perl
     77         # day 20$year-$day
     78         
     79         use strict;
     80         use warnings;
     81         use v5.32;
     82         
     83         \@ARGV = "input" unless \@ARGV;
     84         chomp( my \$input = do { local \$/; <> } );
     85     ] ) =~ s/^ {8}//mg;       # remove leading 8 spaces
     86     $boilerplate =~ s/\A\n//; # remove leading line break
     87     return $boilerplate;
     88 }
     89 
     90 sub create_boilerplate_file {
     91     my ( $day_file, $boilerplate ) = @_;
     92     say "creating boilerplate file...";
     93     if ( -e $day_file ) {
     94         # don't overwrite existing file
     95         warn "solution file for this day already exists";
     96         return;
     97     }
     98     open my $bp_file, '>', $day_file;
     99     say $bp_file $boilerplate;
    100     close $bp_file;
    101     chmod 0755, $day_file;
    102 }
    103 
    104 sub download_input {
    105     my ( $year, $day, $day_subdir ) = @_;
    106     $day    =~ s/^0//; # remove leading 0
    107     my $ua  = Mojo::UserAgent->new;
    108     my $url = "https://$DOMAIN/20$year/day/$day/input";
    109     $ua->cookie_jar->add(
    110         Mojo::Cookie::Response->new(
    111             name   => 'session',
    112             value  => $ENV{SESSIONID},
    113             domain => $DOMAIN,
    114             path   => '/'
    115         )
    116     ); 
    117 
    118     say "downloading input file...";
    119     my $res = $ua->get( $url )->result;
    120     if    ($res->is_success)  {
    121         my $filename = catfile( $day_subdir, 'input' );
    122         if ( -e $filename ) {
    123             # don't overwrite existing file
    124             die "input file for this day already exists.";
    125         }
    126         open my $input_fh, '>', $filename;
    127         say $input_fh $res->body;
    128         close $input_fh;
    129     }
    130     elsif ($res->is_error)    {
    131         say "unable to dowload input file.\n", $res->message;
    132     }
    133     elsif ($res->code == 301) {
    134         say "input file not found.\n", $res->headers->location;
    135     }
    136     else                      {
    137         say 'unexpected error encountered while downloading input file.';
    138     }
    139 }
    140 
    141 my ( $year, $day ) = process_arguments( \@ARGV );
    142 my $year_directory = "$HOME/$PATH_FROM_HOME/$DIR_PREFIX$year";
    143 my $day_subdir     = catfile( $year_directory, "day" . $day );
    144 my $day_file       = catfile( $day_subdir, "day". $day . ".pl" );
    145 my $boilerplate    = read_boilerplate( $year, $day ); 
    146 
    147 create_year_directory  ( $year_directory          );
    148 create_day_subdirectory( $day_subdir              );
    149 create_boilerplate_file( $day_file, $boilerplate  );
    150 download_input         ( $year, $day, $day_subdir );