#!/usr/bin/perl

# Name:		alephrenew.pl
# Purpose:	Automated book renewing at libraries using the "Aleph"-software by ex libris.
# Version:	0.1.6
# Date:		08.10.2008
# License:	GPLv2
# Author:	Robert Annessi <robert@annessi.at>


# Changes
# 0.1.6:	added new success message
# 0.1.5:	first public release



use warnings;
use strict;
use LWP::UserAgent;
use Getopt::Std;

# global vars
my $ua;				# user agent
my $response;			# response from aleph
my $sid;			# session id
my $library;			# library id
my $max_random_wait = '30';	# maximum amount in seconds to wait randomly


# help    
sub usage() {
    print STDERR <<EOF;

Usage: $0 [-h] [-q] -b <baseurl> -u <username> -p <password> [-r <seconds>]

-h	: this help message
-q	: quiet (suppress success message)
-b	: baseurl without trailing slash (eg. http://aleph.ub.tuwien.ac.at)
-u	: username (eg. \$E123456) - you will probably need to escape the "\$"
-p	: password - your date of birth in the form of YYYYMMDD (eg. 19730425)
	  if you did not change it
-r	: wait random time between 1 and "seconds" seconds (before starting and
	  1 to $max_random_wait seconds between the requests - so it does not look like a script)

Examples: 
	$0 -q -b http://aleph.ub.tuwien.ac.at -u \\\$E123456 -p 19730425 -r 3600
	$0 -b http://aleph.univie.ac.at -u \\\$E098765 -p 19851224

A crontab entry may look like this:	
0 0 * * 2-6 /path/to/alephrenew.pl -q -b http://aleph.ub.tuwien.ac.at -u \\\$E3862419 -p 0wN4g3 -r 7200

EOF
 	exit 1;
}


# return random integer between limits
sub random_int_in ($$) {
	my($min, $max) = @_;
	return $min if $min == $max;
	($min, $max) = ($max, $min)  if  $min > $max;
	return $min + int rand(1 + $max - $min);
}


# parse and check command line options
our($opt_u, $opt_p, $opt_r, $opt_h, $opt_q, $opt_b);
getopts('u:p:r:hqb:') or usage();
usage() if ($opt_h || !$opt_u || !$opt_p || !$opt_b);


# change language to english
sub change_language() {
	$response = $ua->get("$opt_b/F/$sid/?func=option-update-lng&P_CON_LNG=ENG&UPDATE_PROFILE=N");
	if (!$response->is_success) {
		die $response->status_line;
	}
	#print $response->content;
	
	# check if the change was successful
	if ($response->content !~ m/Catalogues/) {
		print "ERROR: language change was unsuccessful! ):\n";
		exit 2;
	}
	random_sleep();
}


# random sleep between the requests (1 to $max_random_wait seconds)
sub random_sleep() {
	sleep(random_int_in(1,$max_random_wait)) if ($opt_r);
}


# check for sleep value and sleep (if requested)
if ($opt_r) {
	if ($opt_r =~ m/^\d+$/) {
		sleep(random_int_in(1,$opt_r));	
	} else {
		print "ERROR: \"$opt_r\" is not an integer!\n";
		exit 2;
	}
}


# initiate browser
$ua = LWP::UserAgent->new();
$ua->agent(""); # do not identify


# get start page from aleph
$response = $ua->get("$opt_b/ALEPH");
if (!$response->is_success) {
	die $response->status_line;
}
#print $response->content;

# get the sid
if ($response->content =~ m/ALEPH_SESSION_ID = ([A-Z0-9]{50});/) {
	$sid = "$1";
} else {
	print "ERROR: sid not found! ):\n";
	exit 2;
}
random_sleep();
change_language();


# get the login form from aleph
$response = $ua->get("$opt_b/F/$sid/?func=file&file_name=login-session");
if (!$response->is_success) {
	die $response->status_line;
}
#print $response->content;

# get the library id
if ($response->content =~ m/"?bor_library"? value="?([A-Z]{3}[0-9]{2})"?/) {
	$library = "$1";
} else {
	print "ERROR: library not found! ):\n";
	exit 2;
}
random_sleep();


# login to aleph
$response=$ua->request(HTTP::Request->new ('POST', "$opt_b/F/$sid/", HTTP::Headers->new(), "func=login-session&login_source=&bor_id=$opt_u&bor_verification=$opt_p&bor_library=$library")); 
if (!$response->is_success) {
	die $response->status_line;
}
#print $response->content;
random_sleep();
change_language();

# check if the login was successful
if ($response->content !~ m/(LOG OFF|Sign Out \(Reset\))/) {
	print "ERROR: Wrong username and/or password! ):\n";
	exit 2;
}


# check if there are any items to renew
$response = $ua->get("$opt_b/F/$sid/?func=bor-loan&adm_library=$library");
if (!$response->is_success) {
	die $response->status_line;
}
if ($response->content =~ m/You do not have any items currently checked out\./) {
	exit 0;
}
#print $response->content;
random_sleep();
change_language();


# actually do the renewing
$response = $ua->get("$opt_b/F/$sid/?func=bor-renew-all");
if (!$response->is_success) {
	die $response->status_line;
}
#print $response->content;

# check if the renewing was successful
if ($response->content !~ m/(Renew All finished Successfully on all Loaned Items ! |These items were renewed:)/) {
	print STDERR "WARNING: At least some books could not be renewed! ):\n";
	exit 1;
} elsif (!$opt_q) {
	print "All books were successfully renewed! (:\n";
}

exit 0;
