Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Automatically check jury duty on-call status

View jury-mojo.pl
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);
View jury-mojo.pl
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

Owner
sirhc commented

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.