Keith Vetter 2004-11-26 -- Are you like me and are always forgetting when library books are due?
Well, here's a short script I wrote a while ago that connects to your libraries web-based catalog, logs in as you, and produces either a text or RSS stream of all your checked out items. You'll need to either edit the script to add your username, password and library URL or supply them on the command line.
It was designed for libraries running a web-based system written by Dynix (also known as iPAC or oPAC), and it's only been tested on the libraries I use.
##+##########################################################################
#
# Dynix2RSS.tcl -- logs into a Dynix web-based library and produces
# an RSS feed of all checked out items.
# by Keith Vetter June 17, 2004
#
##+##########################################################################
#############################################################################
package require http
if {! [catch {package require autoproxy}]} {
::autoproxy::init
}
set username "" ;# Typically your library card number
set password "" ;# PIN - try last four digits of your phone
set dynix "" ;# Base URL of your library's Dynix catalog
;# for me its: http://66.213.81.15:8080/ipac20/ipac.jsp
proc GetBooks {} {
global username password dynix2 books whoami
set books {}
#
# Get the authentication page which gives us the session variable
#
set url $dynix2
set token [::http::geturl $url]
set page [::http::data $token] ; ::http::cleanup $token
set n [regexp -nocase {[?&]session=(.*?)&} $page => session]
if {! $n} {DIE "ERROR: cannot extract session ID from initial page"}
#
# Get the items out page
#
set url "$dynix2&session=$session&sec1=$username&sec2=$password"
set token [::http::geturl $url]
set page [::http::data $token] ; ::http::cleanup $token
#
# Now scrape this page for the books we have out
#
set whoami "?"
regexp {Welcome(.*?)<} $page => whoami
regsub -all { } $whoami " " whoami
set whoami [string trim $whoami]
set start 0
set bcnt 0
while {1} {
set n [regexp -start $start -indices -nocase \
{<a[^>]*mediumboldanchor[^>]*>} $page idxs]
if {! $n} break
incr bcnt
set anchor [eval string range [list $page] $idxs]
set n [regexp {href="(.*?)"} $anchor => link]
if {! $n} {DIE "Cannot parse book $bcnt"}
set link [string map {& &} $link]
regsub {session=.*?&} $link {} link
# Extract title
foreach {a b} $idxs break
set n [regexp -start $b {.(.*?)</a>} $page => title]
if {! $n} {DIE "Cannot parse title for book \#$bcnt"}
set title [string trimright $title "/ "]
# Extract checkout date
set n [regexp -start $b -indices -nocase \
{normalBlackfont2.*?>(.*?)</a>} $page => idxs]
if {! $n} {DIE "Cannot parse checkout date for book \#$bcnt"}
set out [eval string range [list $page] $idxs]
# Extract due date
foreach {a b} $idxs break
set n [regexp -start $b -indices -nocase \
{normalBlackfont2.*?>(.*?)</a>} $page => idxs]
if {! $n} {DIE "Cannot parse due date for book \#$bcnt"}
set due [eval string range [list $page] $idxs]
set due2 [clock scan $due]
# Extract times renewed
foreach {a b} $idxs break
set n [regexp -start $b -indices -nocase \
{normalBlackfont2.*?>(.*?)</a>} $page => idxs]
if {! $n} {DIE "Cannot parse times renewed for book \#$bcnt"}
set renewed [eval string range [list $page] $idxs]
# Save the result
lappend books [list $due2 $title $link $out $due $renewed]
set start $b
}
set books [lsort -integer -index 0 $books]
return
}
proc DIE {msg} {puts stderr $msg; exit}
proc htmlQuote {s} { return [string map { & & < < > > } $s] }
proc DoTxt {} {
global books whoami
set txt "Books checked out for $whoami"
foreach book $books {
foreach {. title link out due renewed} $book break
puts "$title"
puts " out: $out"
puts " due: $due"
}
}
proc DoRSS {} {
global books whoami dynix2 date
set title "Library books out"
if {$whoami ne ""} { append title " for $whoami"}
puts "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"yes\"?>"
puts -nonewline "<!DOCTYPE rss PUBLIC "
puts -nonewline "\"-//Netscape Communications//DTD RSS 0.91//EN\" "
puts "\"http://my.netscape.com/publish/formats/rss-0.91.dtd\">"
puts "<rss version=\"0.91\">"
puts " <channel>"
puts " <title>[htmlQuote $title]</title>"
puts " <lastBuildDate>$date</lastBuildDate>"
puts " <link>[htmlQuote $dynix2]</link>"
puts " <description>Books checked out from the library</description>"
foreach book $books {
foreach {. title link out due renewed} $book break
set txt "Checked out: $out Due back: $due"
puts " <item>"
puts " <title>[htmlQuote $title]</title>"
puts " <link>[htmlQuote $link]</link>"
puts " <description>$txt</description>"
puts " </item>"
}
puts " </channel>"
puts "</rss>"
return
}
set rss 1
if {$argc > 0 && [lindex $argv 0] eq "-t"} {
set rss 0
set argc [llength [set argv [lrange $argv 1 end]]]
}
if {$argc == 1} { foreach username $argv break}
if {$argc == 2} { foreach {username password} $argv break}
if {$argc == 3} { foreach {username password dynix} $argv break}
set dynix2 "$dynix?profile=pac&menu=account&submenu=itemsout"
set date [clock format [clock seconds] -format "%Y-%m-%dT%H:%M:%SZ"]
GetBooks
if {$rss} {
DoRSS
} else {
DoTxt
}