File Coverage

blib/lib/WWW/Grooveshark/Response.pm
Criterion Covered Total %
statement 86 104 82.6
branch 5 26 19.2
condition 1 3 33.3
subroutine 28 34 82.3
pod 10 10 100.0
total 130 177 73.4


line stmt bran cond sub pod time code
1             package WWW::Grooveshark::Response;
2              
3 1     1   31 use 5.006;
  1         4  
  1         84  
4 1     1   6 use strict;
  1         2  
  1         50  
5 1     1   5 use warnings;
  1         2  
  1         66  
6              
7             =head1 NAME
8              
9             WWW::Grooveshark::Response - Grooveshark API response message
10              
11             =head1 VERSION
12              
13             This document describes C version 0.02 (July 22,
14             2009).
15              
16             This module is distributed with L and therefore takes its
17             version from that module. The latest version of both components is hosted on
18             Google Code as part of . Significant
19             changes are also contributed to CPAN:
20             http://search.cpan.org/dist/WWW-Grooveshark/.
21              
22             =cut
23              
24             our $VERSION = '0.02';
25             $VERSION = eval $VERSION;
26              
27             =head1 SYNOPSIS
28              
29             Response objects are returned by the API methods of L:
30              
31             # some code to prepare $gs
32            
33             my $response = $gs->search_songs(query => "The Beatles");
34            
35             if($response->is_fault) {
36             print STDERR $response->fault_line;
37             }
38             else {
39             for($response->songs) {
40             # do something interesting
41             }
42             }
43              
44             =head1 DESCRIPTION
45              
46             C encapsulates a response message from the
47             Grooveshark API. A response consists of a header (sessionID, hostname,
48             etc.) and either a result (in the case of "success" responses) or a fault code
49             and message (in case of errors).
50              
51             Internally, this class is just a Ced decoding of the JSON response, so
52             if you're too lazy or stubborn to familiarize yourself with this interface,
53             you may access the data structure directly like any hashref.
54              
55             =cut
56              
57 1     1   5 use Carp;
  1         16  
  1         67  
58 1     1   6 use Exporter;
  1         1  
  1         43  
59 1     1   8918 use NEXT 0.61; # earlier versions seem to have a NEXT::AUTOLOAD bug
  1         3463  
  1         2817  
