#!/usr/bin/perl # Copyright © 2018, Bradley M. Kuhn # License: AGPL-3.0-or-later use strict; use warnings; use autodie qw(open close opendir); use Getopt::Long; use File::Spec; use Date::Manip qw(ParseDate UnixDate); my($PAYMENT_DIR, $VERBOSE, $INTERACTIVE, $PAYMENT_NUMBER, $RT_CMD); sub FindUniqueTicket(@) { my @searchTerms = @_; open(my $rtLsFH, "-|", "$RT_CMD", "ls", "-i", 'Queue = outreachy-interns AND ' . join(" AND ", @searchTerms)); my $ticketSpec; while (my $lsLine = <$rtLsFH>) { chomp $lsLine; if ($lsLine =~ /ticket/) { if (defined $ticketSpec) { $ticketSpec = undef; last; } $ticketSpec = $lsLine; } } close $rtLsFH; return $ticketSpec; } sub PaymentDateByTicket($$) { my($ticketSpec, $paymentNumber) = @_; open(my $rtPayFH, "-|", "$RT_CMD", "show", "-f", 'CF.{payment-' . $paymentNumber . '-sent}', $ticketSpec); my $date; while (my $payLine = <$rtPayFH>) { chomp $payLine; if ($payLine =~ /[\d\-]+/) { $date = $payLine; last; } } close $rtPayFH; return $date; } sub LedgerTagFromTicket($$) { my($ticketSpec, $tag) = @_; open(my $rtPayFH, "-|", "$RT_CMD", "show", "-f", 'CF.{ledger-tags}', $ticketSpec); my $tagValue; while (my $tagsLine = <$rtPayFH>) { chomp $tagsLine; if ($tagsLine =~ /^\s*;?$tag\s*:\s*(.+)\s*$/i) { $tagValue = $1; last; } } close $rtPayFH; return $tagValue; } GetOptions("paymentDir=s" => \$PAYMENT_DIR, "verbose=i" => \$VERBOSE, "interactive" => \$INTERACTIVE, "paymentNumber=i" => \$PAYMENT_NUMBER, "rtCommand=s" => $RT_CMD); $RT_CMD = '/usr/bin/rt' unless defined $RT_CMD; $INTERACTIVE = 0 if not defined $INTERACTIVE; unless (defined $PAYMENT_DIR and -d $PAYMENT_DIR) { print STDERR "usage: $0 --paymentDir= option is required and directory must exist\n"; exit 1; } unless (defined $PAYMENT_NUMBER and $PAYMENT_NUMBER =~ /^123$/) { print STDERR "usage: $0 --paymentNumber= option is required and must be 1, 2 or 3\n"; exit 1; } $VERBOSE = 0 unless defined $VERBOSE; opendir(my $dh, $PAYMENT_DIR); while (my $file = readdir $dh) { unless ($file =~ /^\s*(success|faile?d?)-(\S+)\.txt\s*$/i) { print STDERR "Skipping $file which does not match proper format...\n" if ($VERBOSE >= 2); next; } my($pass, $name) = ($1, $2); $pass = ($pass =~ /success/) ? 1 : 0; open(my $fh, "<", File::Spec->catfile($PAYMENT_DIR, $file)); my $mentorDate; while (my $line = <$fh> ) { if ($line =~ /^\s*Date\s*:\s*(.+)\s*$/) { $mentorDate = UnixDate(ParseDate($1), "%Y-%m-%d"); next; } } if (not defined $mentorDate) { print STDERR "\"$file\": Skipping: Inside that file there is no valid Date: header" ; next; } # Find the ticket number for this intern. my $entity = LedgerTagFromTicket($ticket, 'Entity'); if (not defined $entity) { print STDERR "\"$file\": \"$ticket\": Skipping: cannot determine Entity from ticket." ; next; } my(@nameComponents) = split(/\s*-\s*/, $name); my(@searchTerms); foreach my $name (@nameComponents) { push(@searchTerms, 'Subject LIKE "' . $name . '"'); } my $ticket = FindUniqueTicket(@searchTerms); if (not defined $ticket) { foreach my $term (@searchTerms) { $ticket = FindUniqueTicket(($term)); last if (defined $ticket); } } if (not defined $ticket) { if (not $INTERACTIVE) { print STDERR "\"$file\": Skipped: unable to to find a matching ticket.\n"; next; } else { # FIXME: prompt for ticket die "interactive mode not yet supported"; } } if ($PAYMENT_NUMBER == 1) { print STDERR "Sorry, script does not yet support first payment\n"; exit 1; } # Check to see if this payment was already made my $thisPayDate = PaymentDateByTicket($ticket, $PAYMENT_NUMBER); if (defined $thisPayDate) { print STDERR "\"$file\": \"$ticket\": Skipped: payment $PAYMENT_NUMBER was already made"; if ($pass) { print STDERR ".\n"; } else { print STDERR "... BIG PROBLEM: the intern actually failed but got this payment.\n"; } } # Check to see if previous payment was sent payment my $prevPay = $PAYMENT_NUMBER - 1; my $lastPayDate = PaymentDateByTicket($ticket, $prevPay); if ($pass and (not defined $lastPayDate)) { print STDERR "\"$file\": \"$ticket\": Skipped: payment $prevPay was not made yet.\n"; next; } } ############################################################################### # # Local variables: # compile-command: "perl -c rt-outreachy-payment-next.plx" # perl-indent-level: 2 # End: