File Coverage

blib/lib/POE/Component/Client/Pastebot.pm
Criterion Covered Total %
statement 104 126 82.5
branch 25 44 56.8
condition 12 24 50.0
subroutine 15 17 88.2
pod 3 3 100.0
total 159 214 74.3


line stmt bran cond sub pod time code
1             package POE::Component::Client::Pastebot;
2             $POE::Component::Client::Pastebot::VERSION = '1.18';
3             #ABSTRACT: Interact with Bot::Pastebot web services from POE.
4              
5 2     2   1317 use strict;
  2         3  
  2         51  
6 2     2   8 use warnings;
  2         2  
  2         61  
7 2     2   7 use POE qw(Component::Client::HTTP);
  2         2  
  2         15  
8 2     2   125952 use HTTP::Request::Common;
  2         4259  
  2         110  
9 2     2   10 use URI;
  2         3  
  2         31  
10 2     2   808 use HTML::TokeParser;
  2         14672  
  2         2014  
11              
12             # Stolen from POE::Wheel. This is static data, shared by all
13             my $current_id = 0;
14             my %active_identifiers;
15              
16             sub _allocate_identifier {
17 2     2   3 while (1) {
18 2 50       5 last unless exists $active_identifiers{ ++$current_id };
19             }
20 2         4 return $active_identifiers{$current_id} = $current_id;
21             }
22              
23             sub _free_identifier {
24 2     2   3 my $id = shift;
25 2         2 delete $active_identifiers{$id};
26             }
27              
28             sub spawn {
29 2     2 1 2909 my $package = shift;
30 2         4 my %opts = @_;
31 2         8 $opts{lc $_} = delete $opts{$_} for keys %opts;
32 2         4 my $options = delete $opts{options};
33 2         3 my $self = bless \%opts, $package;
34 2 100       21 $self->{session_id} = POE::Session->create(
35             object_states => [
36             $self => { shutdown => '_shutdown',
37             paste => '_command',
38             fetch => '_command',
39             },
40             $self => [ qw(_start _dispatch _http_request _http_response) ],
41             ],
42             heap => $self,
43             ( ref($options) eq 'HASH' ? ( options => $options ) : () ),
44             )->ID();
45 2         719 return $self;
46             }
47              
48             sub session_id {
49 0     0 1 0 return $_[0]->{session_id};
50             }
51              
52             sub shutdown {
53 0     0 1 0 my $self = shift;
54 0         0 $poe_kernel->post( $self->{session_id}, 'shutdown' );
55             }
56              
57             sub _start {
58 2     2   395 my ($kernel,$self) = @_[KERNEL,OBJECT];
59 2         4 $self->{session_id} = $_[SESSION]->ID();
60 2 50       13 if ( $self->{alias} ) {
61 0         0 $kernel->alias_set( $self->{alias} );
62             }
63             else {
64 2         6 $kernel->refcount_increment( $self->{session_id} => __PACKAGE__ );
65             }
66 2         43 $self->{_httpc} = 'httpc-' . $self->{session_id};
67             POE::Component::Client::HTTP->spawn(
68             Alias => $self->{_httpc},
69 2         14 FollowRedirects => 2,
70             );
71 2         2027 undef;
72             }
73              
74             sub _shutdown {
75 2     2   1761 my ($kernel,$self) = @_[KERNEL,OBJECT];
76 2         5 $kernel->alias_remove( $_ ) for $kernel->alias_list();
77 2 50       44 $kernel->refcount_decrement( $self->{session_id} => __PACKAGE__ ) unless $self->{alias};
78 2         47 $self->{_shutdown} = 1;
79 2         4 $kernel->post( $self->{_httpc}, 'shutdown' );
80 2         125 undef;
81             }
82              
83             sub _dispatch {
84 2     2   875 my ($kernel,$self,$input) = @_[KERNEL,OBJECT,ARG0];
85 2         4 my $session = delete $input->{sender};
86 2         3 my $event = delete $input->{event};
87 2         3 $kernel->post( $session, $event, $input );
88 2         121 $kernel->refcount_decrement( $session => __PACKAGE__ );
89 2         79 undef;
90             }
91              
92             sub _command {
93 2     2   1093 my ($kernel,$self,$state) = @_[KERNEL,OBJECT,STATE];
94 2         3 my $sender = $_[SENDER]->ID();
95 2 50       9 return if $self->{_shutdown};
96 2         1 my $args;
97 2 50       4 if ( ref( $_[ARG0] ) eq 'HASH' ) {
98 2         2 $args = { %{ $_[ARG0] } };
  2         6  
99             } else {
100 0         0 $args = { @_[ARG0..$#_] };
101             }
102              
103 2         3 $args->{lc $_} = delete $args->{$_} for grep { $_ !~ /^_/ } keys %{ $args };
  5         14  
  2         2  
104              
105 2 50       5 unless ( $args->{event} ) {
106 0         0 warn "No 'event' specified for $state";
107 0         0 return;
108             }
109              
110 2 50       4 unless ( $args->{url} ) {
111 0         0 warn "No 'url' specified for $state";
112 0         0 return;
113             }
114              
115 2 50 66     9 if ( $state eq 'paste' and !$args->{paste} ) {
116 0         0 warn "No 'paste' specified for paste";
117 0         0 return;
118             }
119              
120 2 50 66     5 if ( $state eq 'paste' and ref ( $args->{paste} ) eq 'ARRAY' ) {
121 0         0 my $paste = delete $args->{paste};
122 0         0 $args->{paste} = join "\n", @{ $paste };
  0         0  
123             }
124              
125 2         4 $args->{sender} = $sender;
126 2         2 $args->{command} = $state;
127 2         4 $kernel->refcount_increment( $sender => __PACKAGE__ );
128 2         32 $kernel->yield( '_http_request', $args );
129 2         73 undef;
130             }
131              
132             sub _http_request {
133 2     2   155 my ($kernel,$self,$req) = @_[KERNEL,OBJECT,ARG0];
134 2 100       6 if ( $req->{command} eq 'paste' ) {
135             my $url =
136             URI->new(
137 1 50       11 $req->{'url'} . ( ( $req->{'url'} !~ m,/$, ) ? '/' : '' ) . 'paste' )
138             ->canonical;
139 1 50       5880 unless ( defined $url ) {
140 0         0 $req->{error} = "could not determine url from $req->{url}";
141 0         0 $kernel->yield( '_dispatch', $req );
142             }
143             else {
144 1 50 33     4 $req->{'channel'} =~ s/^/#/ if $req->{'channel'} and $req->{'channel'} !~ /^#/;
145             my %postargs = map {
146 1         2 ( defined $req->{$_} and $req->{$_} ne '' )
147 3 50 33     8 ? ( $_ => $req->{$_} )
148             : ()
149             } qw(channel nick summary);
150 1         1 $postargs{'paste'} = $req->{paste};
151 1         2 my $id = _allocate_identifier();
152 1         2 $self->{_requests}->{ $id } = $req;
153             $kernel->post(
154             $self->{_httpc},
155 1         3 'request',
156             '_http_response',
157             POST( $url, \%postargs ),
158             "$id",
159             );
160             }
161 1         417 return;
162             }
163 1 50       2 if ( $req->{command} eq 'fetch' ) {
164 1         2 my $url;
165 1 50       5 my $urltmp = URI->new( $req->{url} . ( ( $req->{url} !~ m,\?tx=on$, ) ? '?tx=on' : '' ) );
166 1 50 33     49 if ( defined $urltmp and defined $urltmp->scheme and $urltmp->scheme =~ /http/ ) {
      33        
167 1         23 $url = $urltmp->canonical;
168 1         54 my $id = _allocate_identifier();
169 1         2 $self->{_requests}->{ $id } = $req;
170             $kernel->post(
171             $self->{_httpc},
172 1         2 'request',
173             '_http_response',
174             GET( $url ),
175             "$id",
176             );
177             }
178             else {
179 0         0 $req->{error} = 'problem with url provided';
180 0         0 $kernel->yield( '_dispatch', $req );
181             }
182 1         105 return;
183             }
184 0         0 return;
185             }
186              
187             sub _http_response {
188 2     2   12883 my ($kernel,$self,$request_packet,$response_packet) = @_[KERNEL,OBJECT,ARG0,ARG1];
189 2         3 my $id = $request_packet->[1];
190 2         2 my $req = delete $self->{_requests}->{ $id };
191 2         4 _free_identifier( $id );
192 2         2 my $response = $response_packet->[0];
193 2         3 $req->{response} = $response;
194 2 50       6 unless ( $response->is_success ) {
195 0 0       0 if ( $response->is_error ) {
196 0         0 $req->{error} = $response->as_string;
197             }
198             else {
199 0         0 $req->{error} = 'unknown error';
200             }
201             }
202             else {
203 2 100 66     20 if ( $req->{command} eq 'paste' and $response->content ) {
204 1         11 my $p = HTML::TokeParser->new( \$response->content );
205 1         210 $p->get_tag('a');
206 1         220 $req->{pastelink} = $p->get_text('/a');
207             }
208 2 100 66     53 if ( $req->{command} eq 'fetch' and $response->content ) {
209 1         10 $req->{content} = $response->content;
210             }
211             }
212 2         9 $kernel->yield( '_dispatch', $req );
213 2         97 return;
214             }
215              
216             'Paste and cut';
217              
218             __END__