File Coverage

blib/lib/WebService/Blogger.pm
Criterion Covered Total %
statement 32 72 44.4
branch 0 16 0.0
condition 0 14 0.0
subroutine 11 18 61.1
pod 1 6 16.6
total 44 126 34.9


line stmt bran cond sub pod time code
1             package WebService::Blogger;
2             our $VERSION = '0.23';
3 2     2   84668 use warnings;
  2         14  
  2         71  
4 2     2   10 use strict;
  2         4  
  2         75  
5              
6 2     2   1155 use Moose;
  2         965908  
  2         13  
7 2     2   17087 use LWP::UserAgent;
  2         85934  
  2         75  
8 2     2   1052 use HTTP::Request::Common;
  2         4582  
  2         182  
9 2     2   1689 use XML::Simple;
  2         18745  
  2         15  
10 2     2   1332 use File::stat;
  2         15837  
  2         10  
11 2     2   1532 use Data::Dumper;
  2         14436  
  2         134  
12 2     2   1139 use Encode ();
  2         28721  
  2         64  
13              
14 2     2   1094 use WebService::Blogger::Blog;
  2         7  
  2         1765  
15              
16             # Authentication credentials. Cannot be changed after object is created.
17             has login_id => ( is => 'ro', isa => 'Str');
18             has password => ( is => 'ro', isa => 'Str');
19              
20             # Blogs belonging to the account.
21             has blogs => (
22             is => 'ro',
23             isa => 'ArrayRef[WebService::Blogger::Blog]',
24             lazy_build => 1,
25             auto_deref => 1,
26             );
27              
28             # LWP:::UserAgent instance for all requests during the session.
29             has ua => (
30             lazy_build => 1,
31             is => 'ro',
32             );
33              
34             # Speed Moose up.
35             __PACKAGE__->meta->make_immutable;
36              
37              
38             sub BUILDARGS {
39             ## Loads credentials from credentials file.
40 0     0 1 0 my $class = shift;
41 0         0 my %attrs = @_;
42              
43 0 0 0     0 return \%attrs if defined $attrs{login_id} && defined $attrs{password};
44              
45             # See if there's a file with login credentials and return if there isn't.
46             my $creds_file_name
47             = $attrs{creds_file_name}
48             || $ENV{WEBSERVICE_BLOGGER_CONFIG}
49 0   0     0 || "$ENV{HOME}/.www_blogger_rc";
50              
51 0 0       0 return \%attrs unless -s $creds_file_name;
52              
53 0 0       0 die "Credentials file \"$creds_file_name\" is accessible by others. "
54             . 'Please make it readable by the owner only, for security reasons.'
55             if stat($creds_file_name)->mode & 07777 != 0600;
56              
57             # Read file contents into a string.
58 0 0       0 open my $creds_fh, '<', $creds_file_name
59             or die "Unable to read login credentials from $creds_file_name: $!";
60 0         0 my $creds_file_contents = join '', <$creds_fh>;
61 0         0 close $creds_fh;
62              
63             # Parse and return available credentials to be set as object attributes.
64 0         0 my %parsed_creds = $creds_file_contents =~ /^(\S+)\s*=\s*(\S+)/gm;
65             $attrs{login_id} = $parsed_creds{username} if !defined $attrs{login_id}
66 0 0 0     0 && defined $parsed_creds{username};
67             $attrs{password} = $parsed_creds{password} if !defined $attrs{password}
68 0 0 0     0 && defined $parsed_creds{password};
69 0         0 return \%attrs;
70             }
71              
72              
73             sub BUILD {
74             ## Authenticates with Blogger.
75 0     0 0 0 my ($self,$creds) = @_;
76              
77             # Submit request for authentiaction token.
78             my $response = $self->{'ua'}->post('https://accounts.google.com/o/oauth2/auth',
79             { basic_authentication => $self->{'base64'},
80             Content_Type => 'application/x-www-form-urlencoded',
81             grant_type => 'client_credentials',
82             client_id => $self->{'key'},
83 0         0 client_secret => $self->{'secret'},
84             }
85             );
86              
87 0         0 print Dumper($response);
88 0         0 exit(0);
89              
90             #There are 4 grant types defined in the OAuth spec.
91             # Authorization code
92             # Implicit
93             # Resource owner password credentials
94             # Client credentials
95              
96              
97              
98              
99             # my $response = $self->ua->post('https://www.google.co.uk/accounts/ClientLogin',
100             # {
101             # Email => $self->login_id,
102             # Passwd => $self->password,
103             # service => 'blogger',
104             # }
105             # );
106              
107             # Check success, parsing Google error message, if available.
108 0 0       0 unless ($response->is_success) {
109 0   0     0 my $error_msg = ($response->content =~ /\bError=(.+)/)[0] || 'Google error message unavailable';
110 0         0 die 'HTTP error when trying to authenticate: ' . $response->status_line . " ($error_msg)";
111             }
112              
113             # Parse authentication token and set it as default header for user agent object.
114 0 0       0 my ($auth_token) = $response->content =~ /\bAuth=(.+)/
115             or die 'Authentication token not found in the response: ' . $response->content;
116 0         0 $self->ua->default_header(Authorization => "GoogleLogin auth=$auth_token");
117              
118             # Set default content type for all requests.
119 0         0 $self->ua->default_header(Content_Type => 'application/atom+xml');
120             }
121              
122              
123             sub creds_file_name {
124             ## Class method. Returns name of optional file with login credentials.
125 1     1 0 96 my $self = shift;
126              
127             # Use the same name and format as WWW::Blogger::XML::API, for compatibility.
128 1         71 return "$ENV{HOME}/.www_blogger_rc";
129             }
130              
131              
132             sub _build_ua {
133             ## Populares 'ua' property.
134 0     0     my $self = shift;
135              
136 0           return LWP::UserAgent->new;
137             }
138              
139              
140             sub _build_blogs {
141             ## Populates 'blogs' property with list of instances of WebService::Blogger::Blog.
142 0     0     my $self = shift;
143              
144             # Get list of blogs.
145 0           my $response = $self->http_get('http://www.blogger.com/feeds/default/blogs');
146 0           my $response_tree = XML::Simple::XMLin($response->content, ForceArray => 1);
147              
148             # Populate the accessor with blog objects generated from the list.
149             return [
150             map WebService::Blogger::Blog->new(
151             source_xml_tree => $_,
152             blogger => $self,
153             ),
154 0           @{ $response_tree->{entry} }
  0            
155             ];
156             }
157              
158              
159             sub http_put {
160             ## Executes a PUT request to the service.
161 0     0 0   my $self = shift;
162 0           my ($url, $content) = @_;
163              
164 0           my $request = HTTP::Request->new(PUT => $url, $self->ua->default_headers,
165             Encode::encode_utf8($content));
166 0           return $self->ua->request($request);
167             }
168              
169              
170             sub http_get {
171             ## Executes a GET request to the service.
172 0     0 0   my $self = shift;
173 0           my @req_args = @_;
174              
175 0           return $self->ua->get(@req_args);
176             }
177              
178              
179             sub http_post {
180             ## Executes a POST request to the service.
181 0     0 0   my $self = shift;
182 0           my @args = @_;
183              
184 0           return $self->ua->request(HTTP::Request::Common::POST(@args));
185             }
186              
187              
188             1;
189              
190              
191             __END__
192              
193             =head1 NAME
194              
195             WebService::Blogger - (DEPRECATED) Interface to Google's Blogger service
196              
197             =cut
198              
199             =head1 SYNOPSIS
200              
201             B<DEPRECATION NOTICE.> This module no longer works and is deprecated. In fact,
202             as of this writing (2020-10-21), none of the CPAN modules for Blogger currently
203             work.
204              
205             This module provides interface to the Blogger service now run by
206             Google. It's built in object-oriented fashion with L<Moose>, which makes
207             it easy to use and extend. It also utilizes newer style GData API for
208             better compatibility. You can retrieve list of blogs for an account,
209             add, update or delete entries.
210              
211             use WebService::Blogger;
212              
213             my $blogger = WebService::Blogger->new(
214             login_id => 'myemail@gmail.com',
215             password => 'mypassword',
216             );
217              
218             my @blogs = $blogger->blogs;
219             foreach my $blog (@blogs) {
220             print join ', ', $blog->id, $blog->title, $blog->public_url, "\n";
221             }
222              
223             my $blog = $blogs[1];
224             my @entries = $blog->entries;
225              
226             my ($entry) = @entries;
227             print $entry->title, "\n", $entry->content;
228              
229             $entry->title('Updated Title');
230             $entry->content('Updated content');
231             $entry->categories([ qw/category1 category2/ ]);
232             $entry->save;
233              
234             my $new_entry = WebService::Blogger::Blog->add_entry(
235             title => 'New entry',
236             content => 'New content',
237             blog => $blog,
238             );
239             $new_entry->delete;
240              
241              
242             =head1 METHODS
243              
244             =head2 new
245              
246             my $blogger = WebService::Blogger->new(
247             login_id => 'myemail@gmail.com',
248             password => 'mypassword',
249             );
250              
251             Connects to Blogger, authenticates and returns object representing
252             Blogger account. The credentials can be given in named parameters or
253             read from a configuration file which has contents like this:
254              
255             username = someone@gmail.com
256             password = somepassword
257              
258             The file is first searched for as $ENV{WEBSERVICE_BLOGGER_CONFIG} then
259             as "$ENV{HOME}/.www_blogger_rc". On Windows, please use the first format.
260              
261             The file must not be accessible by anyone but the owner. Module will
262             die with an error if it is. Authentication token received will be
263             stored privately and used in all subsequent requests.
264              
265             =cut
266              
267             =head2 blogs
268              
269             Returns list of blogs for the account, as either array or array
270             reference, depending on the context. Items are instances of
271             L<WebService::Blogger::Blog>.
272              
273             =cut
274              
275             =head1 AUTHOR
276              
277             Kedar Warriner, C<< <kedar at cpan.org> >>
278              
279             =head1 BUGS
280              
281             Comments are currently not supported.
282              
283             Please report any bugs or feature requests to C<bug-webservice-blogger at rt.cpan.org>, or through
284             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=WebService-Blogger>. I will be notified, and then you'll
285             automatically be notified of progress on your bug as I make changes.
286              
287             =head1 SUPPORT
288              
289             You can find documentation for this module with the perldoc command.
290              
291             perldoc WebService::Blogger
292              
293             You can also look for information at:
294              
295             =over 4
296              
297             =item * RT: CPAN's request tracker
298              
299             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=WebService-Blogger>
300              
301             =item * AnnoCPAN: Annotated CPAN documentation
302              
303             L<http://annocpan.org/dist/WebService-Blogger>
304              
305             =item * CPAN Ratings
306              
307             L<http://cpanratings.perl.org/d/WebService-Blogger>
308              
309             =item * Search CPAN
310              
311             L<http://search.cpan.org/dist/WebService-Blogger/>
312              
313             =back
314              
315             =head1 ACKNOWLEDGEMENTS
316              
317             Many thanks to:
318             - Egor Shipovalov who wrote the original version of this module
319             - Everyone involved with CPAN.
320              
321             =head1 LICENSE AND COPYRIGHT
322              
323             Copyright 2010 Kedar Warriner.
324              
325             This program is free software; you can redistribute it and/or modify it
326             under the terms of either: the GNU General Public License as published
327             by the Free Software Foundation; or the Artistic License.
328              
329             See http://dev.perl.org/licenses/ for more information.
330              
331             =cut