File Coverage

blib/lib/XML/Amazon.pm
Criterion Covered Total %
statement 35 182 19.2
branch 0 58 0.0
condition 0 23 0.0
subroutine 12 18 66.6
pod 4 4 100.0
total 51 285 17.8


line stmt bran cond sub pod time code
1             package XML::Amazon;
2             $XML::Amazon::VERSION = '0.14';
3 1     1   68470 use 5.008;
  1         14  
4              
5 1     1   6 use strict;
  1         2  
  1         20  
6 1     1   5 use warnings;
  1         1  
  1         22  
7              
8 1     1   653 use utf8;
  1         15  
  1         6  
9              
10 1     1   697 use LWP::UserAgent ();
  1         45982  
  1         31  
11 1     1   821 use XML::Simple;
  1         9106  
  1         7  
12 1     1   548 use XML::Amazon::Item;
  1         3  
  1         33  
13 1     1   428 use XML::Amazon::Collection;
  1         3  
  1         43  
14 1     1   623 use Data::Dumper qw ();
  1         6914  
  1         27  
15 1     1   6 use URI::Escape qw();
  1         3  
  1         20  
16 1     1   505 use Digest::SHA qw(hmac_sha256_hex hmac_sha256_base64);
  1         3086  
  1         83  
17 1     1   516 use POSIX qw(strftime);
  1         6835  
  1         5  
