File Coverage

blib/lib/Net/OAuth/Yahoo.pm
Criterion Covered Total %
statement 24 139 17.2
branch 0 30 0.0
condition 0 24 0.0
subroutine 8 20 40.0
pod 10 10 100.0
total 42 223 18.8


line stmt bran cond sub pod time code
1             package Net::OAuth::Yahoo;
2              
3 1     1   626 use strict;
  1         2  
  1         39  
4 1     1   6 use warnings;
  1         2  
  1         31  
5 1     1   1434 use LWP::UserAgent;
  1         94970  
  1         31  
6 1     1   2318 use Data::Dumper;
  1         11222  
  1         85  
7 1     1   1055 use Net::OAuth;
  1         732  
  1         32  
8 1     1   7 use URI::Escape;
  1         2  
  1         65  
9 1     1   1841 use WWW::Mechanize;
  1         183181  
  1         46  
10 1     1   1029 use YAML::Syck;
  1         2135  
  1         1492  
11              
12             =head1 NAME
13              
14             Net::OAuth::Yahoo - Provides simple interface to access Yahoo! APIs
15              
16             =head1 VERSION
17              
18             Version 0.06
19              
20             =cut
21              
22             our $VERSION = '0.06';
23             our $ERRMSG = undef;
24             $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
25              
26             =head1 SYNOPSIS
27              
28             use Net::OAuth::Yahoo;
29              
30             # Construct hashref of OAuth information
31             my $args = {
32             consumer_key => "dj0yJmk9TUhIbnlZa0tYVDAzJmQ9WVdrOWMyMUxNVXBoTjJNbWNHbzlNVGd3TnpjMU5qazJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1lNg--",
33             consumer_secret => "93dfc3e0bbeec0c63b86b6f9f3c55772e4f1fe26",
34             signature_method => "HMAC-SHA1",
35             nonce => "random_string",
36             callback => "oob",
37             };
38              
39             my $oauth = Net::OAuth::Yahoo->new( $args );
40            
41             # First, obtain the request token
42             my $request_token = $oauth->get_request_token();
43            
44             # Second, fetch the OAuth URL to be presented to the user
45             my $url = $oauth->request_auth( $request_token );
46              
47             # Third, obtain the OAuth Verifier. The real way is to present the $url to the end user, have them click on the "Agree" button,
48             # then obtain the OAuth Verifier. I wrote a simulator subroutine that does this, provided Yahoo ID and password.
49             # If you go with the real way, you can skip this step.
50             my $yid = {
51             login => login,
52             passwd => passwd,
53             };
54            
55             my $oauth_verifier = $oauth->sim_present_auth( $url, $yid );
56              
57             # Using the OAuth Verifier, let's get the token.
58             my $token = $oauth->get_token( $oauth_verifier );
59            
60             # Now it's all done, time to access some API!
61             my $api_url = "http://fantasysports.yahooapis.com/fantasy/v2/team/265.l.5098.t.2/players?format=json";
62             my $json = $oauth->access_api( $token, $api_url );
63              
64             OTHER METHODS:
65             The token expires after 1 hour, so you can reuse it until then. 3 methods are provided to facilitate the reuse.
66              
67             # Save the token in a YAML file.
68             $oauth->save_token( "filename" );
69              
70             # Load the token from a YAML file.
71             my $token = $oauth->load_token( "filename" );
72            
73             # Test the token against an URL. Returns 1 if good, 0 otherwise.
74             my $ret = $oauth->test_token( $token, $url );
75            
76             TESTS:
77             Due to the nature of this module, information such as consumer_key, consumer_secret is required. I have provided test_deeply.pl
78             in case the user wants to test the module deeply. This test script prompts for various Net::OAuth information
79             as well as Yahoo login / password.
80            
81             DEBUGGING:
82             This module returns "undef" if something goes wrong. Also, an error message is set in $Net::Oauth::Yahoo::ERRMSG.
83             The user can inspect like so:
84             my $request_token = $oauth->get_request_token();
85             print $Net::OAuth::Yahoo::ERRMSG if ( !defined $request_token );
86              
87             =head1 SUBROUTINES/METHODS
88              
89             =head2 new
90              
91             This is the constructor. Takes a hashref of the following keys, and returns the Net::OAuth::Yahoo object.
92             my $args = {
93             consumer_key => "dj0yJmk9TUhIbnlZa0tYVDAzJmQ9WVdrOWMyMUxNVXBoTjJNbWNHbzlNVGd3TnpjMU5qazJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1lNg--",
94             consumer_secret => "93dfc3e0bbeec0c63b86b6f9f3c55772e4f1fe26",
95             signature_method => "HMAC-SHA1",
96             nonce => "random_string",
97             callback => "oob",
98             };
99             my $oauth = Net::OAuth::Yahoo->new( $args );
100              
101             =cut
102              
103             sub new {
104 0     0 1   my ( $class, $args ) = @_;
105 0           my $self = bless {}, $class;
106            
107 0           $self->_validate_params( $args );
108 0           $self->{ params } = $args;
109 0           $self->{ request_token_url } = "https://api.login.yahoo.com/oauth/v2/get_request_token";
110 0           $self->{ token_url } = "https://api.login.yahoo.com/oauth/v2/get_token";
111 0           $self->{ oauth } = undef;
112              
113 0           return $self;
114             }
115              
116             =head2 get_request_token
117              
118             This method talks to the Yahoo! login server then returns the request_token. No argument is needed as the object contains
119             all the information it needs.
120             my $request_token = $oauth->get_request_token();
121              
122             =cut
123              
124             sub get_request_token {
125 0     0 1   my $self = shift;
126            
127 0           $self->{ oauth } = undef; # clears anything that may have existed
128 0           $self->{ oauth }->{ consumer_key } = $self->{ params }->{ consumer_key };
129 0           $self->{ oauth }->{ nonce } = $self->{ params }->{ nonce };
130 0           $self->{ oauth }->{ signature_method } = $self->{ params }->{ signature_method };
131 0           $self->{ oauth }->{ consumer_secret } = $self->{ params }->{ consumer_secret };
132 0           $self->{ oauth }->{ callback } = $self->{ params }->{ callback };
133 0           my $url = $self->{ request_token_url };
134 0           $self->{ request_token } = $self->_make_oauth_request( "request token", $url );
135              
136 0           return $self->{ request_token };
137             }
138              
139             =head2 get_token
140              
141             Takes the OAuth Verifier (the code that user presents to your webapp) and returns the access token.
142             my $token = $oauth->get_token( $oauth_verifier );
143              
144             =cut
145              
146             sub get_token {
147 0     0 1   my ( $self, $oauth_verifier ) = @_;
148            
149 0 0         unless ( defined $oauth_verifier ) {
150 0           $ERRMSG = "get_token() invoked without oauth_verifier";
151 0           return undef;
152             }
153            
154 0           $self->{ oauth } = undef;
155 0           $self->{ oauth }->{ consumer_key } = $self->{ params }->{ consumer_key };
156 0           $self->{ oauth }->{ signature_method } = $self->{ params }->{ signature_method };
157 0           $self->{ oauth }->{ nonce } = $self->{ params }->{ nonce };
158 0           $self->{ oauth }->{ consumer_secret } = $self->{ params }->{ consumer_secret };
159 0           $self->{ oauth }->{ verifier } = $oauth_verifier;
160 0           $self->{ oauth }->{ token } = $self->{ request_token }->{ oauth_token };
161 0           $self->{ oauth }->{ token_secret } = $self->{ request_token }->{ oauth_token_secret };
162 0           my $url = $self->{ token_url };
163 0           $self->{ token } = $self->_make_oauth_request( "access token", $url );
164            
165 0           return $self->{ token };
166             }
167              
168             =head2 access_api
169              
170             Takes a token and an URL then makes an API call againt the URL. Data from Yahoo API is returned verbatim.
171             This means if you request JSON in the URL, then you'll get JSON back; otherwise XML.
172             my $json = $oauth->access_api( $token, $url );
173              
174             =cut
175              
176             sub access_api {
177 0     0 1   my ( $self, $token, $url ) = @_;
178              
179 0 0 0       unless ( defined $token && defined $url ) {
180 0           $ERRMSG = "access_api() did not receive a token or URL";
181 0           return undef;
182             }
183            
184 0           $self->{ oauth } = undef;
185 0           $self->{ oauth }->{ consumer_key } = $self->{ params }->{ consumer_key };
186 0           $self->{ oauth }->{ nonce } = $self->{ params }->{ nonce };
187 0           $self->{ oauth }->{ signature_method } = $self->{ params }->{ signature_method };
188 0           $self->{ oauth }->{ token } = uri_unescape( $token->{ oauth_token } );
189 0           $self->{ oauth }->{ token_secret } = $token->{ oauth_token_secret };
190 0           $self->{ oauth }->{ consumer_secret } = $self->{ params }->{ consumer_secret };
191              
192 0           return $self->_make_oauth_request( "protected resource", $url );
193             }
194              
195             =head2 _make_oauth_request
196              
197             A private method that abstracts Net::OAuth calls. It is used internally by the object.
198              
199             =cut
200              
201             sub _make_oauth_request {
202 0     0     my ( $self, $req_type, $url ) = @_;
203            
204 0 0         unless ( defined $url ) {
205 0           $ERRMSG = "_make_oauth_request() could not come up with a URL to make an API request";
206 0           return undef;
207             }
208              
209 0           my $ua = LWP::UserAgent->new;
210            
211             my $request = Net::OAuth->request($req_type)->new(
212 0           %{ $self->{ oauth } },
  0            
213             request_method => "GET",
214             request_url => $url,
215             timestamp => time,
216             );
217              
218 0           $request->sign;
219 0           my $req = HTTP::Request->new( "GET" => $request->to_url );
220 0           my $res = $ua->request( $req );
221            
222             #print Dumper($res);
223              
224 0 0         if ($res->is_success) {
225 0 0 0       return $res->content unless ( $req_type eq "request token" || $req_type eq "access token" );
226            
227 0           my @args_array = split( /&/, $res->content );
228 0           my $args_ref;
229              
230 0           for ( @args_array ) {
231 0           my ( $k, $v ) = split( /=/, $_ );
232 0           $args_ref->{$k} = $v;
233             }
234 0           return $args_ref;
235             }
236              
237 0           $ERRMSG = "_make_oauth_request() did not receive a good response";
238 0           return undef;
239             }
240              
241             =head2 _validate_params
242              
243             A private method that verifies parameters in the constructor.
244              
245             =cut
246              
247             sub _validate_params {
248 0     0     my ( $self, $args ) = @_;
249 0           my @list = ( "consumer_key", "consumer_secret", "signature_method", "nonce", "callback" );
250 0           my @keys = keys %{$args};
  0            
251            
252 0           for my $required_key ( @list ) {
253 0 0         unless ( grep( /^$required_key$/, @keys ) ) {
254 0           $ERRMSG = "_validate_params() failed";
255 0           return undef;
256             }
257             }
258 0           return 1;
259             }
260              
261             =head2 request_auth
262              
263             Takes a request token then returns the URL where the end user needs to access and grant your
264             webapp to access protected resources.
265             my $url = $oauth->request_auth( $request_token );
266              
267             =cut
268              
269             sub request_auth {
270 0     0 1   my ( $self, $token ) = @_;
271            
272 0 0         if ( defined $token->{ xoauth_request_auth_url } ) {
273 0           return uri_unescape( $token->{ xoauth_request_auth_url } );
274             }
275             else {
276 0           $ERRMSG = "request_auth() did not receive a valid request token";
277 0           return undef;
278             }
279             }
280              
281             =head2 sim_present_auth
282              
283             Takes an URL and hashref of Yahoo login / password information, then simulates the end user's action
284             of granting your webapp to access protected resources. The method returns the OAuth verifier.
285             my $yid = {
286             login => "some_login",
287             passwd => "some_password",
288             }
289            
290             my $oauth_verifier = $oauth->sim_present_auth( $url, $yid );
291              
292             =cut
293              
294             sub sim_present_auth {
295 0     0 1   my ( $self, $url, $yid ) = @_;
296            
297 0 0 0       unless ( defined $url && defined $yid->{ login } && defined $yid->{ passwd } ) {
      0        
298 0           $ERRMSG = "sim_present_auth() did not receive correct set of params";
299 0           return undef;
300             }
301              
302 0           my $mech = new WWW::Mechanize( autocheck => 1 );
303 0           $mech->get( $url );
304              
305             $mech->submit_form (
306             form_name => "login_form",
307             fields => {
308             login => $yid->{ login },
309             passwd => $yid->{ passwd },
310             },
311 0           );
312              
313 0           $mech->submit_form (
314             button => "agree"
315             );
316            
317 0           my ($code) = $mech->content =~ m|(\w+)|;
318            
319 0 0         unless ( defined $code ) {
320 0           $ERRMSG = "sim_present_auth() could not get oauth_verifier";
321 0           return undef;
322             }
323            
324 0           return $code;
325             }
326              
327             =head2 save_token
328              
329             Takes a filename and dumps the token in YAML format.
330             $oauth->save_token( $file );
331              
332             =cut
333              
334             sub save_token {
335 0     0 1   my ( $self, $file ) = @_;
336            
337 0 0 0       unless ( defined $file && defined $self->{ token } ) {
338 0           $ERRMSG = "save_token() did not receive filename or, object did not have a token";
339 0           return undef;
340             }
341 0           YAML::Syck::DumpFile( $file, $self->{ token } );
342             }
343              
344             =head2 load_token
345              
346             Takes a filename and loads token from the file. Returns the token object.
347             my $token = $oauth->load_token( $file );
348              
349             =cut
350              
351             sub load_token {
352 0     0 1   my ( $self, $file ) = @_;
353            
354 0 0 0       unless ( defined $file && -f $file ) {
355 0           $ERRMSG = "load_token() could not find the file specified";
356 0           return undef;
357             }
358            
359 0           my $ref = YAML::Syck::LoadFile( $file );
360            
361 0 0 0       unless ( defined $ref->{ oauth_token } && defined $ref->{ oauth_token_secret } ) {
362 0           $ERRMSG = "load_token() token does not seem valid";
363 0           return undef;
364             }
365              
366 0           $self->{ token } = $ref;
367 0           return $ref;
368             }
369              
370             =head2 test_token
371              
372             Takes a token object and URL to try fetching some data. Returns 1 if success, 0 otherwise.
373             This method is useful to see if your loaded token has not expired.
374             my $ret_code = $oauth->test_token( $token );
375              
376             =cut
377              
378             sub test_token {
379 0     0 1   my ( $self, $token, $url ) = @_;
380            
381 0 0 0       unless ( defined $token && defined $url ) {
382 0           $ERRMSG = "test_token() did not receive the right params";
383 0           return undef;
384             }
385            
386 0           my $output = $self->access_api( $token, $url );
387 0 0         ( defined $output ) ? return 1 : return 0;
388             }
389              
390             =head2 get
391              
392             Simple getter. Returns object attributes if defined, undef otherwise.
393             my $token = $oauth->get( "token" );
394              
395             =cut
396              
397             sub get {
398 0     0 1   my ( $self, $item ) = @_;
399 0 0         ( defined $self->{ $item } ) ? return $self->{ $item } : undef;
400             }
401              
402             =head1 AUTHOR
403              
404             Satoshi Yagi, C<< >>
405              
406             =head1 BUGS
407              
408             Please report any bugs or feature requests to C, or through
409             the web interface at L. I will be notified, and then you'll
410             automatically be notified of progress on your bug as I make changes.
411              
412              
413              
414              
415             =head1 SUPPORT
416              
417             You can find documentation for this module with the perldoc command.
418              
419             perldoc Net::OAuth::Yahoo
420              
421              
422             You can also look for information at:
423              
424             =over 4
425              
426             =item * RT: CPAN's request tracker
427              
428             L
429              
430             =item * AnnoCPAN: Annotated CPAN documentation
431              
432             L
433              
434             =item * CPAN Ratings
435              
436             L
437              
438             =item * Search CPAN
439              
440             L
441              
442             =back
443              
444              
445             =head1 ACKNOWLEDGEMENTS
446              
447              
448             =head1 LICENSE AND COPYRIGHT
449              
450             Copyright 2012 Satoshi Yagi.
451              
452             This program is free software; you can redistribute it and/or modify it
453             under the terms of either: the GNU General Public License as published
454             by the Free Software Foundation; or the Artistic License.
455              
456             See http://dev.perl.org/licenses/ for more information.
457              
458              
459             =cut
460              
461             1; # End of Net::OAuth::Yahoo