File Coverage

blib/lib/WWW/TypePad.pm
Criterion Covered Total %
statement 69 130 53.0
branch 0 26 0.0
condition 0 12 0.0
subroutine 23 31 74.1
pod 0 5 0.0
total 92 204 45.1


line stmt bran cond sub pod time code
1             package WWW::TypePad;
2 1     1   14327 use strict;
  1         1  
  1         30  
3 1     1   14 use 5.008_001;
  1         2  
  1         36  
4              
5             our $VERSION = '0.009_01';
6              
7 1     1   420 use Any::Moose;
  1         21700  
  1         6  
8 1     1   1079 use JSON;
  1         10421  
  1         5  
9 1     1   703 use LWP::UserAgent;
  1         36197  
  1         34  
10 1     1   528 use Net::OAuth::Simple;
  1         28788  
  1         33  
11 1     1   371 use WWW::TypePad::Util;
  1         2  
  1         24  
12 1     1   303 use WWW::TypePad::Error;
  1         1  
  1         29  
13              
14             # TODO import flag to preload them all
15 1     1   306 use WWW::TypePad::ApiKeys;
  1         2  
  1         27  
16 1     1   309 use WWW::TypePad::Applications;
  1         2  
  1         40  
17 1     1   328 use WWW::TypePad::Assets;
  1         2  
  1         29  
18 1     1   305 use WWW::TypePad::AuthTokens;
  1         2  
  1         27  
19 1     1   339 use WWW::TypePad::BatchProcessor;
  1         2  
  1         24  
20 1     1   358 use WWW::TypePad::Blogs;
  1         2  
  1         26  
21 1     1   306 use WWW::TypePad::BrowserUpload;
  1         2  
  1         27  
22 1     1   304 use WWW::TypePad::Events;
  1         1  
  1         31  
23 1     1   365 use WWW::TypePad::Favorites;
  1         1  
  1         26  
24 1     1   357 use WWW::TypePad::Groups;
  1         2  
  1         41  
25 1     1   342 use WWW::TypePad::Nouns;
  1         2  
  1         25  
26 1     1   347 use WWW::TypePad::ObjectTypes;
  1         3  
  1         27  
27 1     1   410 use WWW::TypePad::Relationships;
  1         1  
  1         26  
28 1     1   309 use WWW::TypePad::Users;
  1         2  
  1         620  
29              
30             has 'consumer_key' => ( is => 'rw' );
31             has 'consumer_secret' => ( is => 'rw' );
32             has 'access_token' => ( is => 'rw' );
33             has 'access_token_secret' => ( is => 'rw' );
34             has 'host' => ( is => 'rw', default => 'api.typepad.com' );
35             has '_oauth' => ( is => 'rw' );
36              
37             for my $object_type (qw( apikeys applications assets auth_tokens batch_processor blogs browser_upload
38             events favorites groups nouns objecttypes relationships users )) {
39             my $backend_class = ucfirst $object_type;
40             $backend_class =~ s/_(\w)/uc $1/eg;
41             $backend_class = "WWW::TypePad::$backend_class";
42             has $object_type => (
43             is => 'rw', lazy => 1,
44             default => sub { $backend_class->new({ base => $_[0] }) },
45             );
46             }
47              
48             sub oauth {
49 0     0 0   my $api = shift;
50 0 0         unless ( defined $api->_oauth ) {
51 0           my $apikey = $api->get_apikey( $api->consumer_key );
52 0           my $links = $apikey->{owner}{links};
53              
54 0           $api->_oauth( Net::OAuth::Simple::AuthHeader->new(
55             tokens => {
56             consumer_key => $api->consumer_key,
57             consumer_secret => $api->consumer_secret,
58             access_token => $api->access_token,
59             access_token_secret => $api->access_token_secret,
60             },
61             urls => {
62             authorization_url => WWW::TypePad::Util::l( $links, 'oauth-authorization-page' ),
63             request_token_url => WWW::TypePad::Util::l( $links, 'oauth-request-token-endpoint' ),
64             access_token_url => WWW::TypePad::Util::l( $links, 'oauth-access-token-endpoint' ),
65             },
66             ) );
67             }
68 0           return $api->_oauth;
69             }
70              
71             sub get_apikey {
72 0     0 0   my $api = shift;
73 0           my( $key ) = @_;
74 0           return $api->call_anon( GET => '/api-keys/' . $key . '.json' );
75             }
76              
77             sub uri_for {
78 0     0 0   my $api = shift;
79 0           my( $path ) = @_;
80 0           return 'http://' . $api->host . $path;
81             }
82              
83             sub call {
84 0     0 0   my $api = shift;
85 0           return $api->_call(0, @_);
86             }
87              
88             sub call_anon {
89 0     0 0   my $api = shift;
90 0           return $api->_call(1, @_);
91             }
92              
93             sub _call {
94 0     0     my $api = shift;
95 0           my( $anon, $method, $uri, $qs ) = @_;
96 0 0         unless ( $uri =~ /^http/ ) {
97 0           $uri = $api->uri_for( $uri );
98             }
99 0 0 0       if ( $method eq 'GET'&& $qs ) {
100 0           $uri = URI->new( $uri );
101 0           $uri->query_form( $qs );
102             }
103 0           my $res;
104 0 0 0       if ( $api->access_token && !$anon ) {
105 0           $uri =~ s/^http:/https:/;
106              
107 0           my %extra;
108 0 0 0       if (($method eq 'POST' or $method eq 'PUT') and $qs) {
      0        
109 0           $extra{ContentBody} = JSON::encode_json($qs);
110 0           $extra{ContentType} = 'application/json';
111             }
112              
113 0           $res = $api->oauth->make_restricted_request( $uri, $method, %extra );
114             } else {
115 0           my $ua = LWP::UserAgent->new;
116 0           my $req = HTTP::Request->new( $method => $uri );
117 0           $res = $ua->request( $req );
118             }
119              
120 0 0         unless ( $res->is_success ) {
121 0           WWW::TypePad::Error::HTTP->throw( $res->code, $res->message );
122             }
123              
124 0 0         return 1 if $res->code == 204;
125 0           return JSON::decode_json( $res->content );
126             }
127              
128             package Net::OAuth::Simple::AuthHeader;
129             # we need Net::OAuth::Simple to make requests with the OAuth credentials
130             # in an Authorization header, as required by the API, rather than the query string
131              
132 1     1   5 use base qw( Net::OAuth::Simple );
  1         1  
  1         375  