60              
61             =head1 EXPORTS
62              
63             None by default. The ":fault" tag can bring the integer fault constants in
64             your namespace with: C. The
65             constants are listed as part of the documentation of the C
66             method below.
67              
68             =cut
69              
70             my %fault = (
71             MALFORMED_REQUEST_FAULT => 1,
72             NO_METHOD_FAULT => 2,
73             MISSING_OR_INVALID_PARAMETERS_FAULT => 4,
74             SESSION_FAULT => 8,
75             AUTHENTICATION_FAULT => 16,
76             AUTHENTICATION_FAILED_FAULT => 32,
77             STREAM_FAULT => 64,
78             API_KEY_FAULT => 128,
79             USER_BLOCKED_FAULT => 256,
80             INTERNAL_FAULT => 512,
81             SSL_FAULT => 1024,
82             ACCESS_RIGHTS_FAULT => 2048,
83             NO_RESOURCE_FAULT => 4096,
84             OFFLINE_FAULT => 8192,
85             );
86             while(my($key, $val) = each %fault) {
87 1     1   9 eval "use constant $key => $val;";
  1     1   1  
  1     1   359  
  1     1   8  
  1     1   1  
  1     1   349  
  1     1   7  
  1     1   1  
  1     1   138  
  1     1   5  
  1     1   3  
  1     1   39  
  1     1   5  
  1     1   3  
  1         36  
  1         5  
  1         2  
  1         37  
  1         6  
  1         2  
  1         50  
  1         5  
  1         2  
  1         34  
  1         7  
  1         2  
  1         38  
  1         5  
  1         2  
  1         34  
  1         6  
  1         1  
  1         39  
  1         5  
  1         2  
  1         41  
  1         7  
  1         1  
  1         53  
  1         6  
  1         1  
  1         35  
88             }
89              
90             our @ISA = qw(Exporter);
91             our %EXPORT_TAGS = (fault => [keys %fault]);
92             our @EXPORT_OK = @{$EXPORT_TAGS{fault}};
93              
94             our $AUTOLOAD;
95              
96             =head1 CONSTRUCTOR
97              
98             If you need to "manually" craft an object of this class, this is how.
99              
100             =over 4
101              
102             =item WWW::Grooveshark::Response->new( \%OBJECT | %OBJECT )
103              
104             Builds a L object from the given hashref or hash.
105              
106             =cut
107              
108             sub new {
109 1     1 1 3 my $pkg = shift;
110 1         2 my $self;
111 1 50       6 if(1 == scalar(@_)) {
112 1         1 $self = shift;
113 1         4 my $ref = ref($self);
114 1 50 33     12 croak "Non-hashref argument passed to one-arg $pkg constructor"
115             unless $ref && ($ref eq 'HASH');
116             }
117             else {
118 0         0 $self = {@_};
119             }
120 1         37 return bless($self, $pkg);
121             }
122              
123             =back
124              
125             =head1 METHOD AUTOLOADING
126              
127             More often than not, you will probably be accessing the result element of a
128             response object. Because C<$response-Eresult('key')> is only marginally
129             better than C<$response-E{result}-E{key}>, this class uses
130             Cing to support the terser C<$response-Ekey> syntax, as with the
131             C "method" in the L. This will only work with success
132             responses, so ask each object if it C. If the result does not
133             contain the given key, the usual unknown method handling mechanism will take
134             over.
135              
136             =cut
137              
138             sub AUTOLOAD {
139 1     1   3 my $self = shift;
140            
141 1 50       8 croak 'Not a reference' unless ref($self);
142              
143 1         17 my($method) = ($AUTOLOAD =~ /(\w*)$/);
144              
145 1 50       7 if($self->is_fault) {
146 1         6 carp $self->fault_line;
147 1         266 carp 'Uh oh, autoloading on a fault response, this could end badly';
148             }
149             else {
150 0         0 my $res = $self->{result};
151 0 0       0 if(ref($res)) {
152 0         0 my %res = %$res;
153 0 0       0 return $self->result($method) if exists($res{$method});
154             }
155             }
156              
157 1         90 eval { return $self->NEXT::ACTUAL::AUTOLOAD(@_); };
  1         13  
158 1 50       10932 croak "Problem while autoloading $AUTOLOAD: $@" if $@;
159             }
160              
161             # provided to appease AUTOLOAD
162 0     0   0 sub DESTROY {}
163              
164             #=head1 OVERLOADED OPERATIONS
165             #
166             #=cut
167             use overload
168 0     0   0 'bool' => sub { return !shift->is_fault; },
169 1     1   19 ;
  1         3  
  1         17  
