File Coverage

blib/lib/WWW/ImagebinCa/Create.pm
Criterion Covered Total %
statement 25 80 31.2
branch 1 34 2.9
condition 2 26 7.6
subroutine 7 14 50.0
pod 6 6 100.0
total 41 160 25.6


line stmt bran cond sub pod time code
1             package WWW::ImagebinCa::Create;
2              
3 1     1   116275 use warnings;
  1         2  
  1         31  
4 1     1   5 use strict;
  1         1  
  1         43  
5              
6             our $VERSION = '0.02';
7              
8 1     1   5 use Carp;
  1         5  
  1         74  
9 1     1   4 use HTTP::Request::Common;
  1         1  
  1         50  
10 1     1   5 use LWP::UserAgent;
  1         1  
  1         23  
11 1     1   5 use HTML::TokeParser::Simple;
  1         1  
  1         963  
12              
13             sub new {
14 1     1 1 306 my $class = shift;
15 1 50       5 croak "Must have even number of arguments to new()"
16             if @_ & 1;
17 1         3 my %args = @_;
18 1         5 $args{ +lc } = delete $args{ $_ } for keys %args;
19              
20 1   50     7 $args{timeout} ||= 30;
21              
22 1   33     14 $args{ua} ||= LWP::UserAgent->new(
23             timeout => $args{timeout},
24             agent => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US;'
25             . ' rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy)'
26             . ' Firefox/2.0.0.12',
27             );
28              
29 1         3193 return bless \%args, $class;
30             }
31              
32             sub upload {
33 0     0 1   my $self = shift;
34 0 0         croak "Must have even number of arguments to upload()"
35             if @_ & 1;
36 0           my %args = @_;
37 0           $args{ +lc } = delete $args{ $_ } for keys %args;
38              
39 0 0         unless ( -e $args{filename} ) {
40 0           $self->error("File ($args{filename}) doesn't exist");
41 0           return;
42             }
43              
44 0           my @post_request = $self->_make_request_args( \%args );
45 0           my $response = $self->{ua}->request( POST @post_request );
46              
47 0 0         if ( $response->is_success ) {
48 0           return $self->_check_content( $response->content, \%args );
49             }
50             else {
51 0           $self->error('Error: ' . $response->status_line );
52 0           return;
53             }
54             }
55              
56             sub _check_content {
57 0     0     my ( $self, $content, $args_ref ) = @_;
58              
59 0           my $parser = HTML::TokeParser::Simple->new( \$content );
60 0           my $paste_uri;
61             my $error;
62 0           my $get_paste_uri = 0;
63 0           my $is_error = 0;
64 0           while ( my $token = $parser->get_token ) {
65 0 0 0       if ( $token->is_start_tag('p') ) {
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
66 0           $get_paste_uri = 1;
67             }
68             elsif ( $get_paste_uri and $token->is_start_tag('a') ) {
69 0           $paste_uri = $token->get_attr('href');
70             }
71             elsif ( $token->is_start_tag('div')
72             and defined $token->get_attr('id')
73             and $token->get_attr('id') eq 'body'
74             ) {
75 0           $is_error = 1;
76             }
77             elsif ( $is_error == 1 and $token->is_start_tag('h2') ) {
78 0           $is_error = 2;
79             }
80             elsif ( $is_error == 2 and $token->is_text ) {
81 0           $error = $token->as_is;
82 0           $is_error = 3;
83             }
84             # this would better be as ->is_start_tag('p') but the parser
85             # ...doesn't seem to catch it this way. Bug? Too invalid markup?
86             elsif ( $is_error == 3 and $token->is_end_tag('h2') ) {
87 0           $is_error = 4;
88             }
89             elsif ( $is_error == 4 and $token->is_text ) {
90 0           $error .= '. ' . $token->as_is;
91 0           last;
92             }
93             }
94              
95 0 0         if ( $is_error ) {
96 0           $self->error( $error );
97 0           return;
98             }
99             else {
100 0           my ( $upload_id ) = $paste_uri =~ m{([^/]+)[.]html$};
101 0           $self->upload_id( $upload_id );
102 0           my ( $image_extension ) = $args_ref->{filename} =~ /[.]([^.]+)$/;
103 0           $self->image_uri(
104             "http://imagebin.ca/img/$upload_id.$image_extension"
105             );
106 0           return $self->page_uri( $paste_uri );
107             }
108             }
109              
110             sub _make_request_args {
111 0     0     my ( $self, $args ) = @_;
112             return (
113 0 0         'http://imagebin.ca/upload.php',
114             Content_Type => 'form-data',
115             Content => [
116             sfile => 'Upload',
117             f => [ $args->{filename} ],
118             t => 'file',
119             name => $args->{name},
120             tags => $args->{tags},
121             description => $args->{description},
122             adult => $args->{is_adult} ? 't' : 'f',
123             ],
124             );
125             }
126              
127             sub error {
128 0     0 1   my $self = shift;
129 0 0         if ( @_ ) {
130 0           $self->{ ERROR } = shift;
131             }
132 0           return $self->{ ERROR };
133             }
134              
135              
136             sub page_uri {
137 0     0 1   my $self = shift;
138 0 0         if ( @_ ) {
139 0           $self->{ PAGE_URI } = shift;
140             }
141 0           return $self->{ PAGE_URI };
142             }
143              
144             sub image_uri {
145 0     0 1   my $self = shift;
146 0 0         if ( @_ ) {
147 0           $self->{ IMAGE_URI } = shift;
148             }
149 0           return $self->{ IMAGE_URI };
150             }
151              
152             sub upload_id {
153 0     0 1   my $self = shift;
154 0 0         if ( @_ ) {
155 0           $self->{ UPLOAD_ID } = shift;
156             }
157 0           return $self->{ UPLOAD_ID };
158             }
159              
160             =head1 NAME
161              
162             WWW::ImagebinCa::Create - "paste" images to from Perl.
163              
164             =head1 SYNOPSIS
165              
166             use strict;
167             use warnings;
168              
169             use WWW::ImagebinCa::Create;
170              
171             my $bin = WWW::ImagebinCa::Create->new;
172              
173             $bin->upload( filename => 'pic.jpg' )
174             or die "Failed to upload: " . $bin->error;
175              
176             printf "Upload ID: %s\nPage URI: %s\nDirect image URI: %s\n",
177             $bin->upload_id,
178             $bin->page_uri,
179             $bin->image_uri;
180              
181             =head1 DESCRIPTION
182              
183             The module provides interface to L for uploading
184             new images and including uploader's name, picture description and picture
185             "tags" along with your upload.
186              
187             =head1 CONSTRUCTOR
188              
189             =head2 new
190              
191             my $bin = WWW::ImagebinCa::Create->new;
192              
193             my $bin = WWW::ImagebinCa::Create->new(
194             timeout => 10,
195             );
196              
197             my $bin = WWW::ImagebinCa::Create->new(
198             ua => LWP::UserAgent->new(
199             timeout => 10,
200             agent => 'PasterUA',
201             ),
202             );
203              
204             Constructs and returns a brand new WWW::ImagebinCa::Create
205             object. Takes two arguments, both are I. Possible arguments are
206             as follows:
207              
208             =head3 timeout
209              
210             ->new( timeout => 10 );
211              
212             B. Specifies the C argument of L's
213             constructor, which is used for uploading. B C<30> seconds.
214              
215             =head3 ua
216              
217             ->new( ua => LWP::UserAgent->new( agent => 'Foos!' ) );
218              
219             B. If the C argument is not enough for your needs
220             of mutilating the L object used for uploading, feel free
221             to specify the C argument which takes an L object
222             as a value. B the C argument to the constructor will
223             not do anything if you specify the C argument as well. B
224             plain boring default L object with C argument
225             set to whatever C's C argument is
226             set to as well as C argument is set to mimic Firefox.
227              
228             =head1 METHODS
229              
230             =head2 upload
231              
232             $bin->upload( filename => 'some_pic.jpg' )
233             or die "Upload error: " . $bin->error;
234              
235             my $page_uri = $bin->upload(
236             filename => 'another_pic.bmp',
237             name => 'Pic name',
238             tags => 'Space separated "tags" for the image',
239             description => 'Description of the image',
240             is_adult => 1, # is adult content?
241             ) or die "Upload error: " . $bin->error;
242              
243             Instructs the object to upload a certain image. Takes several arguments,
244             only one of them (C) is mandatory. If the upload
245             was successful returns a URI to the
246             L page with the image but you don't have
247             to store it (see C method below). If upload failed
248             returns either C or an empty list depending on the context
249             and the reason for the error will be available via C method
250             (see below). Possible arguments are as follows:
251              
252             =head3 filename
253              
254             $bin->upload( filename => 'pic.jpg' );
255              
256             B. Takes a scalar representing the filename of the image to
257             upload.
258              
259             =head3 name
260              
261             $bin->upload( filename => 'pic.jpg', name => 'Kitty meow!' );
262              
263             B. Specifies the name of the image you are uploading.
264             B C (no name).
265              
266             =head3 tags
267              
268             $bin->upload( filename => 'pic.jpg', tags => 'space separated tags');
269              
270             B. Specifies "tags" for the image you are uploading. Multiple
271             tags are separated by space character. B C
272             (no tags).
273              
274             =head3 description
275              
276             $bin->upload( filename => 'pic.jpg', description => 'My kitty!' );
277              
278             B. Specifies the description of the image you are uploading.
279             B C (no description).
280              
281             =head3 is_adult
282              
283             $bin->upload( filename => 'pr0n.jpg', is_adult => 1 );
284              
285             B. Specifies whether or not to flag the image as containing
286             adult content. When set to a I will mark the image as suitable
287             only for adult humans. When set to a I will mark the image
288             as suitable for everyone. B C<0> (suitable for everyone).
289              
290             =head2 error
291              
292             $bin->upload( filename => 'some_pic.jpg' )
293             or die "Upload error: " . $bin->error;
294              
295             If an error occured during the call to C method (see above)
296             it will return either C or an empty list depending on the context.
297             When that happens you will be able to get the reason for the error
298             via C method. Takes no arguments, returns human readable error
299             message.
300              
301             =head2 page_uri
302              
303             print "Yey! You can see your pic on: " . $bin->page_uri;
304              
305             Must be called after a successful call to C. Takes no arguments,
306             returns the URI to the page containing the uploaded image.
307              
308             =head2 image_uri
309              
310             printf qq|
meow
\n|,
311             $bin->image_uri;
312              
313             Must be called after a successful call to C. Takes no arguments,
314             returns a direct URI to the image you have uploaded. Note that this
315             is not the same as C (see above). The C method
316             returns URI to the I containing the image and all the optional
317             information you have provided whereas C method returns the
318             URI to the image itself. For example, you may wish to use this on
319             on some temporary web page.
320              
321             =head2 upload_id
322              
323             print "Your upload ID is: " . $bin->upload_id;
324              
325             Must be called after a successful call to C. Takes
326             no arguments, returns the ID
327             of the image you have uploaded. In other words, if C method
328             (see above) returns C the
329             C method will return C.
330              
331             =head1 AUTHOR
332              
333             Zoffix Znet, C<< >>
334             (L, L)
335              
336             =head1 BUGS AND CAVEATS
337              
338             The module relies on HTML parsing, thus it's possible for it to break
339             one day if the author of the site decides to recode it.
340              
341             According to the bug in
342             L
343             ( L ) it breaks
344             if the filename contains C<"> (double quotes). Avoid those in the images
345             you upload until the bug is resolved.
346              
347             Please report any bugs or feature requests to C, or through
348             the web interface at L. I will be notified, and then you'll
349             automatically be notified of progress on your bug as I make changes.
350              
351             =head1 SUPPORT
352              
353             You can find documentation for this module with the perldoc command.
354              
355             perldoc WWW::ImagebinCa::Create
356              
357             You can also look for information at:
358              
359             =over 4
360              
361             =item * RT: CPAN's request tracker
362              
363             L
364              
365             =item * AnnoCPAN: Annotated CPAN documentation
366              
367             L
368              
369             =item * CPAN Ratings
370              
371             L
372              
373             =item * Search CPAN
374              
375             L
376              
377             =back
378              
379             =head1 COPYRIGHT & LICENSE
380              
381             Copyright 2008 Zoffix Znet, all rights reserved.
382              
383             This program is free software; you can redistribute it and/or modify it
384             under the same terms as Perl itself.
385              
386             =cut
387