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   373 use strict;
  1         1  
  1         22  
4 1     1   3 use warnings;
  1         1  
  1         17  
5 1     1   526 use LWP::UserAgent;
  1         32308  
  1         24  
6 1     1   486 use Data::Dumper;
  1         4608  
  1         47  
7 1     1   432 use Net::OAuth;
  1         464  
  1         22  
8 1     1   4 use URI::Escape;
  1         1  
  1         40  
9 1     1   637 use WWW::Mechanize;
  1         73587  
  1         33  
10 1     1   439 use YAML::Syck;
  1         1330  
  1         1085  
11              
12             =head1 NAME
13              
14             Net::OAuth::Yahoo - Provides simple interface to access Yahoo! APIs
15              
16             =head1 VERSION
17              
18             Version 1.0.0
19              
20             =cut
21              
22             our $VERSION = '1.0.0';
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_number => 0,
307             fields => {
308             login => $yid->{login},
309             passwd => $yid->{passwd},
310             },
311 0           );
312              
313 0           $mech->submit_form( button => "agree" );
314              
315 0           my ($code) = $mech->content =~ m|(\w+)|;
316              
317 0 0         unless ( defined $code ) {
318 0           $ERRMSG = "sim_present_auth() could not get oauth_verifier";
319 0           return undef;
320             }
321              
322 0           return $code;
323             }
324              
325             =head2 save_token
326              
327             Takes a filename and dumps the token in YAML format.
328             $oauth->save_token( $file );
329              
330             =cut
331              
332             sub save_token {
333 0     0 1   my ( $self, $file ) = @_;
334              
335 0 0 0       unless ( defined $file && defined $self->{token} ) {
336 0           $ERRMSG = "save_token() did not receive filename or, object did not have a token";
337 0           return undef;
338             }
339 0           YAML::Syck::DumpFile( $file, $self->{token} );
340             }
341              
342             =head2 load_token
343              
344             Takes a filename and loads token from the file. Returns the token object.
345             my $token = $oauth->load_token( $file );
346              
347             =cut
348              
349             sub load_token {
350 0     0 1   my ( $self, $file ) = @_;
351              
352 0 0 0       unless ( defined $file && -f $file ) {
353 0           $ERRMSG = "load_token() could not find the file specified";
354 0           return undef;
355             }
356              
357 0           my $ref = YAML::Syck::LoadFile($file);
358              
359 0 0 0       unless ( defined $ref->{oauth_token} && defined $ref->{oauth_token_secret} ) {
360 0           $ERRMSG = "load_token() token does not seem valid";
361 0           return undef;
362             }
363              
364 0           $self->{token} = $ref;
365 0           return $ref;
366             }
367              
368             =head2 test_token
369              
370             Takes a token object and URL to try fetching some data. Returns 1 if success, 0 otherwise.
371             This method is useful to see if your loaded token has not expired.
372             my $ret_code = $oauth->test_token( $token );
373              
374             =cut
375              
376             sub test_token {
377 0     0 1   my ( $self, $token, $url ) = @_;
378              
379 0 0 0       unless ( defined $token && defined $url ) {
380 0           $ERRMSG = "test_token() did not receive the right params";
381 0           return undef;
382             }
383              
384 0           my $output = $self->access_api( $token, $url );
385 0 0         ( defined $output ) ? return 1 : return 0;
386             }
387              
388             =head2 get
389              
390             Simple getter. Returns object attributes if defined, undef otherwise.
391             my $token = $oauth->get( "token" );
392              
393             =cut
394              
395             sub get {
396 0     0 1   my ( $self, $item ) = @_;
397 0 0         ( defined $self->{$item} ) ? return $self->{$item} : undef;
398             }
399              
400             =head1 AUTHOR
401              
402             Satoshi Yagi, C<< >>
403              
404             =head1 BUGS
405              
406             Please report any bugs or feature requests to C, or through
407             the web interface at L. I will be notified, and then you'll
408             automatically be notified of progress on your bug as I make changes.
409              
410              
411              
412              
413             =head1 SUPPORT
414              
415             You can find documentation for this module with the perldoc command.
416              
417             perldoc Net::OAuth::Yahoo
418              
419              
420             You can also look for information at:
421              
422             =over 4
423              
424             =item * RT: CPAN's request tracker
425              
426             L
427              
428             =item * AnnoCPAN: Annotated CPAN documentation
429              
430             L
431              
432             =item * CPAN Ratings
433              
434             L
435              
436             =item * Search CPAN
437              
438             L
439              
440             =back
441              
442              
443             =head1 ACKNOWLEDGEMENTS
444              
445              
446             =head1 LICENSE AND COPYRIGHT
447              
448             Copyright 2012 Satoshi Yagi.
449              
450             This program is free software; you can redistribute it and/or modify it
451             under the terms of either: the GNU General Public License as published
452             by the Free Software Foundation; or the Artistic License.
453              
454             See http://dev.perl.org/licenses/ for more information.
455              
456              
457             =cut
458              
459             1; # End of Net::OAuth::Yahoo