From bcbf441e09fb502cf64924ff2530fa144bdf52c5 Mon Sep 17 00:00:00 2001 From: Andreas Brachold Date: Mon, 13 Aug 2007 18:41:27 +0000 Subject: * Move files to trunk --- lib/Net/Amazon.pm | 1255 +++++++++++++++++++++++++++++++ lib/Net/Amazon/Attribute/Review.pm | 104 +++ lib/Net/Amazon/Attribute/ReviewSet.pm | 137 ++++ lib/Net/Amazon/Property.pm | 320 ++++++++ lib/Net/Amazon/Property/Book.pm | 152 ++++ lib/Net/Amazon/Property/DVD.pm | 156 ++++ lib/Net/Amazon/Property/Music.pm | 161 ++++ lib/Net/Amazon/Request.pm | 221 ++++++ lib/Net/Amazon/Request/ASIN.pm | 139 ++++ lib/Net/Amazon/Request/Artist.pm | 86 +++ lib/Net/Amazon/Request/Blended.pm | 80 ++ lib/Net/Amazon/Request/BrowseNode.pm | 137 ++++ lib/Net/Amazon/Request/Exchange.pm | 91 +++ lib/Net/Amazon/Request/Keyword.pm | 90 +++ lib/Net/Amazon/Request/Manufacturer.pm | 78 ++ lib/Net/Amazon/Request/Power.pm | 95 +++ lib/Net/Amazon/Request/Seller.pm | 84 +++ lib/Net/Amazon/Request/Similar.pm | 95 +++ lib/Net/Amazon/Request/Sort.pm | 246 ++++++ lib/Net/Amazon/Request/TextStream.pm | 76 ++ lib/Net/Amazon/Request/UPC.pm | 94 +++ lib/Net/Amazon/Request/Wishlist.pm | 89 +++ lib/Net/Amazon/Response.pm | 214 ++++++ lib/Net/Amazon/Response/ASIN.pm | 28 + lib/Net/Amazon/Response/Artist.pm | 29 + lib/Net/Amazon/Response/Blended.pm | 73 ++ lib/Net/Amazon/Response/BrowseNode.pm | 29 + lib/Net/Amazon/Response/Exchange.pm | 81 ++ lib/Net/Amazon/Response/Keyword.pm | 29 + lib/Net/Amazon/Response/Manufacturer.pm | 29 + lib/Net/Amazon/Response/Power.pm | 28 + lib/Net/Amazon/Response/Seller.pm | 78 ++ lib/Net/Amazon/Response/Similar.pm | 28 + lib/Net/Amazon/Response/TextStream.pm | 28 + lib/Net/Amazon/Response/UPC.pm | 40 + lib/Net/Amazon/Response/Wishlist.pm | 29 + lib/Net/Amazon/Result/Seller.pm | 130 ++++ lib/Net/Amazon/Result/Seller/Listing.pm | 146 ++++ lib/Net/IP/Match/Regexp.pm | 293 ++++++++ 39 files changed, 5298 insertions(+) create mode 100644 lib/Net/Amazon.pm create mode 100644 lib/Net/Amazon/Attribute/Review.pm create mode 100644 lib/Net/Amazon/Attribute/ReviewSet.pm create mode 100644 lib/Net/Amazon/Property.pm create mode 100644 lib/Net/Amazon/Property/Book.pm create mode 100644 lib/Net/Amazon/Property/DVD.pm create mode 100644 lib/Net/Amazon/Property/Music.pm create mode 100644 lib/Net/Amazon/Request.pm create mode 100644 lib/Net/Amazon/Request/ASIN.pm create mode 100644 lib/Net/Amazon/Request/Artist.pm create mode 100644 lib/Net/Amazon/Request/Blended.pm create mode 100644 lib/Net/Amazon/Request/BrowseNode.pm create mode 100644 lib/Net/Amazon/Request/Exchange.pm create mode 100644 lib/Net/Amazon/Request/Keyword.pm create mode 100644 lib/Net/Amazon/Request/Manufacturer.pm create mode 100644 lib/Net/Amazon/Request/Power.pm create mode 100644 lib/Net/Amazon/Request/Seller.pm create mode 100644 lib/Net/Amazon/Request/Similar.pm create mode 100644 lib/Net/Amazon/Request/Sort.pm create mode 100644 lib/Net/Amazon/Request/TextStream.pm create mode 100644 lib/Net/Amazon/Request/UPC.pm create mode 100644 lib/Net/Amazon/Request/Wishlist.pm create mode 100644 lib/Net/Amazon/Response.pm create mode 100644 lib/Net/Amazon/Response/ASIN.pm create mode 100644 lib/Net/Amazon/Response/Artist.pm create mode 100644 lib/Net/Amazon/Response/Blended.pm create mode 100644 lib/Net/Amazon/Response/BrowseNode.pm create mode 100644 lib/Net/Amazon/Response/Exchange.pm create mode 100644 lib/Net/Amazon/Response/Keyword.pm create mode 100644 lib/Net/Amazon/Response/Manufacturer.pm create mode 100644 lib/Net/Amazon/Response/Power.pm create mode 100644 lib/Net/Amazon/Response/Seller.pm create mode 100644 lib/Net/Amazon/Response/Similar.pm create mode 100644 lib/Net/Amazon/Response/TextStream.pm create mode 100644 lib/Net/Amazon/Response/UPC.pm create mode 100644 lib/Net/Amazon/Response/Wishlist.pm create mode 100644 lib/Net/Amazon/Result/Seller.pm create mode 100644 lib/Net/Amazon/Result/Seller/Listing.pm create mode 100644 lib/Net/IP/Match/Regexp.pm (limited to 'lib/Net') diff --git a/lib/Net/Amazon.pm b/lib/Net/Amazon.pm new file mode 100644 index 0000000..4630c11 --- /dev/null +++ b/lib/Net/Amazon.pm @@ -0,0 +1,1255 @@ +##################################################################### +package Net::Amazon; +###################################################################### +# Mike Schilli , 2003 +###################################################################### + +use 5.006; +use strict; +use warnings; + +our $VERSION = '0.34'; +our @CANNED_RESPONSES = (); + +use LWP::UserAgent; +use HTTP::Request::Common; +use XML::Simple; +use Data::Dumper; +use URI; +use Log::Log4perl qw(:easy get_logger); +use Time::HiRes qw(usleep gettimeofday tv_interval); + +# Each key represents a search() type, and each value indicates which +# Net::Amazon::Request:: class to use to handle it. +use constant SEARCH_TYPE_CLASS_MAP => { + artist => 'Artist', + asin => 'ASIN', + blended => 'Blended', + browsenode => 'BrowseNode', + exchange => 'Exchange', + keyword => 'Keyword', + manufacturer => 'Manufacturer', + power => 'Power', + seller => 'Seller', + similar => 'Similar', + textstream => 'TextStream', + upc => 'UPC', + wishlist => 'Wishlist', +}; + + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + if(! exists $options{token}) { + die "Mandatory paramter 'token' not defined"; + } + + if(! exists $options{affiliate_id}) { + $options{affiliate_id} = "webservices-20"; + } + + my $self = { + strict => 1, + response_dump => 0, + rate_limit => 1.0, # 1 req/sec + max_pages => 5, + ua => LWP::UserAgent->new(), + %options, + }; + + help_xml_simple_choose_a_parser(); + + bless $self, $class; +} + +################################################## +sub search { +################################################## + my($self, %params) = @_; + + foreach my $key ( keys %params ) { + next unless ( my $class = SEARCH_TYPE_CLASS_MAP->{$key} ); + + return $self->_make_request($class, \%params); + } + + # FIX? + # This seems like it really should be a die() instead...this is + # indicative of a programming problem. Generally speaking, it's + # best to issue warnings from a module--you can't be sure that the + # client has a stderr to begin with, or that he wants errors + # spewed to it. + warn "No Net::Amazon::Request type could be determined"; + + return undef; +} + +################################################## +sub intl_url { +################################################## + my($self, $url) = @_; + + # Every time Amazon is adding a new country to the web service, + # they're rolling a dice on what the new URL is going to be. + # This method will try to keep up with their crazy mappings. + + if(! exists $self->{locale}) { + return $url; + } + + if ($self->{locale} eq "jp") { + $url =~ s/\.com/.co.jp/; + return $url; + } + + if($self->{locale} eq "uk" or + $self->{locale} eq "de") { + $url =~ s/xml/xml-eu/; + return $url; + } + + return $url; +} + +################################################## +sub request { +################################################## + my($self, $request) = @_; + + my $AMZN_WISHLIST_BUG_ENCOUNTERED = 0; + + my $resp_class = $request->response_class(); + + eval "require $resp_class;" or + die "Cannot find '$resp_class'"; + + my $res = $resp_class->new(); + + my $url = URI->new($self->intl_url($request->amzn_xml_url())); + my $page = $request->{page}; + my $ref; + + { + my %params = $request->params(); + $params{page} = $page; + $params{locale} = $self->{locale} if exists $self->{locale}; + + $url->query_form( + 'dev-t' => $self->{token}, + 't' => $self->{affiliate_id}, + map { $_, $params{$_} } sort keys %params, + ); + + my $urlstr = $url->as_string; + my $xml = fetch_url($self, $urlstr, $res); + + if(!defined $xml) { + return $res; + } + + DEBUG(sub { "Received [ " . $xml . "]" }); + + # Let the response class parse the XML + $ref = $res->xml_parse($xml); + + # DEBUG(sub { Data::Dumper::Dumper($ref) }); + + if(! defined $ref) { + ERROR("Invalid XML"); + $res->messages( [ "Invalid XML" ]); + $res->status(""); + return $res; + } + + if(exists $ref->{TotalPages}) { + INFO("Page $page/$ref->{TotalPages}"); + } + + if(exists $ref->{TotalResults}) { + $res->total_results( $ref->{TotalResults} ); + } + + if(exists $ref->{ErrorMsg}) { + + if($AMZN_WISHLIST_BUG_ENCOUNTERED && + $ref->{ErrorMsg} =~ /no exact matches/) { + DEBUG("End of buggy wishlist detected"); + last; + } + + if (ref($ref->{ErrorMsg}) eq "ARRAY") { + # multiple errors, set arrary ref + $res->messages( $ref->{ErrorMsg} ); + } else { + # single error, create array + $res->messages( [ $ref->{ErrorMsg} ] ); + } + + ERROR("Fetch Error: " . $res->message ); + $res->status(""); + return $res; + } + + my $new_items = $res->xmlref_add($ref); + DEBUG("Received valid XML ($new_items items)"); + + # Stop if we've fetched max_pages already + if($self->{max_pages} <= $page) { + DEBUG("Fetched max_pages ($self->{max_pages}) -- stopping"); + last; + } + + # Work around the Amazon bug not setting TotalPages properly + # for wishlists + if(ref($res) =~ /Wishlist/ and + !exists $ref->{TotalPages} and + $new_items == 10 + ) { + $AMZN_WISHLIST_BUG_ENCOUNTERED = 1; + DEBUG("Trying to fetch additional wishlist page (AMZN bug)"); + $page++; + redo; + } + + if(exists $ref->{TotalPages} and + $ref->{TotalPages} > $page) { + DEBUG("Page $page of $ref->{TotalPages} fetched - continuing"); + $page++; + redo; + } + + # We're gonna fall out of this loop here. + } + + $res->status(1); + # We have a valid response, so if TotalResults isn't set, + # we most likely have a single response + $res->total_results(1) unless defined $res->total_results(); + return $res; +} + +################################################## +sub fetch_url { +################################################## + my($self, $url, $res) = @_; + + my $max_retries = 2; + + INFO("Fetching $url"); + + if(@CANNED_RESPONSES) { + INFO("Serving canned response (testing)"); + return shift @CANNED_RESPONSES; + } + + if(exists $self->{cache}) { + my $resp = $self->{cache}->get($url); + if(defined $resp) { + INFO("Serving from cache"); + return $resp; + } + + INFO("Cache miss"); + } + + my $ua = $self->{ua}; + $ua->env_proxy(); + + my $resp; + + { + # wait up to a second before the next request so + # as to not violate Amazon's 1 query per second + # rule (or the configured rate_limit). + $self->pause() if $self->{strict}; + + $resp = $ua->request(GET $url); + + $self->reset_timer() if $self->{strict}; + + if($resp->is_error) { + # retry on 503 Service Unavailable errors + if ($resp->code == 503) { + if ($max_retries-- >= 0) { + INFO("Temporary Amazon error 503, retrying"); + redo; + } else { + INFO("Out of retries, giving up"); + $res->status(""); + $res->messages( [ "Too many temporary Amazon errors" ] ); + return undef; + } + } else { + $res->status(""); + $res->messages( [ $resp->message ] ); + return undef; + } + } + + if($self->{response_dump}) { + my $dumpfile = "response-$self->{response_dump}.txt"; + open FILE, ">$dumpfile" or die "Cannot open $dumpfile"; + print FILE $resp->content(); + close FILE; + $self->{response_dump}++; + } + + if($resp->content =~ // && + $resp->content =~ /Please retry/i) { + if($max_retries-- >= 0) { + INFO("Temporary Amazon error, retrying"); + redo; + } else { + INFO("Out of retries, giving up"); + $res->status(""); + $res->messages( [ "Too many temporary Amazon errors" ] ); + return undef; + } + } + } + + if(exists $self->{cache}) { + $self->{cache}->set($url, $resp->content()); + } + + return $resp->content(); +} + +################################################## +# Poor man's Class::Struct +################################################## +sub make_accessor { +################################################## + my($package, $name) = @_; + + no strict qw(refs); + + my $code = <{$name} = \$value; + } + if(exists \$self->{$name}) { + return (\$self->{$name}); + } else { + return ""; + } + } +EOT + if(! defined *{"$package\::$name"}) { + eval $code or die "$@"; + } +} + +################################################## +# Make accessors for arrays +################################################## +sub make_array_accessor { +################################################## + my($package, $name) = @_; + + no strict qw(refs); + + my $code = <{$name} = \$nameref; + } else { + \$self->{$name} = [\$nameref]; + } + } + # Return a list + if(exists \$self->{$name} and + ref \$self->{$name} eq "ARRAY") { + return \@{\$self->{$name}}; + } + + return undef; + } +EOT + + if(! defined *{"$package\::$name"}) { + eval $code or die "$@"; + } +} + +################################################## +sub artist { +################################################## + my($self, $nameref) = @_; + + # Only return the first artist + return ($self->artists($nameref))[0]; +} + + +################################################## +sub xmlref_add { +################################################## + my($self, $xmlref) = @_; + + my $nof_items_added = 0; + + # Push a nested hash structure, retrieved via XMLSimple, onto the + # object's internal 'xmlref' entry, which holds a ref to an array, + # whichs elements are refs to hashes holding an item's attributes + # (like OurPrice etc.) + + #DEBUG("xmlref_add ", Data::Dumper::Dumper($xmlref)); + + unless(ref($self->{xmlref}) eq "HASH" && + ref($self->{xmlref}->{Details}) eq "ARRAY") { + $self->{xmlref}->{Details} = []; + } + + if(ref($xmlref->{Details}) eq "ARRAY") { + # Is it an array of items? + push @{$self->{xmlref}->{Details}}, @{$xmlref->{Details}}; + $nof_items_added = scalar @{$xmlref->{Details}}; + } else { + # It is a single item + push @{$self->{xmlref}->{Details}}, $xmlref->{Details}; + $nof_items_added = 1; + } + + #DEBUG("xmlref_add (after):", Data::Dumper::Dumper($self)); + return $nof_items_added; +} + +################################################## +sub help_xml_simple_choose_a_parser { +################################################## + + eval "require XML::Parser"; + unless($@) { + $XML::Simple::PREFERRED_PARSER = "XML::Parser"; + return; + } + + eval "require XML::SAX::PurePerl"; + unless($@) { + $XML::Simple::PREFERRED_PARSER = "XML::SAX::PurePerl"; + return; + } +} + +################################################## +# This timer makes sure we don't query Amazon more +# than once a second. +################################################## +sub reset_timer { +################################################## + + my $self = shift; + $self->{t0} = [gettimeofday]; +} + +################################################## +# Pause for up to a second if necessary. +################################################## +sub pause { +################################################## + + my $self = shift; + return unless ($self->{t0}); + + my $t1 = [gettimeofday]; + my $dur = (1.0/$self->{rate_limit} - + tv_interval($self->{t0}, $t1)) * 1000000; + if($dur > 0) { + # Use a pseudo subclass for the logger, since the app + # might not want to log that as 'ERROR'. Log4perl's + # inheritance mechanism makes sure it does the right + # thing for the current class. + my $logger = get_logger(__PACKAGE__ . "::RateLimit"); + $logger->error("Ratelimiting: Sleeping $dur microseconds"); + usleep($dur); + } +} + +## +## 'PRIVATE' METHODS +## + +# $self->_make_request( TYPE, PARAMS ) +# +# Takes a TYPE that corresponds to a Net::Amazon::Request +# class, require()s that class, instantiates it, and returns +# the result of that instance's request() method. +# +sub _make_request { + my ($self, $type, $params) = @_; + + my $class = "Net::Amazon::Request::$type"; + + eval "require $class"; + + my $req = $class->new(%{$params}); + + return $self->request($req); +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon - Framework for accessing amazon.com via SOAP and XML/HTTP + +=head1 SYNOPSIS + + use Net::Amazon; + + my $ua = Net::Amazon->new(token => 'YOUR_AMZN_TOKEN'); + + # Get a request object + my $response = $ua->search(asin => '0201360683'); + + if($response->is_success()) { + print $response->as_string(), "\n"; + } else { + print "Error: ", $response->message(), "\n"; + } + +=head1 ABSTRACT + + Net::Amazon provides an object-oriented interface to amazon.com's + SOAP and XML/HTTP interfaces. This way it's possible to create applications + using Amazon's vast amount of data via a functional interface, without + having to worry about the underlying communication mechanism. + +=head1 DESCRIPTION + +C works very much like C: First you define a useragent +like + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN', + max_pages => 3, + ); + +which you pass your personal amazon developer's token (can be obtained +from L) and (optionally) the maximum number of +result pages the agent is going to request from Amazon in case all +results don't fit on a single page (typically holding 20 items). Note that +each new page requires a minimum delay of 1 second to comply with Amazon's +one-query-per-second policy. + +According to the different search methods on Amazon, there's a bunch +of different request types in C. The user agent's +convenience method C triggers different request objects, +depending on which parameters you pass to it: + +=over 4 + +=item C<< $ua->search(asin => "0201360683") >> + +The C parameter has Net::Amazon search for an item with the +specified ASIN. If the specified value is an arrayref instead of a single +scalar, like in + + $ua->search(asin => ["0201360683", "0596005083"]) + +then a search for multiple ASINs is performed, returning a list of +results. + +=item C<< $ua->search(artist => "Rolling Stones") >> + +The C parameter has the user agent search for items created by +the specified artist. Can return many results. + +=item C<< $ua->search(browsenode=>"4025", mode=>"books" [, keywords=>"perl"]) >> + +Returns a list of items by category ID (node). For example node "4025" +is the CGI books category. You can add a keywords parameter to filter +the results by that keyword. + +=item C<< $ua->search(exchange => 'Y04Y3424291Y2398445') >> + +Returns an item offered by a third-party seller. The item is referenced +by the so-called I. + +=item C<< $ua->search(keyword => "perl xml", mode => "books") >> + +Search by keyword, mandatory parameters C and C. +Can return many results. + +=item C<< $ua->search(wishlist => "1XL5DWOUFMFVJ") >> + +Search for all items in a specified wishlist. +Can return many results. + +=item C<< $ua->search(upc => "075596278324", mode => "music") >> + +Music search by UPC (product barcode), mandatory parameter C. +C has to be set to C. Returns at most one result. + +=item C<< $ua->search(similar => "0201360683") >> + +Search for all items similar to the one represented by the ASIN provided. +Can return many results. + +=item C<< $ua->search(power => "subject: perl and author: schwartz", mode => "books") >> + +Initiate a power search for all books matching the power query. +Can return many results. See L for details. + +=item C<< $ua->search(manufacturer => "o'reilly", mode => "books") >> + +Initiate a search for all items made by a given manufacturrer. +Can return many results. See L +for details. + +=item C<< $ua->search(blended => "Perl") >> + +Initiate a search for items in all categories. + +=item C<< $ua->search(seller => "A2GXAGU54VOP7") >> + +Start a search on items sold by a specific third-party seller, referenced +by its ID (not seller name). + +=item C<< $ua->search(textstream => "Blah blah Rolling Stones blah blah") >> + +Find items related to keywords within a text stream. + +=back + +The user agent's C method returns a response object, which can be +checked for success or failure: + + if($resp->is_success()) { + print $resp->as_string(); + } else { + print "Error: ", $resp->message(), "\n"; + } + +In case the request for an item search +succeeds, the response contains one or more +Amazon 'properties', as it calls the products found. +All matches can be retrieved from the Response +object using it's C method. + +In case the request fails, the response contains one or more +error messages. The response object's C method will +return it (or them) as a single string, while C (notice +the plural) will +return a reference to an array of message strings. + +Response objects always have the methods +C, +C, +C, +C, +C and +C available. + +C returns the total number of results the search +yielded. +C returns one or more C objects of type +C (or one of its subclasses like +C, C +or Net::Amazon::Property::DVD), each +of which features accessors named after the attributes of the product found +in Amazon's database: + + for ($resp->properties) { + print $_->Asin(), " ", + $_->OurPrice(), "\n"; + } + +In scalar context, C just returns the I +C object found. +Commonly available accessors to C objects are +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, +C. +For details, check L. + +Also, the specialized classes C and +C feature convenience methods like +C (returning the list of authors of a book) or +C for CDs, returning the album title. + +Customer reviews: +Every property features a C method which returns a +C object, which in turn offers +a list of C objects. Check the respective +man pages for details on what's available. + +=head2 Requests behind the scenes + +C's C method is just a convenient way to +create different kinds of request objects behind the scenes and +trigger them to send requests to Amazon. + +Depending on the parameters fed to the C method, C will +determine the kind of search requested and create one of the following +request objects: + +=over 4 + +=item Net::Amazon::Request::ASIN + +Search by ASIN, mandatory parameter C. +Returns at most one result. + +=item Net::Amazon::Request::Artist + +Music search by Artist, mandatory parameter C. +Can return many results. + +=item Net::Amazon::Request::BrowseNode + +Returns category (node) listing. Mandatory parameters C +(must be numeric) and C. Can return many results. + +=item Net::Amazon::Request::Keyword + +Keyword search, mandatory parameters C and C. +Can return many results. + +=item Net::Amazon::Request::UPC + +Music search by UPC (product barcode), mandatory parameter C. +C has to be set to C. Returns at most one result. + +=item Net::Amazon::Request::Blended + +'Blended' search on a keyword, resulting in matches across the board. +No 'mode' parameter is allowed. According to Amazon's developer's kit, +this will result in up to three matches per category and can yield +a total of 45 matches. + +=item Net::Amazon::Request::Power + +Understands power search strings. See L +for details. Mandatory parameter C. + +=item Net::Amazon::Request::Manufacturer + +Searches for all items made by a given manufacturer. Mandatory parameter +C. + +=item Net::Amazon::Request::Similar + +Finds items similar to a given one. + +=item Net::Amazon::Request::Wishlist + +Find item on someone's wish list. + +=item Net::Amazon::Request::Seller + +Searches for a third-party seller on Amazon by seller ID. This search +is different than the previous ones, since it doesn't return Amazon +items, but a single seller record. Don't use the C method +on the response, use C instead, which returns a +L object. Check the manpage for details. + +=item Net::Amazon::Request::Exchange + +Searches for items offered by third-party sellers. Items are referenced +by their so-called I. +Similar to L, +this request doesn't return a list of Amazon properties, so please use +C instead, which will return a I +L item. +Check the manpage for details on what attributes are available there. + +=back + +Check the respective man pages for details on these request objects. +Request objects are typically created like this (with a Keyword query +as an example): + + my $req = Net::Amazon::Request::Keyword->new( + keyword => 'perl', + mode => 'books', + ); + +and are handed over to the user agent like that: + + # Response is of type Net::Amazon::Response::ASIN + my $resp = $ua->request($req); + +The convenient C method just does these two steps in one. + +=head2 METHODS + +=over 4 + +=item $ua = Net::Amazon->new(token => $token, ...) + +Create a new Net::Amazon useragent. C<$token> is the value of +the mandatory Amazon developer's token, which can be obtained from +L. + +Additional optional parameters: + +=over 4 + +=item C<< max_pages => $max_pages >> + +Sets how many +result pages the module is supposed to fetch back from Amazon, which +only sends back 10 results per page. +Since each page requires a new query to Amazon, at most one query +per second will be made in C mode to comply with Amazon's terms +of service. This will impact performance if you perform a search +returning many pages of results. + +=item C<< affiliate_id => $affiliate_id >> + +your Amazon affiliate ID, if you have one. It defaults to +C which is currently (as of 06/2003) +required by Amazon. + +=item C<< strict => 1 >> + +Makes sure that C complies with Amazon's terms of service +by limiting the number of outgoing requests to 1 per second. Defaults +to C<1>, enabling rate limiting as defined via C. + +=item C<< rate_limit => $reqs_per_sec >> + +Sets the rate limit to C<$reqs_per_sec> requests per second if +rate limiting has been enabled with C (see above). +Defaults to C<1>, limiting the number of outgoing requests to +1 per second. + +=item C<< $resp = $ua->request($request) >> + +Sends a request to the Amazon web service. C<$request> is of a +C type and C<$response> will be of the +corresponding C type. + +=back + +=head2 Accessing foreign Amazon Catalogs + +As of this writing (07/2003), Amazon also offers its web service for +the UK, Germany, and Japan. Just pass in + + locale => 'uk' + locale => 'de' + locale => 'jp' + +respectively to C's constructor C and instead of returning +results sent by the US mothership, it will query the particular country's +catalog and show prices in (gack!) local currencies. + +=head2 EXAMPLE + +Here's a full-fledged example doing a artist search: + + use Net::Amazon; + use Net::Amazon::Request::Artist; + use Data::Dumper; + + die "usage: $0 artist\n(use Zwan as an example)\n" + unless defined $ARGV[0]; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN', + ); + + my $req = Net::Amazon::Request::Artist->new( + artist => $ARGV[0], + ); + + # Response is of type Net::Amazon::Artist::Response + my $resp = $ua->request($req); + + if($resp->is_success()) { + print $resp->as_string, "\n"; + } else { + print $resp->message(), "\n"; + } + +And here's one displaying someone's wishlist: + + use Net::Amazon; + use Net::Amazon::Request::Wishlist; + + die "usage: $0 wishlist_id\n" . + "(use 1XL5DWOUFMFVJ as an example)\n" unless $ARGV[0]; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN', + ); + + my $req = Net::Amazon::Request::Wishlist->new( + id => $ARGV[0] + ); + + # Response is of type Net::Amazon::ASIN::Response + my $resp = $ua->request($req); + + if($resp->is_success()) { + print $resp->as_string, "\n"; + } else { + print $resp->message(), "\n"; + } + +=head1 CACHING + +Responses returned by Amazon's web service can be cached locally. +C's C method accepts a reference to a C +object. C (or one of its companions like C, +C, etc.) can be downloaded from CPAN, please check their +documentation for details. In fact, any other type of cache +implementation will do as well, see the requirements below. + +Here's an example utilizing a file cache which causes C to +cache responses for 30 minutes: + + use Cache::File; + + my $cache = Cache::File->new( + cache_root => '/tmp/mycache', + default_expires => '30 min', + ); + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN', + cache => $cache, + ); + +C uses I caching only, errors won't be cached. +Erroneous requests will be sent to Amazon every time. Positive cache +entries are keyed by the full URL used internally by requests submitted +to Amazon. + +Caching isn't limited to the C class. Any cache object which +adheres to the following interface can be used: + + # Set a cache value + $cache->set($key, $value); + + # Return a cached value, 'undef' if it doesn't exist + $cache->get($key); + +=head1 PROXY SETTINGS + +C uses C under the hood to send +web requests to Amazon's web site. If you're in an environment where +all Web traffic goes through a proxy, there's two ways to configure that. + +First, C picks up proxy settings from environment variables: + + export http_proxy=http://proxy.my.place:8080 + +in the surrounding shell or setting + + $ENV{http_proxy} = "http://proxy.my.place:8080"; + +in your Perl script +will route all requests through the specified proxy. + +Secondly, you can +pass a user agent instance to Net::Amazon's constructor: + + use Net::Amazon; + use LWP::UserAgent; + + my $ua = LWP::UserAgent->new(); + my $na = Net::Amazon->new(ua => $ua, token => 'YOUR_AMZN_TOKEN'); + # ... + +This way, you can configure C<$ua> up front before Net::Amazon will use it. + +=head1 DEBUGGING + +If something's going wrong and you want more verbosity, just bump up +C's logging level. C comes with C +statements embedded, which are disabled by default. However, if you initialize +C, e.g. like + + use Net::Amazon; + use Log::Log4perl qw(:easy); + + Log::Log4perl->easy_init($DEBUG); + my Net::Amazon->new(); + # ... + +you'll see what's going on behind the scenes, what URLs the module +is requesting from Amazon and so forth. Log::Log4perl allows all kinds +of fancy stuff, like writing to a file or enabling verbosity in certain +parts only -- check http://log4perl.sourceforge.net for details. + +=head1 LIVE TESTING + +Results returned by Amazon can be incomplete or simply wrong at times, +due to their "best effort" design of the service. This is why the test +suite that comes with this module has been changed to perform its test +cases against canned data. If you want to perform the tests against +the live Amazon servers instead, just set the environment variable + + NET_AMAZON_LIVE_TESTS=1 + +=head1 WHY ISN'T THERE SUPPORT FOR METHOD XYZ? + +Because nobody wrote it yet. If Net::Amazon doesn't yet support a method +advertised on Amazon's web service, you could help us out. Net::Amazon +has been designed to be expanded over time, usually it only takes a couple +of lines to support a new method, the rest is done via inheritance within +Net::Amazon. + +Here's the basic plot: + +=over 4 + +=item * + +Get Net::Amazon from CVS. Use + + # (Just hit enter when prompted for a password) + cvs -d:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon login + cvs -z3 -d:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon co Net-Amazon + +If this doesn't work, just use the latest distribution from +net-amazon.sourceforge.net. + +=item * + +Write a new Net::Amazon::Request::XYZ package, start with this template + + ###################################### + package Net::Amazon::Request::XYZ; + ###################################### + use base qw(Net::Amazon::Request); + + ###################################### + sub new { + ###################################### + my($class, %options) = @_; + + if(!exists $options{XYZ_option}) { + die "Mandatory parameter 'XYZ_option' not defined"; + } + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate + } + +and add documentation. Then, create a new Net::Amazon::Response::XYZ module: + + ############################## + package Net::Amazon::Response; + ############################## + use base qw(Net::Amazon::Response); + + use Net::Amazon::Property; + + ############################## + sub new { + ############################## + my($class, %options) = @_; + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate + } + +and also add documentation to it. Then, add the line + + use Net::Amazon::Request::XYZ; + +to Net/Amazon.pm. + +=back + +And that's it! Again, don't forget the I part. Modules +without documentation are of no use to anybody but yourself. + +Check out the different Net::Amazon::Request::* +and Net::Amazon::Response modules in the distribution if you need to adapt +your new module to fulfil any special needs, like a different Amazon URL +or a different way to handle the as_string() method. Also, post +and problems you might encounter to the mailing list, we're gonna help you +out. + +If possible, provide a test case for your extension. When finished, send +a patch to the mailing list at + + net-amazon-devel@lists.sourceforge.net + +and if it works, I'll accept it and will work it into the main distribution. +Your name will show up in the contributor's list below (unless you tell +me otherwise). + +=head2 SAMPLE SCRIPTS + +There's a number of useful scripts in the distribution's eg/ directory. +Take C for example, written by Martin Streicher +Emartin.streicher@apress.comE: I lets you perform +a I using Amazon's query language. To search for all books +written by Randal Schwartz about Perl, call this from the command line: + + power 'author: schwartz subject: perl' + +Note that you need to quote the query string to pass it as one argument +to C. If a power search returns more results than you want to +process at a time, just limit the number of pages, telling C +which page to start at (C<-s>) and which one to finish with (C<-f>). +Here's a search for all books on the subject C, limited +to the first 10 pages: + + power -s 1 -f 10 'subject: computer' + +Check out the script C in eg/ for more options. + +=head2 HOW TO SEND ME PATCHES + +If you want me to include your modification or enhancement +in the distribution of Net::Amazon, please do the following: + +=over 4 + +=item * + +Work off the latest CVS version. Here's the steps to get it: + + CVSROOT=:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon + export CVSROOT + cvs login (just hit Enter) + cvs co Net-Amazon + +This will create a new C directory with the latest +development version of C on your local machine. + +=item * + +Apply your changes to this development tree. + +=item * + +Run a diff between the tree and your changes it in this way: + + cd Net-Amazon + cvs diff -Nau >patch_to_mike.txt + +=item * + +Email me C. If your patch works (and you've included +test cases and documentation), I'll apply it on the spot. + +=back + +=head1 INSTALLATION + +C depends on Log::Log4perl, which can be pulled from CPAN by +simply saying + + perl -MCPAN -eshell 'install Log::Log4perl' + +Also, it needs LWP::UserAgent and XML::Simple 2.x, which can be obtained +in a similar way. + +Once all dependencies have been resolved, C installs with +the typical sequence + + perl Makefile.PL + make + make test + make install + +Make sure you're connected to the Internet while running C +because it will actually contact amazon.com and run a couple of live tests. + +The module's distribution tarball and documentation are available at + + http://perlmeister.com/devel/#amzn + +and on CPAN. + +=head1 SEE ALSO + +The following modules play well within the C framework: + +=over 4 + +=item C + +by David Emery Edave@skiddlydee.comE provides a complete API for +creating Amazon shopping carts on a local site, managing them and finally +submitting them to Amazon for checkout. It is available on CPAN. + +=back + +=head1 CONTACT + +The C project's home page is hosted on + + http://net-amazon.sourceforge.net + +where you can find documentation, news and the latest development and +stable releases for download. If you have questions about how to +use C, want to report a bug or just participate in its +development, please send a message to the mailing +list net-amazon-devel@lists.sourceforge.net + +=head1 AUTHOR + +Mike Schilli, Ena@perlmeister.comE (Please contact me via the mailing list: net-amazon-devel@lists.sourceforge.net ) + +Contributors (thanks y'all!): + + Andy Grundman + Barnaby Claydon + Batara Kesuma + Bill Fitzpatrick + Brian + Brian Hirt + Dan Kreft + Dan Sully + Jackie Hamilton + Konstantin Gredeskoul + Lance Cleveland + Martha Greenberg + Martin Streicher + Mike Evron + Padraic Renaghan + rayg + Robert Graff + Robert Rothenberg + Steve Rushe + Tatsuhiko Miyagawa + Tony Bowden + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003, 2004 by Mike Schilli Ena@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Attribute/Review.pm b/lib/Net/Amazon/Attribute/Review.pm new file mode 100644 index 0000000..5a5d094 --- /dev/null +++ b/lib/Net/Amazon/Attribute/Review.pm @@ -0,0 +1,104 @@ +###################################################################### +package Net::Amazon::Attribute::Review; +###################################################################### +use warnings; +use strict; +use Log::Log4perl qw(:easy); +use base qw(Net::Amazon); + +__PACKAGE__->make_accessor($_) for qw(rating summary comment); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = { + rating => "", + summary => "", + comment => "", + %options, + }; + + bless $self, $class; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + for(qw(Rating Summary Comment)) { + my $method = lc($_); + if($xmlref->{$_}) { + $self->$method($xmlref->{$_}); + } else { + #LOGWARN "No '$_'"; + return undef; + } + } +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Attribute::Review - Customer Review Class + +=head1 SYNOPSIS + + use Net::Amazon::Attribute::Review; + my $rev = Net::Amazon::Attribute::Review->new( + 'rating' => $rating, + 'summary' => $summary, + 'comment' => $comment, + ); + +=head1 DESCRIPTION + +C holds customer reviews. + +=head2 METHODS + +=over 4 + +=item rating() + +Accessor for the numeric value of the rating. + +=item summary() + +Accessor for the string value of the summary. + +=item comment() + +Accessor for the string value of the customer comment. + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + +__END__ + + 4.33 + 6 + + 4 + Good introduction to Perl, and great reference + From its corny title you might expect another one of those + diff --git a/lib/Net/Amazon/Attribute/ReviewSet.pm b/lib/Net/Amazon/Attribute/ReviewSet.pm new file mode 100644 index 0000000..29a34e6 --- /dev/null +++ b/lib/Net/Amazon/Attribute/ReviewSet.pm @@ -0,0 +1,137 @@ +###################################################################### +package Net::Amazon::Attribute::ReviewSet; +###################################################################### +use warnings; +use strict; +use Log::Log4perl qw(:easy); +use Net::Amazon::Attribute::Review; +use base qw(Net::Amazon); + +__PACKAGE__->make_accessor($_) for qw(average_customer_rating total_reviews); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = { + reviews => [], # list of reviews + }; + + bless $self, $class; +} + +########################################### +sub add_review { +########################################### + my($self, $review) = @_; + + if(ref $review ne "Net::Amazon::Attribute::Review") { + warn "add_review called with type ", ref $review; + return undef; + } + + push @{$self->{reviews}}, $review; +} + +########################################### +sub reviews { +########################################### + my($self) = @_; + + return @{$self->{reviews}}; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + my @pairs = qw(AvgCustomerRating average_customer_rating + TotalCustomerReviews total_reviews); + + while(my($field, $method) = splice @pairs, 0, 2) { + + if(defined $xmlref->{$field}) { + DEBUG "Setting $field via $method to $xmlref->{$field}"; + $self->$method($xmlref->{$field}); + } else { + LOGWARN "No '$field'"; + return undef; + } + } + + if(ref $xmlref->{CustomerReview} ne "ARRAY") { + $xmlref->{CustomerReview} = [$xmlref->{CustomerReview}]; + } + + for my $review_xmlref (@{$xmlref->{CustomerReview}}) { + my $review = Net::Amazon::Attribute::Review->new(); + $review->init_via_xmlref($review_xmlref); + DEBUG "Adding review ", $review->summary(); + $self->add_review($review); + } +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Attribute::ReviewSet - A set of customer reviews + +=head1 SYNOPSIS + + use Net::Amazon::Attribute::ReviewSet; + my $rev = Net::Amazon::Attribute::Review->new( + average_customer_rating => $avg, + total_reviews => $total, + ); + +=head1 DESCRIPTION + +C holds a list of customer +reviews, each of type C. + +=head2 METHODS + +=over 4 + +=item C<< $self->reviews() >> + +Returns a list of C objects. + +=item C<< $self->average_customer_rating() >> + +Accessor for the average customer rating, a numeric value. + +=item C<< $self->total_reviews() >> + +Accessor for the total number of reviews. Please note that this +might not be equal to the number of reviews held in the list, since +there might be less customer reviews than total reviews (reviews +can also be non-customer-reviews, but they're not available by +the web service as of Aug 2003). + +=item C<< $self->add_review($rev) >> + +Add a C object to the list. +(Used internally only). + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Property.pm b/lib/Net/Amazon/Property.pm new file mode 100644 index 0000000..6c06957 --- /dev/null +++ b/lib/Net/Amazon/Property.pm @@ -0,0 +1,320 @@ +###################################################################### +package Net::Amazon::Property; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon); + +use Net::Amazon::Property::DVD; +use Net::Amazon::Property::Book; +use Net::Amazon::Property::Music; +use Net::Amazon::Attribute::ReviewSet; +use Data::Dumper; +use Log::Log4perl qw(:easy); + +use warnings; +use strict; + +our @DEFAULT_ATTRIBUTES = qw( + OurPrice ImageUrlLarge ImageUrlMedium ImageUrlSmall + ReleaseDate Catalog Asin url Manufacturer UsedPrice + ListPrice ProductName Availability SalesRank + Media NumMedia ProductDescription + CollectiblePrice CollectibleCount NumberOfOfferings + UsedCount ThirdPartyNewPrice ThirdPartyNewCount + ThirdPartyProductInfo +); + +__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES; +__PACKAGE__->make_accessor($_) for qw(year review_set); +__PACKAGE__->make_array_accessor($_) for qw(browse_nodes similar_asins); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + if(!$options{xmlref}) { + die "Mandatory param xmlref missing"; + } + + my $self = { + %options, + }; + + bless $self, $class; + + # Set default attributes + for my $attr (@DEFAULT_ATTRIBUTES) { + $self->$attr($options{xmlref}->{$attr}); + } + + # The release date is sometimes missing + if($options{xmlref}->{ReleaseDate}) { + my ($year) = ($options{xmlref}->{ReleaseDate} =~ /(\d{4})/); + $self->year($year); + } else { + $self->year(""); + } + + my $browse_nodes = $options{xmlref}->{BrowseList}->{BrowseNode}; + if(ref($browse_nodes) eq "ARRAY") { + my @nodes = map { + $_->{BrowseName} + } @{ $browse_nodes }; + $self->browse_nodes(\@nodes); + } elsif (ref($browse_nodes) eq "HASH") { + $self->browse_nodes([ $browse_nodes->{BrowseName} ]); + } else { + $self->browse_nodes([ ]); + } + + my $similar = $options{xmlref}->{SimilarProducts}; + if(ref($similar) eq "HASH") { + $self->similar_asins($similar->{Product}); + } else { + $self->similar_asins([ ]); + } + + return $self; +} + +################################################## +sub as_string { +################################################## + my($self) = @_; + + my $result = "\"$self->{xmlref}->{ProductName}\", "; + + if($self->{xmlref}->{Manufacturer}) { + $result .= "$self->{xmlref}->{Manufacturer}, "; + } + + $result .= $self->year() . ", " if $self->year(); + + $result .= $self->OurPrice() . ", "; + $result .= $self->Asin(); + return $result; +} + +################################################## +sub factory { +################################################## + my(%options) = @_; + + my $xmlref = $options{xmlref}; + die "Called factory without xmlref" unless $xmlref; + + # DEBUG(sub {"factory xmlref=" . Data::Dumper::Dumper($xmlref)}); + + my $catalog = $xmlref->{Catalog}; + my $obj; + + if(0) { + } elsif($catalog eq "Book") { + DEBUG("Creating new Book Property"); + $obj = Net::Amazon::Property::Book->new(xmlref => $xmlref); + } elsif($catalog eq "Music") { + DEBUG("Creating new Music Property"); + $obj = Net::Amazon::Property::Music->new(xmlref => $xmlref); + } elsif($catalog eq "DVD") { + DEBUG("Creating new DVD Property"); + $obj = Net::Amazon::Property::DVD->new(xmlref => $xmlref); + } else { + DEBUG("Creating new Default Property ($catalog)"); + $obj = Net::Amazon::Property->new(xmlref => $xmlref); + } + + return $obj; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + my $reviewset = Net::Amazon::Attribute::ReviewSet->new(); + + if(exists $xmlref->{Reviews}) { + $reviewset->init_via_xmlref($xmlref->{Reviews}); + } + + $self->review_set($reviewset); +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Property - Baseclass for products on amazon.com + +=head1 SYNOPSIS + + use Net::Amazon; + + # ... + + if($resp->is_success()) { + for my $prop ($resp->properties) { + print $_->ProductName(), " ", + $_->Manufacturer(), " ", + $_->OurPrice(), "\n"; + +=head1 DESCRIPTION + +C is the baseclass for results returned +from Amazon web service queries. The term 'properties' is used as +a generic description for an item on amazon.com. + +Typically, the C method of a C object +will return one or more objects of class C or +one of its subclasses, e.g. C or +C. + +While C objects expose accessors for all +fields returned in the XML response (like C, C, +C, C, C, C, subclasses +might define their own accessors to more class-specific fields +(like the iC's C method returning +a list of authors, while C's C method +will return a reference to a sub-hash containing a C field, just like +the response's XML contained it). + +=head2 METHODS + +Methods vary, depending on the item returned from a query. Here's the most +common ones. They're all accessors, meaning they can be used like C +to retrieve the value or like C to set the value of the +field. + +=over 4 + +=item Asin() + +The item's ASIN number. + +=item ProductName() + +Book title, CD album name or item name + +=item Availability() + +Text string describing if the item is available. Examples: +C<"Usually ships within 24 hours"> or +C<"Out of Print--Limited Availability">. + +=item Catalog() + +Shows the catalog the item was found in: C, C, C, +C etc. + +=item Authors() + +Returns a sub-hash with a C key, which points to either a single +$scalar or to a reference of an array containing author names as scalars. + +=item ReleaseDate() + +Item's release date, format is "NN Monthname, Year". + +=item Manufacturer() + +Music label, publishing company or manufacturer + +=item ImageUrlSmall() + +URL to a small (thumbnail) image of the item + +=item ImageUrlMedium() + +URL to a medium-size image of the item + +=item ImageUrlLarge() + +URL to a large image of the item + +=item ListPrice() + +List price of the item + +=item OurPrice() + +Amazon price of the item + +=item UsedPrice() + +Used price of the item + +=item SalesRank() + +Sales rank of the item (contains digits and commas, like 1,000,001) + +=item Media() + +Type of media (Paperback, etc.). + +=item NumMedia() + +Number of media the item carries (1,2 CDs etc.). + +=item ProductDescription() + +Lengthy textual description of the product. + +=item CollectiblePrice() + +Lowest price in "Collectible" category. + +=item CollectibleCount() + +Number of offerings in "Collectible" category. + +=item NumberOfOfferings() + +Total number of offerings in all categories. + +=item UsedCount() + +Number of offerings in "Used" category. + +=item ThirdPartyNewPrice() + +Lowest price in "Third Party New" category. + +=item ThirdPartyNewCount() + +Number of offerings in "Third Party New" category. + +=item year() + +The release year extracted from ReleaseDate(). + +=item browse_nodes() + +Returns a list of browse nodes (text string categories) for this item. + +=item similar_asins() + +Returns a list of ASINs of similar items for this item. + +=back + +Please check the subclasses of C for specialized +methods. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Property/Book.pm b/lib/Net/Amazon/Property/Book.pm new file mode 100644 index 0000000..8a01756 --- /dev/null +++ b/lib/Net/Amazon/Property/Book.pm @@ -0,0 +1,152 @@ +###################################################################### +package Net::Amazon::Property::Book; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Property); + +__PACKAGE__->make_accessor($_) for qw(title publisher binding isbn); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = $class->SUPER::new(%options); + bless $self, $class; # Bless into this class + + if(exists $options{xmlref}) { + $self->init_via_xmlref($options{xmlref}); + } + + return $self; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + $self->SUPER::init_via_xmlref($xmlref); + + $self->authors($xmlref->{Authors}->{Author}); + $self->title($xmlref->{ProductName}); + $self->publisher($xmlref->{Manufacturer}); + $self->binding($xmlref->{Media}); + $self->isbn($xmlref->{Isbn}); +} + +################################################## +sub author { +################################################## + my($self, $nameref) = @_; + + # Only return the first author + return ($self->authors($nameref))[0]; +} + +################################################## +sub authors { +################################################## + my($self, $nameref) = @_; + + if(defined $nameref) { + if(ref $nameref eq "ARRAY") { + $self->{authors} = $nameref; + } else { + $self->{authors} = [$nameref]; + } + } + + # Return a list + return $self->{authors} ? @{$self->{authors}} : (); +} + +################################################## +sub as_string { +################################################## + my($self) = @_; + + return join('/', $self->authors) . ", " . + '"' . $self->title . '"' . ", " . + $self->year . ", " . + $self->OurPrice . ", " . + $self->Asin; +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Property::Book - Class for books on amazon.com + +=head1 SYNOPSIS + + use Net::Amazon; + + # ... + + if($resp->is_success()) { + for my $prop ($resp->properties) { + print join("/", $prop->authors(), " ", + $prop->title(), " ", + $prop->publisher(), " ", + $prop->year(), "\n"; + } + +=head1 DESCRIPTION + +C is derived from +C and on top of the all-purpose +methods the base class provides, it offers specialized accessors for +book parameters. + +=head2 METHODS + +=over 4 + +=item authors() + +Returns a list of the book's authors. There's also a C method +which just returns the I author. + +=item publisher() + +Returns the book's publishing company as a string. + +=item title() + +Returns the book's title as a string. + +=item isbn() + +Returns the book's ISBN number. + +=item new(xmlref => $xmlref) + +Initializes an object by passing a hash of hashes structure containing +the XML data returned from the service. Usually, this is just used by +C internally to initialize objects for on backcoming +data. + +=back + +Check out L for all-purpose accessors, like +C, C, C, etc. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Property/DVD.pm b/lib/Net/Amazon/Property/DVD.pm new file mode 100644 index 0000000..dc7fd5a --- /dev/null +++ b/lib/Net/Amazon/Property/DVD.pm @@ -0,0 +1,156 @@ +###################################################################### +package Net::Amazon::Property::DVD; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Property); + +__PACKAGE__->make_accessor($_) for qw(title studio theatrical_release_date + media nummedia upc mpaa_rating); +__PACKAGE__->make_array_accessor($_) for qw(directors starring features); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = $class->SUPER::new(%options); + bless $self, $class; # Bless into this class + + if(exists $options{xmlref}) { + $self->init_via_xmlref($options{xmlref}); + } + + return $self; +} + +################################################## +sub director { +################################################## + my($self, $nameref) = @_; + + # Only return the first director + return ($self->directors($nameref))[0]; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + $self->SUPER::init_via_xmlref($xmlref); + + $self->title($xmlref->{ProductName}); + $self->studio($xmlref->{Manufacturer}); + $self->directors($xmlref->{Directors}->{Director}); + $self->starring($xmlref->{Starring}->{Actor}); + $self->media($xmlref->{Media}); + $self->nummedia($xmlref->{NumMedia}); + $self->upc($xmlref->{Upc}); + $self->theatrical_release_date($xmlref->{TheatricalReleaseDate}); + $self->mpaa_rating($xmlref->{MpaaRating}); + $self->features($xmlref->{Features}->{Feature}); +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Property::DVD - Class for DVDs on amazon.com + +=head1 SYNOPSIS + + use Net::Amazon; + + # ... + + if($resp->is_success()) { + for my $prop ($resp->properties) { + print $_->title(), " ", + $_->studio(), " ", + $_->year(), "\n"; + } + +=head1 DESCRIPTION + +C is derived from +C and on top of the all-purpose +methods the base class provides, it offers specialized accessors for +DVD parameters. + +=head2 METHODS + +=over 4 + +=item title() + +Returns the title of the DVD. + +=item studio() + +Returns the studio. + +=item directors() + +Returns a list of directors. Note that there's also a director() method +only returning the first director. + +=item starring() + +Returns a list of actors starring in the movie. + +=item upc() + +Returns the DVD's UPC as a string. + +=item media() + +Returns the DVD's media type as a string. + +=item nummedia() + +Returns the DVD's number of media (number of discs) as a string. +Amazon doesn't always send this back, so if you get undef assume it +is 1. + +=item theatrical_release_date() + +Returns the DVD's theatrical release date. + +=item mpaa_rating() + +Returns the DVD's MPAA rating. + +=item features() + +Returns the DVD's features as a list of strings. Examples: +"Color", "Closed-captioned", "Widescreen". + +=item new(xmlref => $xmlref) + +Initializes an object by passing a hash of hashes structure containing +the XML data returned from the service. Usually, this is just used by +C internally to initialize objects for on backcoming +data. + +=back + +Check out L for all-purpose accessors, like +C, C, C, etc. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Property/Music.pm b/lib/Net/Amazon/Property/Music.pm new file mode 100644 index 0000000..59807be --- /dev/null +++ b/lib/Net/Amazon/Property/Music.pm @@ -0,0 +1,161 @@ +###################################################################### +package Net::Amazon::Property::Music; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Property); + +__PACKAGE__->make_accessor($_) for qw(album label media nummedia upc); +__PACKAGE__->make_array_accessor($_) for qw(artists tracks); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = $class->SUPER::new(%options); + bless $self, $class; # Bless into this class + + if(exists $options{xmlref}) { + $self->init_via_xmlref($options{xmlref}); + } + + return $self; +} + +################################################## +sub artist { +################################################## + my($self, $nameref) = @_; + + # Only return the first artist + return ($self->artists($nameref))[0]; +} + +################################################## +sub init_via_xmlref { +################################################## + my($self, $xmlref) = @_; + + $self->SUPER::init_via_xmlref($xmlref); + + $self->artists($xmlref->{Artists}->{Artist}); + $self->tracks($xmlref->{Tracks}->{Track}); + $self->album($xmlref->{ProductName}); + $self->label($xmlref->{Manufacturer}); + $self->upc($xmlref->{Upc}); + $self->media($xmlref->{Media}); + $self->nummedia($xmlref->{NumMedia}); +} + +################################################## +sub as_string { +################################################## + my($self) = @_; + + return join('/', $self->artists) . ", " . + '"' . $self->album . '"' . ", " . + $self->year . ", " . + $self->OurPrice . ", " . + $self->Asin; +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Property::Music - Class for pop CDs on amazon.com + +=head1 SYNOPSIS + + use Net::Amazon; + + # ... + + if($resp->is_success()) { + for my $prop ($resp->properties) { + print join("/", $_->artists(), " ", + $_->album(), " ", + $_->label(), " ", + $_->year(), " "; + $_->upc(), " "; + $_->media(), " "; + $_->nummedia(), "\n"; + } + +=head1 DESCRIPTION + +C is derived from +C and on top of the all-purpose +methods the base class provides, it offers specialized accessors for +popular music CD parameters. + +=head2 METHODS + +=over 4 + +=item artists() + +Returns a list of the CD's artists. There's also a C method +which just returns the first artist. + +=item tracks() + +Returns a list of the CD's track titles. + +=item label() + +Returns the music label as a string. + +=item album() + +Returns the CD's title as a string. + +=item upc() + +Returns the CD's UPC as a string. + +=item media() + +Returns the CD's media type as a string. + +=item nummedia() + +Returns the CD's number of media (number of discs) as a string. +Amazon doesn't always send this back, so if you get undef assume it +is 1. + +=item new(xmlref => $xmlref) + +Initializes an object by passing a hash of hashes structure containing +the XML data returned from the service. Usually, this is just used by +C internally to initialize objects for on backcoming +data. + +=back + +Check out L for all-purpose accessors, like +C, C, C, etc. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 THANKS + +Thanks to Padraic Renaghan Epadraic@renaghan.com for adding +the upc/media/nummedia fields. + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + diff --git a/lib/Net/Amazon/Request.pm b/lib/Net/Amazon/Request.pm new file mode 100644 index 0000000..962d7bf --- /dev/null +++ b/lib/Net/Amazon/Request.pm @@ -0,0 +1,221 @@ +###################################################################### +package Net::Amazon::Request; +###################################################################### + +use warnings; +use strict; + +use constant DEFAULT_MODE => 'books'; +use constant DEFAULT_TYPE => 'heavy'; +use constant DEFAULT_PAGE_COUNT => 1; +use constant DEFAULT_FORMAT => 'xml'; +use constant DEFAULT_SORT_CRITERIA => '+salesrank'; + +use constant VALID_TYPES => { map { $_ => 1 } qw(heavy lite) }; + +our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3"; + +################################################## +sub amzn_xml_url { +################################################## + return $AMZN_XML_URL; +} + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + my $self = { + mode => DEFAULT_MODE, + type => DEFAULT_TYPE, + page => DEFAULT_PAGE_COUNT, + f => DEFAULT_FORMAT, + sort => DEFAULT_SORT_CRITERIA, + %options, + }; + + die "Unknown type in ", __PACKAGE__, " constructor: ", + $self->{type} unless exists VALID_TYPES->{$self->{type}}; + + bless $self, $class; +} + +################################################## +sub params { +################################################## + my($self) = @_; + + return(%$self); +} + +################################################## +# Figure out the Response class to a given Request +# class. To be used by sub classes. +################################################## +sub response_class { +################################################## + my($self) = @_; + + my $response_class = ref($self); + $response_class =~ s/Request/Response/; + return $response_class; +} + +## +## 'PRIVATE' METHODS +## + +# CLASS->_convert_option( OPTIONS, ORIGINAL, TARGET [, CALLBACK] ) +# +# Takes a reference to a hash of OPTIONS and renames the +# ORIGINAL key name to the TARGET key name. If the optional +# CALLBACK subroutine reference is defined, that subroutine +# is invoked with two arguments: +# +# CALLBACK->( OPTIONS, TARGET ) +# +# The result of the CALLBACK's execution is then returned to +# the caller. No assumptions are made about what the CALLBACK +# should return (or even *if* is should return)--that's the +# caller's responsibility. +# +# Returns 1 in the absensence of a CALLBACK. +# +sub _convert_option { + my ($class, $options, $original, $target, $callback) = @_; + + if ( exists $options->{$original} ) { + $options->{$target} = $options->{$original}; + delete $options->{$original}; + } + + return 1 unless ( $callback ); + + # The key name is explicitly passed-in so that the caller doesn't + # have think "Hrmm.. now which key am I working on, the original + # or the target key?" Confusion is bad. + return $callback->($options, $target); +} + +# CLASS->_assert_options_defined( OPTIONS, KEYS ) +# +# Takes a reference to a hash of OPTIONS and a list of +# one or more KEYS. Tests to see if each key in KEYS +# has a defined value. Calls die() upon the first +# missing key. Otherwise, returns undef. +# +sub _assert_options_defined { + my ($class, $options, @keys) = @_; + + foreach my $key ( @keys ) { + die "Mandatory parameter '$key' not defined" + unless ( defined $options->{$key} ); + } +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request - Baseclass for requests to Amazon's web service + +=head1 SYNOPSIS + + my $req = Net::Amazon::Request::XXX->new( + [ type => 'heavy', ] + [ page => $start_page, ] + [ mode => $mode, ] + [ offer => 'All', ] + [ sort => $sort_type, ] + ); + +=head1 DESCRIPTION + +Don't use this class directly, use derived classes +(like C, C +etc.) instead to specify the type of request and its parameters. + +However, there's a bunch of parameters to the constructor +that all request types have in common, here they are: + +=over 4 + +=item type + +Defaults to C, but can be set to C if no reviews etc. +on a product are wanted. Some fields (e.g. C) are not going to be +available in C mode, though. + +=item mode + +Defaults to C, but can be set to other catalog values. + +=item page + +Defaults to C<1>, but can be set to a different number to +start with a different result page. Used in conjunction with the +C parameter of the C object. C is the +offset, C is the maximum number of pages pulled in starting +at C. + +=item sort + +Defaults to C<+salesrank>, but search results can be sorted in various +ways, depending on the type of product returned by the search. Search +results may be sorted by the following criteria: + +=over 8 + +=item * +Featured Items + +=item * +Bestselling + +=item * +Alphabetical (A-Z and Z-A) + +=item * +Price (High to Low and Low to High) + +=item * +Publication or Release Date + +=item * +Manufacturer + +=item * +Average Customer Review + +=item * +Artist Name + +=back + +Consult L for details. + +=item offer + +To receive values for the fields +C, C, C, +specify C "All">. + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/ASIN.pm b/lib/Net/Amazon/Request/ASIN.pm new file mode 100644 index 0000000..4d8f752 --- /dev/null +++ b/lib/Net/Amazon/Request/ASIN.pm @@ -0,0 +1,139 @@ +###################################################################### +package Net::Amazon::Request::ASIN; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +# These values are defined in the AWS SDK +# (http://amazon.com/webservices) under +# "Product and Catalog Data" / "ASIN and ISBN Searches" +use constant MAX_ASINS_PER_TYPE => { + heavy => 10, + lite => 30, +}; + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, 'asin'); + + $class->_convert_option(\%options, + 'asin', + 'AsinSearch', + \&_process_asin_option); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +## +## PRIVATE FUNCTIONS +## + +# _process_asin_option( OPTIONS, KEY ) +# +# Takes a reference to a hash of OPTIONS and checks the value keyed by +# KEY to make sure it looks legitimate. If the value associated with +# KEY is an array, we check to make sure that we're not asking for +# too many asins at once. +# +# Returns true if all goes well. If any problems are encountered, +# die() will be called. +# +sub _process_asin_option { + my ($options, $key) = @_; + + # If the asins are supplied in the form of an array, we have to + # make sure that the caller isn't trying to ask for too many at a + # time. If we don't make this test, those excessive asins will be + # silently ignored by the AWS servers...resulting in potentially + # confusing results for the user. + if ( ref $options->{$key} eq 'ARRAY' ) { + my $type = $options->{'type'} || __PACKAGE__->SUPER::DEFAULT_TYPE; + my $max_asins = MAX_ASINS_PER_TYPE->{$type}; + + # Dying is the right thing to do here because this is + # indicative of a programming error. + die "Only $max_asins may be requested at a time using type '$type'" + if ( @{$options->{$key}} > $max_asins ); + + $options->{$key} = join ',', @{$options->{$key}}; + } elsif ( ref $options->{$key} ) { + die "The 'asin' parameter must either be a scalar or an array"; + } + + return 1; +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::ASIN - Class for submitting ASIN requests + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::ASIN; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::ASIN->new( + asin => '0201360683' + ); + + # Response is of type Net::Amazon::Response::ASIN + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit ASIN requests +to the Amazon web service. + +The ASIN of the item to look is specified in the C parameter. + +Upon success, the responses' C method will return one +single C object. + +=head2 METHODS + +=over 4 + +=item new( asin => $asin ) + +Constructs a new C object, used to query +the Amazon web service for an item with the specified ASIN number. + +C<$asin> can also be a reference to an array of ASINs, like in + + $ua->search(asin => ["0201360683", "0596005083"]) + +in which case a search for multiple ASINs is performed, returning a list of +results. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Artist.pm b/lib/Net/Amazon/Request/Artist.pm new file mode 100644 index 0000000..4c111f8 --- /dev/null +++ b/lib/Net/Amazon/Request/Artist.pm @@ -0,0 +1,86 @@ +###################################################################### +package Net::Amazon::Request::Artist; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + if(exists $options{artist}) { + $options{ArtistSearch} = $options{artist}; + delete $options{artist}; + $options{mode} = "music"; + } else { + die "Mandatory parameter 'artist' not defined"; + } + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Artist - Class for submitting Artist requests + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Artist; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Artist->new( + artist => 'Zwan' + ); + + # Response is of type Net::Amazon::Response::Artist + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit Artist search +requests to the Amazon web service. + +The artist to search for is specified in the C parameter. + +Upon success, the responses' C method will return a list of +C objects. + +Check L for common request parameters not listed here. + +=head2 METHODS + +=over 4 + +=item new( artist => $artist ) + +Constructs a new C object, used to query +the Amazon web service for items of a given artist. + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Blended.pm b/lib/Net/Amazon/Request/Blended.pm new file mode 100644 index 0000000..1000eec --- /dev/null +++ b/lib/Net/Amazon/Request/Blended.pm @@ -0,0 +1,80 @@ +###################################################################### +package Net::Amazon::Request::Blended; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, 'blended'); + + $class->_convert_option(\%options, + 'blended', + 'BlendedSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Blended - request class for 'Blended Search' + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Blended; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Blended->new( + blended => 'perl' + ); + + # Response is of type Net::Amazon::Response::Blended + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to request +I from the Amazon web service. + +The C parameter specifies the keyword search string +for the blended query. C is not applicable to blended +searches which returns books, music, etc all at once. + +Upon success, the response's C method will return a list +of C objects. + +=head2 METHODS + +=over 4 + +=item new(keyword => $search_string) + +Constructs a new C object. + +See the "Amazon Web Services 2.1 API and Integration Guide" for details. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHORS + +Robert Graff, Ergraff@workingdemo.comE + +=cut diff --git a/lib/Net/Amazon/Request/BrowseNode.pm b/lib/Net/Amazon/Request/BrowseNode.pm new file mode 100644 index 0000000..2f8d92f --- /dev/null +++ b/lib/Net/Amazon/Request/BrowseNode.pm @@ -0,0 +1,137 @@ +###################################################################### +package Net::Amazon::Request::BrowseNode; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, + qw(browsenode mode)); + + $class->_convert_option(\%options, + 'browsenode', + 'BrowseNodeSearch', + \&_assert_node_is_numeric); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +## +## 'PRIVATE' FUNCTIONS +## + +# _assert_node_is_numeric( OPTIONS, KEY ) +# +# Takes a reference to a hash of OPTIONS and makes sure +# that the browse node id keyed by KEY is numeric. +# +# Returns if all is well, dies otherwise. +# +sub _assert_node_is_numeric { + my ($options, $key) = @_; + + die "Browse Node ID must be numeric." + if ( $options->{$key} =~ /\D/ ); +} + + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::BrowseNode - request class for browse node search + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::BrowseNode; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::BrowseNode->new( + browsenode => 30, + mode => 'books' + ); + + # Response is of type Net::Amazon::Response::BrowseNode + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit node search +requests to the Amazon web service. + +The node to search for is specified in the C parameter. The +browse node ID is a number that corresponds to a general subject area +of Amazon.com. + +To find browse node IDs, the best way is to visit the "browse" area +of the various product lines at Amazon.com. When you find a subject area +that you would like to generate XML for, look at the web page URL. The +browse ID should appear after the string "/tg/browse/-/". Here are some +examples of URLs that contain browse IDs: + +=over 8 + +http://www.amazon.com/exec/obidos/tg/browse/-/30 +(In this example, the browse ID = 30) + +http://www.amazon.com/exec/obidos/tg/browse/-/467970 +(In this example, the browse ID = 467970) + +http://www.amazon.com/exec/obidos/tg/browse/-/602314 +(In this example, the browse ID = 60231 + +=back + +Please be aware that some nodes cannot be used with a +BrowseNodeSearch. (The vast majority of them can, but you +may run across a few that simply will not work). It is also +important to point out that from time to time, some browse +nodes are deprecated or are changed without notice. + +The catalog to search in is specified in the C parameter, +typical values are C, C, C or C. + +An optional C parameter may be added to filter the results by that keyword. + +Upon success, the responses' C method will return a list of +C objects. + +=head2 METHODS + +=over 4 + +=item new( browsenode => $nodeID, mode => $mode [, keywords => $keywords] ) + +Constructs a new C object, used to query +the Amazon web service for items in a particular category (node) in the +mode (catalog) specified. + +=back + +Check L for common request parameters not listed here. + +=head1 AUTHOR + +Net::Amazon framework by Mike Schilli, Em@perlmeister.comE + +BrowseNode.pm by Jackie Hamilton, Ekira@cgi101.comE + +=head1 LICENSE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Exchange.pm b/lib/Net/Amazon/Request/Exchange.pm new file mode 100644 index 0000000..df75549 --- /dev/null +++ b/lib/Net/Amazon/Request/Exchange.pm @@ -0,0 +1,91 @@ +###################################################################### +package Net::Amazon::Request::Exchange; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + if(exists $options{exchange}) { + $options{ExchangeSearch} = $options{exchange}; + delete $options{exchange}; + $options{type} = "lite"; + $options{mode} = ""; + } else { + die "Mandatory parameter 'exchange' not defined"; + } + +# if(!exists $options{exchange}) { +# die "Mandatory parameter 'exchange' not defined"; +# } + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Exchange - Class for submitting Exchange requests + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Exchange; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Exchange->new( + exchange => 'Y04Y3424291Y2398445' + ); + + # Response is of type Net::Amazon::Response::Seller + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit Exchange search +requests to the Amazon web service. Exchange requests send an item's +exchange ID and retrieve a description of the item, offered by a third +party seller on Amazon. + +Upon success, the responses' C method will return a single +C object. + +Check L for common request parameters not listed here. + +=head2 METHODS + +=over 4 + +=item new( exchange => $exchange_id ) + +Constructs a new C object, used to query +the Amazon web service with the given seller id. + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2005 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Keyword.pm b/lib/Net/Amazon/Request/Keyword.pm new file mode 100644 index 0000000..0b15d1d --- /dev/null +++ b/lib/Net/Amazon/Request/Keyword.pm @@ -0,0 +1,90 @@ +###################################################################### +package Net::Amazon::Request::Keyword; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, + qw(keyword mode)); + + $class->_convert_option(\%options, + 'keyword', + 'KeywordSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Keyword - request class for keyword search + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Keyword; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Keyword->new( + keyword => 'Zwan', + mode => 'books' + ); + + # Response is of type Net::Amazon::Response::Keyword + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit keyword search +requests to the Amazon web service. + +The keyword to search for is specified in the C parameter. + +The catalog to search in is specified in the C parameter, +typical values are C, C, C or C. + +Upon success, the responses' C method will return a list of +C objects. + +=head2 METHODS + +=over 4 + +=item new( keyword => $keyword, mode => $mode ) + +Constructs a new C object, used to query +the Amazon web service for items matching a given keyword in the +mode (catalog) specified. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Manufacturer.pm b/lib/Net/Amazon/Request/Manufacturer.pm new file mode 100644 index 0000000..0e8adb8 --- /dev/null +++ b/lib/Net/Amazon/Request/Manufacturer.pm @@ -0,0 +1,78 @@ +###################################### +package Net::Amazon::Request::Manufacturer; +###################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +###################################### +sub new { +###################################### + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, + 'manufacturer'); + + $class->_convert_option(\%options, + 'manufacturer', + 'ManufacturerSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Manufacturer - Class for submitting Manufacturer requests + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Manufacturer; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Manufacturer->new( + manufacturer => 'Disney' + ); + + # Response is of type Net::Amazon::Response::Manufacturer + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit +searches for items made by a given manufacturer. + +The manufacturer to search for is specified in the C parameter. + +Upon success, the responses' C method will return one +or more C objects. + +=head2 METHODS + +=over 4 + +=item new( manufacturer => $manufacturer ) + +Constructs a new C object, used to query +the Amazon web service for an item with the specified manufacturer name. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHORS + +Bill Fitzpatrick +Mike Schilli, Em@perlmeister.comE + +=cut diff --git a/lib/Net/Amazon/Request/Power.pm b/lib/Net/Amazon/Request/Power.pm new file mode 100644 index 0000000..fdfd74e --- /dev/null +++ b/lib/Net/Amazon/Request/Power.pm @@ -0,0 +1,95 @@ +###################################################################### +package Net::Amazon::Request::Power; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, + qw(power mode)); + + $class->_convert_option(\%options, + 'power', + 'PowerSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Power - request class for 'Power Search' + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Power; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Power->new( + power => 'subject: perl and author: schwartz', + mode => 'books', + ); + + # Response is of type Net::Amazon::Response::Power + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to request +so-called I from the Amazon web service. + +The C parameter specifies the power search string, C +defines which properties to look for. + +Upon success, the response's C method will return a list +of C objects. + +=head2 METHODS + +=over 4 + +=item new(power => $search_string, mode => $property) + +Constructs a new C object. C<$property> +is typically C<"books">. Examples for C<$search_string> are: + + author: schwartz + + author: schwartz and pubdate: after 10-2002 + + subject: perl and (objects or object-oriented) + + keywords: "high tech*" and not fiction and pubdate: during 1999 + + power "author: randal schwartz and publisher: Addison Wesley" + + author: randal schwartz and title: object books + +See the "Amazon Web Services 2.1 API and Integration Guide" for details. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHORS + +Martin Streicher, Emartin.streicher@apress.comE +Mike Schilli, Em@perlmeister.comE + +=cut diff --git a/lib/Net/Amazon/Request/Seller.pm b/lib/Net/Amazon/Request/Seller.pm new file mode 100644 index 0000000..54e1930 --- /dev/null +++ b/lib/Net/Amazon/Request/Seller.pm @@ -0,0 +1,84 @@ +###################################################################### +package Net::Amazon::Request::Seller; +###################################################################### +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + if(exists $options{seller}) { + $options{SellerSearch} = $options{seller}; + delete $options{seller}; + } else { + die "Mandatory parameter 'seller' not defined"; + } + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Seller - Class for submitting Seller requests + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Seller; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Seller->new( + seller => 'A2GXAGU54VOP7' + ); + + # Response is of type Net::Amazon::Response::Seller + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit Seller search +requests to the Amazon web service. + +The seller to search for is specified in the C parameter, which +contains the seller's ID (not the seller's nickname!). + +Upon success, the responses' C method will return a single +C object. + +Check L for common request parameters not listed here. + +=head2 METHODS + +=over 4 + +=item new( seller => $seller_id ) + +Constructs a new C object, used to query +the Amazon web service with the given seller id. + +=back + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2004 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Similar.pm b/lib/Net/Amazon/Request/Similar.pm new file mode 100644 index 0000000..c5b5a53 --- /dev/null +++ b/lib/Net/Amazon/Request/Similar.pm @@ -0,0 +1,95 @@ +###################################################################### +package Net::Amazon::Request::Similar; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3"; + +################################################## +sub amzn_xml_url { +################################################## + return $AMZN_XML_URL; +} + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + # For backwards compatibility + $class->_convert_option(\%options, 'asin', 'similar'); + + $class->_assert_options_defined(\%options, 'similar'); + + $class->_convert_option(\%options, + 'similar', + 'SimilaritySearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::Similar - request class for 'Similarities Search' + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::Similar; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::Similar->new( + similar => 'B00005B6TL', + ); + + # Response is of type Net::Amazon::Response::Similar + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to request +so-called I from the Amazon web service. + +The C parameter specifies the ASIN of the item which you want +to get similar items for. + +Upon success, the response's C method will return a list +of C objects. + +=head2 METHODS + +=over 4 + +=item new(similar => $asin) + +Constructs a new C object. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=head1 AUTHOR + +Mike Schilli, Em@perlmeister.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2003 by Mike Schilli Em@perlmeister.comE + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut diff --git a/lib/Net/Amazon/Request/Sort.pm b/lib/Net/Amazon/Request/Sort.pm new file mode 100644 index 0000000..059845d --- /dev/null +++ b/lib/Net/Amazon/Request/Sort.pm @@ -0,0 +1,246 @@ +=pod + +=head1 SORT TYPES + +Search results can be sorted in various ways, depending on the type of +product returned by the search. If a sort parameter isn't specified in +the request, the results will be ordered as if the +salesrank value is +specified. + +=head2 Sorting Books Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Average Customer Review | +reviewrank | + |-------------------------+-------------------------+ + | Price (Low to High) | +pricerank | + |-------------------------+-------------------------+ + | Price (High to Low) | +inverse-pricerank | + |-------------------------+-------------------------+ + | Publication Date | +daterank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + +---------------------------------------------------+ + +=head2 Sorting Software Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + |-------------------------+-------------------------+ + | Price (High to Low) | +price | + |-------------------------+-------------------------+ + | Price (Low to High) | -price | + +---------------------------------------------------+ + +=head2 Sorting Outdoor Living Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +psrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + |-------------------------+-------------------------+ + | Manufacturer (A-Z) | +manufactrank | + |-------------------------+-------------------------+ + | Manufacturer (Z-A) | -manufactrank | + |-------------------------+-------------------------+ + | Price (Low to High) | +price | + |-------------------------+-------------------------+ + | Price (High to Low) | -price | + +---------------------------------------------------+ + +=head2 Sorting Tools Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +psrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + |-------------------------+-------------------------+ + | Manufacturer (A-Z) | +manufactrank | + |-------------------------+-------------------------+ + | Manufacturer (Z-A) | -manufactrank | + |-------------------------+-------------------------+ + | Price (Low to High) | +price | + |-------------------------+-------------------------+ + | Price (High to Low) | -price | + +---------------------------------------------------+ + +=head2 Sorting Camera and Photo Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + +---------------------------------------------------+ + +=head2 Sorting Computers Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +psrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + +---------------------------------------------------+ + +=head2 Sorting Video Games Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + |-------------------------+-------------------------+ + | Price (Low to High) | +price | + |-------------------------+-------------------------+ + | Price (High to Low) | -price | + +---------------------------------------------------+ + +=head2 Sorting Music Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +psrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Artist Name | +artistrank | + |-------------------------+-------------------------+ + | Original Release Date | +orig-rel-date | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + +---------------------------------------------------+ + +=head2 Sorting Office Products Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + |-------------------------+-------------------------+ + | Price (Low to High) | +price | + |-------------------------+-------------------------+ + | Price (High to Low) | -price | + |-------------------------+-------------------------+ + | Review | +reviewrank | + +---------------------------------------------------+ + +=head2 Sorting Video Results + + +---------------------------------------------------+ + | Sort Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +psrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + +---------------------------------------------------+ + +=head2 Sorting Electronics Results + + +---------------------------------------------------+ + | Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + |-------------------------+-------------------------+ + | Review | +reviewrank | + +---------------------------------------------------+ + +=head2 Sorting DVDs Results + + +---------------------------------------------------+ + | Type | Value | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical | +titlerank | + +---------------------------------------------------+ + +=head2 Sorting Kitchen Results + + +---------------------------------------------------+ + | Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + |-------------------------+-------------------------+ + | Alphabetical (Z-A) | -titlerank | + |-------------------------+-------------------------+ + | Manufacturer (A-Z) | +manufactrank | + |-------------------------+-------------------------+ + | Manufacturer (Z-A) | -manufactrank | + |-------------------------+-------------------------+ + | Price (Low to High) | +price | + |-------------------------+-------------------------+ + | Price (High to Low) | -price | + +---------------------------------------------------+ + +=head2 Sorting Toys Results + + +---------------------------------------------------+ + | Type | Value | + |-------------------------+-------------------------+ + | Featured Items | +pmrank | + |-------------------------+-------------------------+ + | Bestselling | +salesrank | + |-------------------------+-------------------------+ + | Price (Low to High) | +pricerank | + |-------------------------+-------------------------+ + | Price (High to Low) | +inverse-pricerank | + |-------------------------+-------------------------+ + | Alphabetical (A-Z) | +titlerank | + +---------------------------------------------------+ + +=cut diff --git a/lib/Net/Amazon/Request/TextStream.pm b/lib/Net/Amazon/Request/TextStream.pm new file mode 100644 index 0000000..62a0717 --- /dev/null +++ b/lib/Net/Amazon/Request/TextStream.pm @@ -0,0 +1,76 @@ +###################################################################### +package Net::Amazon::Request::TextStream; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, + 'textstream'); + + $class->_convert_option(\%options, + 'textstream', + 'TextStreamSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::TextStream - request class for text stream search + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::TextStream; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::TextStream->new( + textstream => 'Here is some text that mentions the Rolling Stones.', + ); + + # Response is of type Net::Amazon::Response::TextStream + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to perform a search on +a block of text. Amazon extracts keywords from the given block of text, +but note that conjunctions and helper words, such as "and", "or", "the", +etc. are not excluded, so strip them out yourself if need be. + +TextStream searching is only available for the US service. + +Upon success, the response's C method will return a list +of C objects. + +=head2 METHODS + +=over 4 + +=item new(textstream => $text) + +Constructs a new C object, used to query +the Amazon web service with a block of text. + +=back + +Check L for common request parameters not listed here. + +=head1 SEE ALSO + +=cut diff --git a/lib/Net/Amazon/Request/UPC.pm b/lib/Net/Amazon/Request/UPC.pm new file mode 100644 index 0000000..ae77645 --- /dev/null +++ b/lib/Net/Amazon/Request/UPC.pm @@ -0,0 +1,94 @@ +###################################################################### +package Net::Amazon::Request::UPC; +###################################################################### +use warnings; +use strict; +use base qw(Net::Amazon::Request); + +################################################## +sub new { +################################################## + my($class, %options) = @_; + + $class->_assert_options_defined(\%options, 'upc'); + + $class->_convert_option(\%options, + 'upc', + 'UpcSearch'); + + my $self = $class->SUPER::new(%options); + + bless $self, $class; # reconsecrate +} + +1; + +__END__ + +=head1 NAME + +Net::Amazon::Request::UPC - request class for UPC search + +=head1 SYNOPSIS + + use Net::Amazon; + use Net::Amazon::Request::UPC; + + my $ua = Net::Amazon->new( + token => 'YOUR_AMZN_TOKEN' + ); + + my $req = Net::Amazon::Request::UPC->new( + upc => '724381198421', + mode => 'music', + + ); + + # Response is of type Net::Amazon::Response::UPC + my $resp = $ua->request($req); + +=head1 DESCRIPTION + +C is a class used to submit UPC (product barcode) +search requests to the Amazon web service. + +The UPC number to search for is specified in the C parameter. +It currently works with the following values of the C parameter: +C, +C, +C, +C, +C