#!/usr/bin/perl
use LWP::UserAgent;
use HTML::Form;
use Date::Manip; # CPAN
use HTML::TreeBuilder; # CPAN
######################################################################
# Send the password form and check for success.
#
# @param $form the form to send.
sub send_pw {
my $form = shift;
print "sending password\n";
# [1] Build request from the form
my $request = $form->click();
# [2] Pass request to the user agent and get a response back
my $response = $ua->request($request);
# [3] Check the outcome of the response
if (! $response->is_success) {
die "Can't send password.\n";
}
return 0;
}
######################################################################
# Bid for an auction.
#
# @param $username the user
# @param $password the password of this user
# @param $form the form to submit.
sub send_bid {
my $ret;
my $username = shift;
my $password = shift;
my $form = shift;
# we start without sucess...
$ret = 1;
print "sending bid\n";
# [1] Build request from the form
my $request = $form->click();
# [2] Pass request to the user agent and get a response back
my $response = $ua->request($request);
# [3] Check the outcome of the response
if (! $response->is_success) {
die "Can't send bid.\n";
}
# [4] Get all forms and find the right one to set the username and password
@forms = HTML::Form->parse($response->content, $response->base());
foreach $form (@forms) {
$username_input = $form->find_input("user");
$password_input = $form->find_input("pass");
# the form must have a user and password field
if ( $username_input != undef && $password_input != undef ) {
$username_input->value($username);
$password_input->value($password);
$ret = send_pw($form);
}
}
return $ret;
}
######################################################################
# Bid for an auction.
#
# @param $number the article to buy
# @param $username the user
# @param $password the password of this user
# @param $maxbid the maximum bid
sub bid {
my $ret;
my $number = shift;
my $username = shift;
my $password = shift;
my $maxbid = shift;
# we start without sucess...
$ret = 1;
# [1] Create a request
my $request = HTTP::Request->new(GET => 'http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=' . $number);
# [2] Pass request to the user agent and get a response back
my $response = $ua->request($request);
# [3] Check the outcome of the response
if (! $response->is_success) {
die "Can't contact ebay for article.\n";
}
# [4] Get all forms and find the right one
@forms = HTML::Form->parse($response->content, $response->base());
foreach $form (@forms) {
$maxbid_input = $form->find_input("maxbid");
# the form must contain a field named "maxbid".
if ( defined($maxbid_input) ) {
$maxbid_input->value($maxbid);
$ret = send_bid($username, $password, $form);
}
}
return $ret;
}
######################################################################
# Get the number of seconds until the auction ends.
#
# @param $number the item number of the auction
sub get_secs_until_end_of_auction {
my $number = shift;
my $remaining_secs = 1000;
# [1] Create a request
my $request = HTTP::Request->new(GET => 'http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=' . $number);
# [2] Pass request to the user agent and get a response back
my $response = $ua->request($request);
# [3] Check the outcome of the response
if (! $response->is_success) {
warn "Can't contact ebay for articel.\n";
}
# [4] Build the HTML tree and look for the title element
my $tree = HTML::TreeBuilder->new;
$tree->parse($response->content);
my $title = $tree->look_down('_tag', 'title');
if ($title) {
# the title contains something like:
# "eBay item 27323776XX (Ends Jun-04-03 14:04:04 PDT) - Laptop..."
$title_string = $title->as_text;
# [4.1] Find out the date inside the brackets
if ( $title_string =~ /\(\S+\s+(.*)\)/ ) {
# [4.1.1] Parse the date of the auction and "today"
$secs_to_end = &UnixDate($1,"%s");
$secs_to_now = &UnixDate("today","%s");
# [4.1.2] Compute the remaining seconds
$remaining_secs = $secs_to_end - $secs_to_now;
}
} else {
warn "No title in article";
}
$tree->delete;
return $remaining_secs;
}
######################################################################
# Wait for the end of the auction.
#
# @param $number the item number of the auction
#
sub wait_for_end_of_auction {
my $ret;
my $number = shift;
print "waiting for end of auction... ";
# [1] Get the number of seconds until the auction ends
$secs = get_secs_until_end_of_auction($number);
# [2] Wait this time
while ($secs > 400 ) {
print " $secs";
sleep(300);
# [2.1] resynchronize again
$secs = get_secs_until_end_of_auction($number);
}
# [3] add 10 more seconds until the auction ends
$secs = $secs + 10;
# [4] ... and wait
print "Last sleep for $secs seconds.\n";
sleep($secs);
}
######################################################################
# Print the winner of the auction.
#
# @param $number the item number of the auction
sub print_winner_of_auction {
my $number = shift;
my $remaining_secs = 1000;
# [1] Create a request
my $request = HTTP::Request->new(GET => 'http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=' . $number);
# [2] Pass request to the user agent and get a response back
my $response = $ua->request($request);
# [3] Check the outcome of the response
if (! $response->is_success) {
warn "Can't contact ebay for articel.\n";
}
# [4] Build the HTML tree and look for the title element
if ( $response->content =~ /ReturnUserEmail&requested=(\w+)&/ ) {
print "The winner is: $1\n";
} else {
warn "No winner could be found.";
}
}
$| = 1;
if ( $#ARGV != 3 ) {
die "usage: ebay.pl number username password maximum-bid\n";
}
$number = shift;
$username = shift;
$password = shift;
$maxbid = shift;
# [1] Build the user agent
$ua = LWP::UserAgent->new;
# [2] Bid
bid($number, $username, $password, $maxbid);
# [3] Wait for end
wait_for_end_of_auction($number);
# [4] Check for success
print_winner_of_auction($number);