#!/usr/local/bin/perl =head1 NAME wishlist - look for cheap stuff on your Amazon wishlist =head1 SYNOPSIS wishlist --token=MYAMAZONTOKEN --wishlist=WISHLISTID --email=god@heaven.mil =head1 DESCRIPTION If you maintain an amazon wishlist, and don't mind buying used books C will go to amazon and look for cheap copies of things you want and email you if cheap stuff is found. The idea is that you put a call to wishlist in your crontab to run every hour looking for bargains. When a bargain appears you'll get an email letting you know what's available. C uses Amazons Web Services so you'll need to get a token, which takes just a second, and is absolutely free. Once you've got a token, you need to figure out what your wishlist ID is. The easiest way to do this is to search for your own wishlist, and look at the URL that links to it. For example mine looks like: http://www.amazon.com/gp/registry/registry.html/102-0255529-0382518?%5Fencoding=UTF8&id=F1K2C8DXQGOE The id=F1K2C8DXQGOE identifies my wishlist ID. With these two pieces of informaton you can run wishlist if you supply an email address to send the notifications to. You can change the limits by which something is regarded as 'cheap' with the remining optiond detailed below. =head1 OPTIONS =head2 --token Your Amazon Web Services token. =head2 --wishlist The ID for your wishlist. =head2 --email The email address to send notifications. =head2 --sale A decimal percentage indicating what you consider cheap off the list price. Defaults to .50 which means if an item is available for less than 50% of the list price it qualifies as as a bargain. =head2 --cheap If an item is less than this it qualifies as a bargain. Default is 5, which means that if an item is available for less than $5.00 you'll get an email. =head2 --window Time window (days) in which you don't want to be renotified. Defaults to 3. This means if an item is cheap you won't get notified about it again for three days. =head1 AUTHORS =over 4 =item * Ed Summers =back =cut use strict; use LWP::Simple; use XML::Simple; use File::Copy; use Mail::Send; use Getopt::Long; use Pod::Usage qw( pod2usage ); my $tmpDir = '/tmp'; ## wishlist and directory options my ( $token, $wishlist, $email, $salePercent, $cheap, $notifyPeriod ) = @_; GetOptions( 'token:s' => \$token, 'wishlist:s' => \$wishlist, 'email:s' => \$email, 'sale:s' => \$salePercent, 'cheap:s' => \$cheap, 'window:i' => \$notifyPeriod ); if ( ! $wishlist or ! $token or ! $email ) { pod2usage( { -verbose => 3 } ); } ## alerts when item drops below this percentage of list my $salePercent = .50 if ! $salePercent; ## alerts when item is below this price my $cheap = 5 if ! $cheap; ## no repeat alert within this amount of days my $notifyPeriod = 3 if ! $notifyPeriod; ## build the amazon web services url my $host = 'xml.amazon.com'; my $path = 'onca/xml2'; my $query = "t=webservices-20" . "&dev-t=$token" . "&type=heavy" . "&f=xml" . "&WishlistSearch=$wishlist"; ## fetch the XML my $wishlist = XMLin( get( "http://$host/$path?$query" ) ); ## cycle through items, and look for good stuff foreach my $item (@{ $wishlist->{ Details } } ) { my $listPrice = $item->{ ListPrice }; my $amazonPrice = $item->{ OurPrice }; my $usedPrice = $item->{ UsedPrice }; ## strip of dollar sign so we can use as numbers map { s/\$// } ($usedPrice,$amazonPrice,$listPrice); ## if a used copy is significantly cheaper if ( $usedPrice and $amazonPrice and ( ($usedPrice/$listPrice) <= $salePercent ) ) { email( $email, $item ); } ## or amazon has it on sale elsif ( $amazonPrice and $listPrice and ( ($amazonPrice/$listPrice) <= $salePercent ) ) { email( $email, $item ); } ## or if it's just plain cheap elsif ( $amazonPrice and $usedPrice and ( $amazonPrice <= $cheap or $usedPrice <= $cheap ) ) { email( $email, $item ); } } ## fire off notification email sub email { my ($email,$item) = @_; ## create a file that will be used to indicate we've seen this sale item ## and how much it cost my ($isbn) = ( $item->{ Isbn } =~ tr/0-9//dc ); my $bookfile = "$tmpDir/amazon_" . $item->{ Isbn }; ## don't email if we've seen this book before in the past N days return() if ( -f $bookfile and -M $bookfile <= $notifyPeriod ); ## touch the file to indicate we're emailing now system( 'touch', $bookfile ); my $msg = new Mail::Send; $msg->to( $email); $msg->subject( "sale: " . $item->{ ProductName } ); my $fh = $msg->open(); $item =~ s{}{}g; print $fh "title: ", $item->{ ProductName }, "\n", "url: ", $item->{ url }, "\n", "list: ", $item->{ ListPrice }, "\n", "amazon: ", $item->{ OurPrice }, "\n", "used: ", $item->{ UsedPrice }, "\n\n"; $fh->close(); }