Skip to content

Instantly share code, notes, and snippets.

@sirhc
Created April 28, 2012 23:13
Show Gist options
  • Save sirhc/2522558 to your computer and use it in GitHub Desktop.
Save sirhc/2522558 to your computer and use it in GitHub Desktop.
Automatically check jury duty on-call status
#!/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);
#!/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);
@cpansprout
Copy link

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

@sirhc
Copy link
Author

sirhc commented May 1, 2012

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