18              
19             sub new{
20 0     0 1   my($pkg, %options) = @_;
21 0 0         die 'No Access Key ID provided!' unless $options{'token'};
22 0 0         die 'No Secret Access Key provided!' unless $options{'sak'};
23 0           my $locale = $options{'locale'};
24 0   0       $locale ||= "us";
25 0 0 0       die "Invalid locale" unless $locale eq "jp" || $locale eq "uk" || $locale eq "fr" || $locale eq "us" || $locale eq "de"|| $locale eq "ca";
      0        
      0        
      0        
      0        
26 0   0       my $associate = $options{'associate'} || 'webservices-20';
27              
28 0           my $url;
29              
30 0 0         $url = 'ecs.amazonaws.jp' if $locale eq "jp";
31 0 0         $url = 'ecs.amazonaws.co.uk' if $locale eq "uk";
32 0 0         $url = 'ecs.amazonaws.fr' if $locale eq "fr";
33 0 0         $url = 'ecs.amazonaws.de' if $locale eq "de";
34 0 0         $url = 'ecs.amazonaws.ca' if $locale eq "ca";
35 0 0         $url = 'ecs.amazonaws.com' if $locale eq "us";
36              
37              
38             my $req = {
39             'Service' => 'AWSECommerceService',
40 0           'AWSAccessKeyId' => $options{'token'},
41             'AssociateTag' => $associate,
42             'Version' => '2009-03-31',
43             'Timestamp' => strftime( "%Y-%m-%dT%TZ", gmtime() )
44             };
45              
46             bless{
47             token => $options{'token'},
48 0           sak => $options{'sak'},
49             associate => $associate,
50             locale => $locale,
51             url => $url,
52             req => $req,
53             data => undef,
54             success => '0'
55             }, $pkg;
56             }
57              
58             sub _get {
59 0     0     my $self = shift;
60 0           my $type = shift;
61 0           my $query = shift;
62 0           my $field = shift;
63 0 0         $self->asin($query) if $type eq "asin";
64 0 0         $self->search($query,$field) if $type eq "search";
65             }
66              
67             sub asin{
68 0     0 1   my $self = shift;
69 0           my $asin = shift;
70 0           my $url = $self->{url};
71 0           my $ITEM = XML::Amazon::Item->new();
72              
73 0 0         warn 'Apparently not an appropriate ASIN' if $asin =~ /[^a-zA-Z0-9]/;
74              
75 0           my %params = %{$self->{req}};
  0            
76              
77 0           $params{'Operation'} = 'ItemLookup';
78 0           $params{'ResponseGroup'} = 'Images,ItemAttributes';
79 0           $params{'ItemId'} = $asin;
80 0           $params{'Version'} = '2009-03-31';
81              
82 0           my $data = $self->_get_data(\%params);
83              
84 0           my $xs = new XML::Simple(SuppressEmpty => undef, ForceArray => ['Creator', 'Author', 'Artist', 'Director', 'Actor']);
85 0           my $pl = $xs->XMLin($data);
86 0           $self->{data} = $pl;
87              
88 0 0         if ($pl->{Items}->{Item}->{ASIN}){
89 0           $ITEM->{asin} = $pl->{Items}->{Item}->{ASIN};
90 0           $ITEM->{title} = $pl->{Items}->{Item}->{ItemAttributes}->{Title};
91 0           $ITEM->{type} = $pl->{Items}->{Item}->{ItemAttributes}->{ProductGroup};
92              
93              
94 0 0         if ($pl->{Items}->{Item}->{ItemAttributes}->{Author}->[0]){
95 0           for (my $i = 0; $pl->{Items}->{Item}->{ItemAttributes}->{Author}->[$i]; $i++){
96 0           $ITEM->{authors}->[$i] = $pl->{Items}->{Item}->{ItemAttributes}->{Author}->[$i];
97             }
98             }
99              
100 0 0         if ($pl->{Items}->{Item}->{ItemAttributes}->{Artist}->[0]){
101 0           for (my $i = 0; $pl->{Items}->{Item}->{ItemAttributes}->{Artist}->[$i]; $i++){
102 0           $ITEM->{artists}->[$i] = $pl->{Items}->{Item}->{ItemAttributes}->{Artist}->[$i];
103             }
104             }
105 0 0         if ($pl->{Items}->{Item}->{ItemAttributes}->{Actor}->[0]){
106 0           for (my $i = 0; $pl->{Items}->{Item}->{ItemAttributes}->{Actor}->[$i]; $i++){
107 0           $ITEM->{actors}->[$i] = $pl->{Items}->{Item}->{ItemAttributes}->{Actor}->[$i];
108             }
109             }
110              
111 0 0         if ($pl->{Items}->{Item}->{ItemAttributes}->{Director}->[0]){
112 0           for (my $i = 0; $pl->{Items}->{Item}->{ItemAttributes}->{Director}->[$i]; $i++){
113 0           $ITEM->{directors}->[$i] = $pl->{Items}->{Item}->{ItemAttributes}->{Director}->[$i];
114             }
115             }
116              
117              
118 0 0         if ($pl->{Items}->{Item}->{ItemAttributes}->{Creator}->[0]->{content}){
119 0           for (my $i = 0; $pl->{Items}->{Item}->{ItemAttributes}->{Creator}->[$i]->{content}; $i++){
120 0           $ITEM->{creators}->[$i] = $pl->{Items}->{Item}->{ItemAttributes}->{Creator}->[$i]->{content};
121             }
122             }
123              
124              
125 0           $ITEM->{price} = $pl->{Items}->{Item}->{ItemAttributes}->{ListPrice}->{FormattedPrice};
126 0           $ITEM->{author} = $ITEM->{authors}->[0];
127 0           $ITEM->{url} = $pl->{Items}->{Item}->{DetailPageURL};
128 0           $ITEM->{publisher} = $pl->{Items}->{Item}->{ItemAttributes}->{Publisher};
129 0           $ITEM->{smallimage} = $pl->{Items}->{Item}->{SmallImage}->{URL};
130 0           $ITEM->{mediumimage} = $pl->{Items}->{Item}->{MediumImage}->{URL};
131 0 0         $ITEM->{mediumimage} = $ITEM->{smallimage} unless $ITEM->{mediumimage};
132 0           $ITEM->{largeimage} = $pl->{Items}->{Item}->{LargeImage}->{URL};
133 0 0         $ITEM->{largeimage} = $ITEM->{mediumimage} unless $ITEM->{largeimage};
134              
135 0           $self->{success} = '1';
136 0           return $ITEM;
137             }
138             else{
139 0           $self->{success} = '0';
140 0           warn 'No item found';
141 0           return '';
142             }
143             }
144              
145             sub search{
146 0     0 1   my($self, %options) = @_;
147 0           my $keywords = $options{'keywords'};
148 0   0       my $type = $options{'type'} || "Blended";
149 0   0       my $page = $options{'page'} || 1;
150              
151 0           my %params = %{$self->{req}};
  0            
152              
153 0           $params{'Operation'} = 'ItemSearch';
154 0           $params{'SearchIndex'} = $type;
155 0           $params{'ResponseGroup'} = 'Images,ItemAttributes';
156 0           $params{'Keywords'} = $keywords;
157 0           $params{'ItemPage'} = $page;
158              
159 0           my $data = $self->_get_data(\%params);
160              
161 0           my $xs = new XML::Simple(SuppressEmpty => undef, ForceArray => ['Item', 'Creator', 'Author', 'Artist', 'Actor', 'Director']);
162 0           my $pl = $xs->XMLin($data);
163 0           $self->{data} = $pl;
164              
165 0           my $collection = XML::Amazon::Collection->new();
166 0 0         if ($pl->{Items}->{Item}->[0]->{ASIN}){
167 0           $collection->{total_results} = $pl->{Items}->{TotalResults};
168 0           $collection->{total_pages} = $pl->{Items}->{TotalPages};
169 0           $collection->{current_page} = $pl->{Items}->{Request}->{ItemSearchRequest}->{ItemPage};
170              
171 0           for (my $i = 0; $pl->{Items}->{Item}->[$i]; $i++){
172              
173 0           my $new_item = XML::Amazon::Item->new();
174              
175 0           $new_item->{asin} = $pl->{Items}->{Item}->[$i]->{ASIN};
176 0           $new_item->{title} = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Title};
177 0           $new_item->{publisher} = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Publisher};
178 0           $new_item->{url} = $pl->{Items}->{Item}->[$i]->{DetailPageURL};
179 0           $new_item->{type} = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{ProductGroup};
180              
181 0 0         if ($pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Author}->[0]){
182 0           for (my $j = 0; $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Author}->[$j]; $j++){
183 0           $new_item->{authors}->[$j] = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Author}->[$j];
184             }
185             }
186              
187 0 0         if ($pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Artist}->[0]){
188 0           for (my $j = 0; $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Artist}->[$j]; $j++){
189 0           $new_item->{artists}->[$j] = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Artist}->[$j];
190             }
191             }
192              
193 0 0         if ($pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Creator}->[0]->{content}){
194 0           for (my $j = 0; $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Creator}->[$j]->{content}; $j++){
195 0           $new_item->{creators}->[$j] = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Creator}->[$j]->{content};
196             }
197             }
198              
199 0 0         if ($pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Director}->[0]){
200 0           for (my $j = 0; $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Director}->[$j]; $j++){
201 0           $new_item->{directors}->[$j] = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Director}->[$j];
202             }
203             }
204              
205              
206 0 0         if ($pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Actor}->[0]){
207 0           for (my $j = 0; $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Actor}->[$j]; $j++){
208 0           $new_item->{actors}->[$j] = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{Actor}->[$j];
209             }
210             }
211              
212              
213              
214 0           $new_item->{price} = $pl->{Items}->{Item}->[$i]->{ItemAttributes}->{ListPrice}->{FormattedPrice};
215 0           $new_item->{smallimage} = $pl->{Items}->{Item}->[$i]->{SmallImage}->{URL};
216 0           $new_item->{mediumimage} = $pl->{Items}->{Item}->[$i]->{MediumImage}->{URL};
217 0 0         $new_item->{mediumimage} = $new_item->{smallimage} unless $new_item->{mediumimage};
218 0           $new_item->{largeimage} = $pl->{Items}->{Item}->[$i]->{LargeImage}->{URL};
219 0 0         $new_item->{largeimage} = $new_item->{mediumimage} unless $new_item->{largeimage};
220              
221 0           $collection->add_Amazon($new_item);
222             }
223 0           $self->{success} = '1';
224 0           return $collection;
225              
226             }
227              
228             else{
229 0           $self->{success} = '0';
230 0           warn 'No item found';
231 0           return '';
232             }
233             }
234              
235             sub is_success {
236 0     0 1   my $self = shift;
237 0           return $self->{success};
238              
239             }
240              
241             sub _get_data {
242 0     0     my $self = shift;
243 0           my $params = shift;
244              
245 0           my $url = $self->{url};
246 0           my @param;
247 0           foreach my $key (sort { $a cmp $b } keys %{$params}){
  0            
  0            
248 0           push @param, $key . '=' . URI::Escape::uri_escape(${$params}{$key}, "^A-Za-z0-9\-_.~");
  0            
249             }
250              
251 0           my $string_to_sign = 'GET' . "\n" . $url . "\n" . '/onca/xml' . "\n" . join('&', @param);
252              
253 0           my $sign = hmac_sha256_base64($string_to_sign,$self->{sak});
254              
255 0           while (length($sign) % 4) {
256 0           $sign .= '=';
257             }
258              
259 0           push @param, 'Signature=' . URI::Escape::uri_escape($sign, "^A-Za-z0-9\-_.~");
260              
261 0           my $ua = LWP::UserAgent->new;
262 0           $ua->env_proxy;
263              
264 0           my $response = $ua->get('https://' . $url . '/onca/xml?' . join('&', @param));
265 0 0         if ($response->is_success()) {
266 0           return $response->decoded_content;
267             }
268             else {
269 0           warn $response->status_line;
270 0           return undef;
271             }
272             }
273              
274             1;
275              
276             __END__