File Coverage

blib/lib/Net/Twitter/Error.pm
Criterion Covered Total %
statement 35 37 94.5
branch 6 6 100.0
condition 11 18 61.1
subroutine 13 14 92.8
pod 3 3 100.0
total 68 78 87.1


line stmt bran cond sub pod time code
1             package Net::Twitter::Error;
2             $Net::Twitter::Error::VERSION = '4.01010';
3 32     32   15310 use Moose;
  32         289734  
  32         203  
4 32     32   150944 use Try::Tiny;
  32         53  
  32         1545  
5 32     32   15952 use Devel::StackTrace;
  32         69558  
  32         1010  
6              
7 32         153 use overload '""' => \&error,
8 32     32   146 'fallback' => 1;
  32         41  
9              
10             has twitter_error => ( is => 'rw', predicate => 'has_twitter_error' );
11             has http_response => ( isa => 'HTTP::Response', is => 'rw', required => 1, handles => [qw/code message/] );
12             has stack_trace => ( is => 'ro', init_arg => undef, builder => '_build_stack_trace' );
13             has _stringified => ( is => 'rw', init_arg => undef, default => undef );
14              
15             sub _build_stack_trace {
16 14     14   21 my $seen;
17 14         77 my $this_sub = (caller 0)[3];
18             Devel::StackTrace->new(frame_filter => sub {
19 58     58   1093 my $caller = shift->{caller};
20 58   100     166 my $in_nt = $caller->[0] =~ /^Net::Twitter::/ || $caller->[3] eq $this_sub;
21 58 100 66     279 ($seen ||= $in_nt) && !$in_nt || 0;
      66        
22 14         113 });
23             }
24              
25             sub error {
26 14     14 1 1572 my $self = shift;
27              
28 14 100       357 return $self->_stringified if $self->_stringified;
29              
30             # Don't walk on $@
31 9         9 local $@;
32              
33 9   66     223 my $error = $self->has_twitter_error && $self->twitter_error_text
34             || $self->http_response->status_line;
35              
36 9         359 my ($location) = $self->stack_trace->frame(0)->as_string =~ /( at .*)/;
37 9   50     1085 return $self->_stringified($error . ($location || ''));
38             }
39              
40             sub twitter_error_text {
41 11     11 1 1037 my $self = shift;
42             # Twitter does not return a consistent error structure, so we have to
43             # try each known (or guessed) variant to find a suitable message...
44              
45 11 100       282 return '' unless $self->has_twitter_error;
46 10         206 my $e = $self->twitter_error;
47              
48             # the newest: array of errors
49             return try {
50 10     10   190 exists $e->{errors}
51             && exists $e->{errors}[0]
52             && exists $e->{errors}[0]{message}
53             && $e->{errors}[0]{message};
54             }
55              
56             # it's single error variant
57             || try {
58 7     7   183 exists $e->{error}
59             && exists $e->{error}{message}
60             && $e->{error}{message};
61             }
62              
63             # or maybe it's not that deep (documentation would be helpful, here, Twitter!)
64 5     5   105 || try { exists $e->{message} && $e->{message} }
65              
66             # the original error structure
67 5     5   103 || try { exists $e->{error} && $e->{error} }
68 10   50     56 || '';
69             }
70              
71              
72             sub twitter_error_code {
73 0     0 1   my $self = shift;
74              
75 0   0       return $self->has_twitter_error
76             && exists $self->twitter_error->{errors}
77             && exists $self->twitter_error->{errors}[0]
78             && exists $self->twitter_error->{errors}[0]{code}
79             && $self->twitter_error->{errors}[0]{code}
80             || 0;
81             }
82              
83             __PACKAGE__->meta->make_immutable;
84              
85 32     32   12741 no Moose;
  32         44  
  32         185  
86              
87             1;
88              
89             __END__
90              
91             =head1 NAME
92              
93             Net::Twitter::Error - A Net::Twitter exception object
94              
95             =head1 VERSION
96              
97             version 4.01010
98              
99             =head1 SYNOPSIS
100              
101             my $nt = Net::Twitter->new(username => $username, password => $password);
102              
103             my $followers = eval { $nt->followers };
104             if ( my $err = $@ ) {
105             die $@ unless blessed $err and $err->isa('Net::Twitter::Error');
106              
107             warn "HTTP Response Code: ", $err->code, "\n",
108             "HTTP Message......: ", $err->message, "\n",
109             "Twitter error.....: ", $err->error, "\n";
110             }
111              
112             =head1 DESCRIPTION
113              
114             B<Net::Twitter::Error> encapsulates the C<HTTP::Response> and Twitter
115             error HASH (if any) resulting from a failed API call.
116              
117             =head1 METHODS
118              
119             =over 4
120              
121             =item new
122              
123             Constructs a C<Net::Twitter::Error> object. It accepts the following parameters:
124              
125             =over 4
126              
127             =item http_response
128              
129             An C<HTTP::Response> object, required.
130              
131             =item twitter_error
132              
133             The error returned by Twitter as a HASH ref. Optional, since some API errors do
134             not include a response from Twitter. They may, instead, be the result of network
135             timeouts, proxy errors, or some other problem that prevents an API response.
136              
137             =back
138              
139             =item twitter_error
140              
141             Get or set the Twitter error HASH.
142              
143             =item http_response
144              
145             Get or set the C<HTTP::Response> object.
146              
147             =item code
148              
149             Returns the HTTP response code.
150              
151             =item message
152              
153             Returns the HTTP response message.
154              
155             =item has_twitter_error
156              
157             Returns true if the object contains a Twitter error HASH.
158              
159             =item error
160              
161             Returns the C<error> value from the C<twitter_error> HASH ref if there is one.
162             Otherwise, it returns the string "[unknown]". Includes a stack trace.
163              
164             =item twitter_error_text
165              
166             Returns the C<error> value from the C<twitter_error> HASH ref if there is one.
167             Otherwise, returns an empty string
168              
169             =item twitter_error_code
170              
171             Returns the first numeric twitter error code from the JSON response body, if
172             there is one. Otherwise, it returns 0 so the result should always be safe use
173             in a numeric test.
174              
175             See L<Twitter Error Codes|https://dev.twitter.com/docs/error-codes-responses>
176             for a list of defined error codes.
177              
178             =back
179              
180             =head1 SEE ALSO
181              
182             =over 4
183              
184             =item L<Net::Twitter>
185              
186             =back
187              
188             =head1 AUTHOR
189              
190             Marc Mims <marc@questright.com>
191              
192             =head1 LICENSE
193              
194             Copyright (c) 2009 Marc Mims
195              
196             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
197              
198             =head1 DISCLAIMER OF WARRANTY
199              
200             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
201             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
202             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
203             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
204             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
205             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
206             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
207             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
208             NECESSARY SERVICING, REPAIR, OR CORRECTION.
209              
210             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
211             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
212             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
213             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
214             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
215             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
216             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
217             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
218             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
219             SUCH DAMAGES.