diff options
-rwxr-xr-x | culosillad.pl | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/culosillad.pl b/culosillad.pl new file mode 100755 index 0000000..74d2297 --- /dev/null +++ b/culosillad.pl @@ -0,0 +1,152 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use File::Basename; +use HTTP::Tiny; +use JSON::PP qw<decode_json>; + +my @REQUIRED_CONFIG_KEYS = qw(url user token); + +sub usage { + die <<EOF +Usage: $0 [OPTIONS] {start|stop} +Options: + --cron <minutes> wait randomly from 0 to <minutes> before doing anything + -n | --dry-run fetch data but don't change anything + -v | --verbose increase log level + +Sample config file (~/.config/culosillad/fulanito.conf): + + url = https://time.example.com + user = fulanito + token = 123456789 +EOF + ; +} + +# Parse CLI arguments +my $DRYRUN = my $CRON = my $VERBOSE = 0; +my $MODE; +while (my $opt = shift) { + if ($opt eq '--cron') { + $CRON = int(shift) || die "Invalid argument for '--cron'\n"; + } elsif ($opt eq '-v' || $opt eq '--verbose') { + $VERBOSE = 1; + } elsif ($opt eq '-n' || $opt eq '--dryrun') { + $DRYRUN = 1; + } elsif ($opt eq 'start' || $opt eq 'stop') { + $MODE = $opt; + } +} +usage unless $MODE; + +my $CONFDIR = $ENV{'CULOSILLAD_CONFDIR'} || + ($ENV{'XDG_CONFIG_HOME'} || glob '~/.config') . '/culosillad'; +mkdir $CONFDIR; +print "[+] Configs dir: $CONFDIR\n" if $VERBOSE == 1; + +my @CONFIGS = glob("$CONFDIR/*"); + +sub read_config { + my $cfgfile = shift; + my %config; + + print "[+] Reading config $cfgfile\n" if $VERBOSE == 1; + + open(my $fh, '<', $cfgfile) or die "Could not open file: $!"; + my $line = 1; + while (<$fh>) { + if (/^([a-z]+)\s*=\s*(\S+)$/) { + $config{$1} = $2; + } else { + die "Error reading config $cfgfile (line=$line)\n" + } + $line += 1; + } + foreach my $key (@REQUIRED_CONFIG_KEYS) { + die "Missing key '$key' in config file\n" unless exists $config{$key}; + } + return \%config; +} + +my %CONFIG; + +sub request { + my ($method, $endpoint) = @_; + + my $response = HTTP::Tiny->new( + agent => 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/110.0' + )->request( + $method, + "$CONFIG{url}/api/$endpoint", + { + headers => { + 'X-AUTH-USER' => $CONFIG{user}, + 'X-AUTH-TOKEN' => $CONFIG{token}, + } + } + ); + my $content = decode_json($response->{content}); + $response->{status} eq '200' or die "Error calling '$endpoint': '$content->{message}'\n"; + return $content; +} + +sub get_recent_timesheets { + return request('GET', 'timesheets/recent'); +} + +sub get_active_timesheets { + return request('GET', 'timesheets/active'); +} + +sub get_active_ets { + my $timesheets = get_active_timesheets(); + return grep { $_->{project}{name} eq "Fichaje_Empleados" } @$timesheets; +} + +sub get_ets { + my $timesheets = get_recent_timesheets(); + return grep { $_->{project}{name} eq "Fichaje_Empleados" } @$timesheets; +} + +sub start_ets { + my $tsid = shift; + return request('PATCH', "timesheets/$tsid/restart"); +} + +sub stop_ets { + my $tsid = shift; + return request('PATCH', "timesheets/$tsid/stop"); +} + +print "[+] DRY RUN: not doing anything\n" if $DRYRUN == 1; + +if ($CRON > 0) { + my $minutes = int(rand($CRON)); + printf "[+] Cron mode enabled (max: %s minutes); sleeping %s minutes...\n", $CRON, $minutes; + sleep $minutes * 60; +} + +foreach my $cfgfile (@CONFIGS) { + next unless -f $cfgfile; # skip directories + + %CONFIG = %{ read_config($cfgfile) }; + + my ($ets) = get_active_ets(); + + if ($MODE eq 'start') { + die "Refusing to start; found active ETS ($ets->{id})\n" if defined $ets; + + my ($ets) = get_ets(); + die "Unable to find ETS\n" unless defined $ets; + + start_ets($ets->{id}) unless $DRYRUN == 1; + print "[+] OK! Started successfully\n"; + } elsif ($MODE eq 'stop') { + die "Unable to find active timesheet\n" unless defined $ets; + stop_ets($ets->{id}) unless $DRYRUN == 1; + print "[+] OK! Stopped successfully\n"; + } +} |