133              
134             sub new {
135 0     0     my $class = shift;
136 0           my $self = $class->SUPER::new( @_ );
137 0           $self->{browser}->max_redirect( 0 );
138 0           return $self;
139             }
140              
141             sub make_restricted_request {
142 0     0     my $self = shift;
143 0 0         croak $Net::OAuth::Simple::UNAUTHORIZED unless $self->authorized;
144              
145 0           my( $url, $method, %extras ) = @_;
146              
147 0           my $uri = URI->new( $url );
148 0           my %query = $uri->query_form;
149 0           $uri->query_form( {} );
150              
151 0           $method = lc $method;
152              
153 0           my $content_body = delete $extras{ContentBody};
154 0           my $content_type = delete $extras{ContentType};
155              
156 0 0         my $request = Net::OAuth::ProtectedResourceRequest->new(
157             consumer_key => $self->consumer_key,
158             consumer_secret => $self->consumer_secret,
159             request_url => $uri,
160             request_method => uc( $method ),
161             signature_method => $self->signature_method,
162             protocol_version => $self->oauth_1_0a ?
163             Net::OAuth::PROTOCOL_VERSION_1_0A :
164             Net::OAuth::PROTOCOL_VERSION_1_0,
165             timestamp => time,
166             nonce => $self->_nonce,
167             extra_params => \%query,
168             token => $self->access_token,
169             token_secret => $self->access_token_secret,
170             extra_params => \%extras,
171             );
172 0           $request->sign;
173 0 0         die "COULDN'T VERIFY! Check OAuth parameters.\n"
174             unless $request->verify;
175              
176 0           my $request_url = URI->new( $url );
177 0 0         my $response = $self->{browser}->$method(
178             $request_url, 'Authorization' => $request->to_authorization_header,
179             ( $content_body ? (
180             'Content-Type' => $content_type,
181             'Content-Length' => length $content_body,
182             'Content' => $content_body,
183             ) : () ),
184             );
185              
186 0 0         if ( $response->is_redirect ) {
187 0           my $referral_uri = $response->header( 'Location' );
188 0           return $self->make_restricted_request(
189             $referral_uri,
190             $method,
191             %extras,
192             );
193             }
194              
195 0 0         die "$method on $request_url failed: " . $response->status_line
196             unless $response->is_success;
197              
198 0           return $response;
199             }
200              
201             1;
202             __END__