public
Created

Automatically check jury duty on-call status

  • Download Gist
jury-mojo.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#!/usr/bin/env perl
#
# A simple script to repeatedly check on-call status for United States
# District Court juror instructions. It will send mail with any instructions
# and, if necessary, schedule itself to check again when instructed.
#
# Usage: /path/to/jury-mojo.pl PARTICIPANT_ID ZIP_CODE
 
use 5.012;
use Mojo::UserAgent;
use DateTime::Format::DateParse;
use Email::Simple;
use Email::Sender::Simple qw( sendmail );
 
my $email = Email::Simple->create(
header => [
To => '"Me" <me@example.com>',
From => '"Me Too" <me@example.com>',
],
);
 
# Safety first!
$SIG{'__DIE__'} = sub {
$email->header_set( 'Subject' => 'Jury Check: Died' );
$email->body_set( $_[0] );
sendmail($email);
die @_;
};
 
my $ua = Mojo::UserAgent->new;
my $url = 'http://jury.casd.uscourts.gov/AppearWeb/Default.aspx';
my $res = $ua->get($url)->res; # initial fetch to get cookie and form fields
my $tx = $ua->max_redirects(3)->post_form(
$url => {
'__VIEWSTATE' => $res->dom('form#Form1 > input#__VIEWSTATE')->[0]->attrs('value'),
'__EVENTVALIDATION' => $res->dom('form#Form1 > input#__EVENTVALIDATION')->[0]->attrs('value'),
'ctl02$txtPart' => $ARGV[0],
'ctl02$txtZip' => $ARGV[1],
'ctl02$btnInstructions' => 'Reporting Instructions',
}
);
 
$res = $tx->success or die $tx->error;
 
# This is what the response message looks like in the HTML:
# <span id="ctl02_lblMsg">Please check again Sunday, April 29, after 6:00pm for further reporting instructions. Do NOT report at this time.</span>
my $message = $res->dom('span#ctl02_lblMsg')->[0]->text;
 
if ( $message !~ /Do NOT report at this time/ ) {
# We didn't see the message we wanted to see, so we'd better alert.
$email->header_set( 'Subject' => 'Jury Check: You may need to report' );
$email->body_set("$message\n");
sendmail($email);
exit;
}
 
if ( $message !~ /Please check again (?<weekday>\w+), (?<month>\w+) (?<day>\d+)/ ) {
# We couldn't parse the next date to check, so we'd better alert.
$email->header_set( 'Subject' => 'Jury Check: Failed to parse date' );
$email->body_set("$message\n");
sendmail($email);
exit;
}
 
my $dt = DateTime::Format::DateParse->parse_datetime("$+{'weekday'}, $+{'day'} $+{'month'} 18:15");
 
# Set up an at(1) job for the next time we need to check. The jury
# instructions are always updated at 18:00, so we're hard-coding that bit with
# a buffer.
open my $at, '|-', 'at', $dt->strftime('%R'), $dt->strftime('%F') or die "at: $!";
say {$at} "$0 @ARGV 2>/dev/null"; # $0 must be fully qualified or in PATH
close $at;
 
# We should alert anyway, just in case things didn't work out quite right.
$email->header_set( 'Subject' => 'Jury Check: Do NOT report at this time' );
$email->body_set( sprintf "%s\n\nNext check scheduled for %s.\n", $message, $dt->strftime('%c') );
sendmail($email);
jury.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
#!/usr/bin/env perl
#
# A simple script to repeatedly check on-call status for United States
# District Court juror instructions. It will send mail with any instructions
# and, if necessary, schedule itself to check again when instructed.
#
# Usage: /path/to/jury.pl PARTICIPANT_ID ZIP_CODE
 
use 5.012;
use WWW::Scripter; # h/t cpansprout (https://gist.github.com/2522558#gistcomment-292147)
use DateTime::Format::DateParse;
use Email::Simple;
use Email::Sender::Simple qw( sendmail );
 
my $email = Email::Simple->create(
header => [
To => '"Me" <me@example.com>',
From => '"Me Too" <me@example.com>',
],
);
 
# Safety first!
$SIG{'__DIE__'} = sub {
$email->header_set( 'Subject' => 'Jury Check: Died' );
$email->body_set( $_[0] );
sendmail($email);
die @_;
};
 
# This may only work for the Southern District of California.
my $mech = WWW::Scripter->new();
$mech->get('http://jury.casd.uscourts.gov/AppearWeb/Default.aspx');
$mech->submit_form(
form_name => 'Form1',
fields => {
'ctl02$txtPart' => $ARGV[0],
'ctl02$txtZip' => $ARGV[1],
},
button => 'ctl02$btnInstructions',
);
 
# This is what the response message looks like in the HTML:
# <span id="ctl02_lblMsg">Please check again Sunday, April 29, after 6:00pm for further reporting instructions. Do NOT report at this time.</span>
my $message = $mech->document->getElementById('ctl02_lblMsg')->innerHTML;
 
if ( $message !~ /Do NOT report at this time/ ) {
# We didn't see the message we wanted to see, so we'd better alert.
$email->header_set( 'Subject' => 'Jury Check: You may need to report' );
$email->body_set("$message\n");
sendmail($email);
exit;
}
 
if ( $message !~ /Please check again (?<weekday>\w+), (?<month>\w+) (?<day>\d+)/ ) {
# We couldn't parse the next date to check, so we'd better alert.
$email->header_set( 'Subject' => 'Jury Check: Failed to parse date' );
$email->body_set("$message\n");
sendmail($email);
exit;
}
 
my $dt = DateTime::Format::DateParse->parse_datetime("$+{'weekday'}, $+{'day'} $+{'month'} 18:15");
 
# Set up an at(1) job for the next time we need to check. The jury
# instructions are always updated at 18:00, so we're hard-coding that bit with
# a buffer.
open my $at, '|-', 'at', $dt->strftime('%R'), $dt->strftime('%F') or die "at: $!";
say {$at} "$0 @ARGV 2>/dev/null"; # $0 must be fully qualified or in PATH
close $at;
 
# We should alert anyway, just in case things didn't work out quite right.
$email->header_set( 'Subject' => 'Jury Check: Do NOT report at this time' );
$email->body_set( sprintf "%s\n\nNext check scheduled for %s.\n", $message, $dt->strftime('%c') );
sendmail($email);

Instead of

$dom->parse_file( IO::Scalar->new( do { my $c = $mech->content; \$c } ) );

you could write simply

$dom->write($mech->content);
$dom->close;

Alternatively, you could s/WWW::Mechanize/WWW::Scripter/ and write

my $message = $mech->document->getElementById('ctl02_lblMsg')->innerHTML;

WWW::Scripter, a subclass of WWW::Mechanize, is HTML::DOM’s raison d’être

Oh, that's excellent. As I was working on a version using Mojo::UserAgent (as someone recommended I try), I found myself thinking, "It would be awesome if WWW::Mechanize gave me access to the document with HTML::DOM." Thanks for the pointer to the module that filled exactly that need.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.