170              
171             =head1 METHODS
172              
173             The following methods exist for all class instances:
174              
175             =over 4
176              
177             =item $response->header( $KEY )
178              
179             Returns the header element corresponding to $KEY.
180              
181             =cut
182              
183             sub header {
184 0     0 1 0 return shift->{header}->{shift()};
185             }
186              
187             =item $response->sessionID( )
188              
189             Returns the ID of the session that created this response object. This is a
190             shortcut for C<$response-Eheader('sessionID')>.
191              
192             =cut
193              
194             sub sessionID {
195 0     0 1 0 return shift->header('sessionID');
196             }
197              
198             =item $response->is_fault( )
199              
200             Checks whether this response object represents a fault.
201              
202             =cut
203              
204             sub is_fault {
205 1     1 1 60 return exists(shift->{fault});
206             }
207              
208             =item $response->result( [ $KEY ] )
209              
210             Returns the result element corresponding to $KEY, or the whole result part of
211             the response if no $KEY is specified. This will probably only give a
212             meaningful result if C is false. In C context, this method
213             will return references where applicable. In list context, it will
214             dereference arrayrefs and hashrefs before returning them.
215              
216             =cut
217              
218             sub result {
219 0     0 1 0 my $res = shift->{result};
220            
221             # is there an argument? grab the proper key, otherwise the whole result
222 0 0       0 my $ret = scalar(@_) ? (ref($res) ? $res->{shift()} : undef) : $res;
    0          
223            
224             # take care of list context
225 0 0       0 if(wantarray) {
226 0         0 my $ref = ref($ret);
227 0 0       0 if($ref) {
228 0 0       0 return @$ret if $ref eq 'ARRAY';
229 0 0       0 return %$ret if $ref eq 'HASH';
230             }
231             }
232            
233 0         0 return $ret;
234             }
235              
236             =item $response->fault( $KEY )
237              
238             Returns the fault element corresponding to $KEY. This will only give a
239             meaningful result if C is true.
240              
241             =cut
242              
243             sub fault {
244 2     2 1 14 return shift->{fault}->{shift()};
245             }
246              
247             =item $response->fault_code( )
248              
249             Returns the integer code of the fault represented by this response object.
250             This is a shortcut for C<$response-Efault('code')>. Check Grooveshark's
251             API for the most up-to-date information about fault codes. The standard set
252             at the time of this writing is listed below, along with the corresponding
253             names for the constants that may be exported by this module (in parentheses).
254              
255             =over 4
256              
257             =item 1 Malformed request (C)
258              
259             Some part of the request, most likely the parameters, was malformed.
260              
261             =item 2 No method (C)
262              
263             The requested method does not exist.
264              
265             =item 4 Missing or invalid parameters (C)
266              
267             Method parameters were missing or incorrectly formatted.
268              
269             =item 8 Session (C)
270              
271             Most likely the session has expired, or it failed to start.
272              
273             =item 16 Authentication (C)
274              
275             Authentication is required to access the invoked method.
276              
277             =item 32 Authentication failed (C)
278              
279             The supplied user credentials were incorrect.
280              
281             =item 64 Stream (C)
282              
283             There was an error creating a stream key, or returning a stream server URL.
284              
285             =item 128 API key (C)
286              
287             The supplied API key is invalid, or is no longer active.
288              
289             =item 256 User blocked (C)
290              
291             A user's privacy restrictions have blocked access to their account through the API.
292              
293             =item 512 Internal (C)
294              
295             There was an error internal to the API while fulfilling the request.
296              
297             =item 1024 SSL (C)
298              
299             SSL is required to access the requested method.
300              
301             =item 2048 Access rights (C)
302              
303             Your API key does not have the proper access rights to invoke the requested method.
304              
305             =item 4096 No resource (C)
306              
307             Something doesn't exist, perhaps a userID, artistID, etc.
308              
309             =item 8192 Offline (C)
310              
311             The requested method is offline and is temporarily unavailable.
312              
313             =back
314              
315             =cut
316              
317             sub fault_code {
318 1     1 1 6 return shift->fault('code');
319             }
320              
321             =item $response->fault_message( )
322              
323             Returns the contextually customized message of the fault represented by this
324             response object. This is a shortcut for C<$response-Efault('message')>.
325              
326             =cut
327              
328             sub fault_message {
329 1     1 1 4 return shift->fault('message');
330             }
331              
332             =item $response->fault_details( )
333              
334             Returns the (possibly undefined) details of the fault represented by this
335             response object. This is a shortcut for C<$response-Efault('details')>.
336              
337             =cut
338              
339             sub fault_details {
340 0     0 1 0 return shift->fault('details');
341             }
342              
343             =item $response->fault_line( )
344              
345             Returns an HTTP style status line, containing the fault code and message.
346              
347             =cut
348              
349             sub fault_line {
350 1     1 1 3 my $self = shift;
351 1         5 my $ret = sprintf("%s %s\n", $self->fault_code, $self->fault_message);
352             # add details here perhaps?
353 1         236 return $ret;
354             }
355              
356             =back
357              
358             =cut
359              
360             1;
361              
362             __END__