File Coverage

blib/lib/POE/Component/IRC/Plugin/RSS/Headlines.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package POE::Component::IRC::Plugin::RSS::Headlines;
2             $POE::Component::IRC::Plugin::RSS::Headlines::VERSION = '1.10';
3             #ABSTRACT: A POE::Component::IRC plugin that provides RSS headline retrieval.
4              
5 1     1   225686 use strict;
  1         2  
  1         24  
6 1     1   3 use warnings;
  1         3  
  1         25  
7 1     1   3 use POE;
  1         1  
  1         5  
8 1     1   819 use POE::Component::Client::HTTP;
  1         61271  
  1         29  
9 1     1   6 use POE::Component::IRC::Plugin qw(:ALL);
  1         2  
  1         119  
10 1     1   621 use XML::RSS;
  0            
  0            
11             use HTTP::Request;
12              
13             sub new {
14             my $package = shift;
15             my %args = @_;
16             $args{lc $_} = delete $args{$_} for keys %args;
17             return bless \%args, $package;
18             }
19              
20             sub PCI_register {
21             my ($self,$irc) = @_;
22             $self->{irc} = $irc;
23             $irc->plugin_register( $self, 'SERVER', qw(spoof) );
24             unless ( $self->{http_alias} ) {
25             $self->{http_alias} = join('-', 'ua-rss-headlines', $irc->session_id() );
26             $self->{follow_redirects} ||= 2;
27             POE::Component::Client::HTTP->spawn(
28             Alias => $self->{http_alias},
29             Timeout => 30,
30             FollowRedirects => $self->{follow_redirects},
31             );
32             }
33             $self->{session_id} = POE::Session->create(
34             object_states => [
35             $self => [ qw(_shutdown _start _get_headline _response) ],
36             ],
37             )->ID();
38             $poe_kernel->state( 'get_headline', $self );
39             return 1;
40             }
41              
42             sub PCI_unregister {
43             my ($self,$irc) = splice @_, 0, 2;
44             $poe_kernel->state( 'get_headline' );
45             $poe_kernel->call( $self->{session_id} => '_shutdown' );
46             delete $self->{irc};
47             return 1;
48             }
49              
50             sub _start {
51             my ($kernel,$self) = @_[KERNEL,OBJECT];
52             $self->{session_id} = $_[SESSION]->ID();
53             $kernel->refcount_increment( $self->{session_id}, __PACKAGE__ );
54             undef;
55             }
56              
57             sub _shutdown {
58             my ($kernel,$self) = @_[KERNEL,OBJECT];
59             $kernel->alarm_remove_all();
60             $kernel->refcount_decrement( $self->{session_id}, __PACKAGE__ );
61             $kernel->call( $self->{http_alias} => 'shutdown' );
62             undef;
63             }
64              
65             sub get_headline {
66             my ($kernel,$self,$session) = @_[KERNEL,OBJECT,SESSION];
67             $kernel->post( $self->{session_id}, '_get_headline', @_[ARG0..$#_] );
68             undef;
69             }
70              
71             sub _get_headline {
72             my ($kernel,$self) = @_[KERNEL,OBJECT];
73             my %args;
74             if ( ref $_[ARG0] eq 'HASH' ) {
75             %args = %{ $_[ARG0] };
76             } else {
77             %args = @_[ARG0..$#_];
78             }
79             $args{lc $_} = delete $args{$_} for grep { !/^_/ } keys %args;
80             return unless $args{url};
81             $args{irc_session} = $self->{irc}->session_id();
82             $kernel->post( $self->{http_alias}, 'request', '_response', HTTP::Request->new( GET => $args{url} ), \%args );
83             undef;
84             }
85              
86             sub _response {
87             my ($kernel,$self,$request,$response) = @_[KERNEL,OBJECT,ARG0,ARG1];
88             my $args = $request->[1];
89             my @params;
90             push @params, delete $args->{irc_session}, '__send_event';
91             my $result = $response->[0];
92             if ( $result->is_success ) {
93             my $str = $result->content;
94             my $rss = XML::RSS->new();
95             eval { $rss->parse($str); };
96             if ($@) {
97             push @params, 'irc_rssheadlines_error', $args, $@;
98             } else {
99             push @params, 'irc_rssheadlines_items', $args;
100             push @params, $_->{'title'} for @{ $rss->{'items'} };
101             }
102             } else {
103             push @params, 'irc_rssheadlines_error', $args, $result->status_line;
104             }
105             $kernel->post( @params );
106             undef;
107             }
108              
109             qq[Read all about it!];
110              
111             __END__
112              
113             =pod
114              
115             =encoding UTF-8
116              
117             =head1 NAME
118              
119             POE::Component::IRC::Plugin::RSS::Headlines - A POE::Component::IRC plugin that provides RSS headline retrieval.
120              
121             =head1 VERSION
122              
123             version 1.10
124              
125             =head1 SYNOPSIS
126              
127             use strict;
128             use warnings;
129             use POE qw(Component::IRC Component::IRC::Plugin::RSS::Headlines);
130              
131             my $nickname = 'RSSHead' . $$;
132             my $ircname = 'RSSHead the Sailor Bot';
133             my $ircserver = 'irc.perl.org';
134             my $port = 6667;
135             my $channel = '#IRC.pm';
136             my $rss_url = 'http://eekeek.org/jerkcity.cgi';
137              
138             my $irc = POE::Component::IRC->spawn(
139             nick => $nickname,
140             server => $ircserver,
141             port => $port,
142             ircname => $ircname,
143             debug => 0,
144             plugin_debug => 1,
145             options => { trace => 0 },
146             ) or die "Oh noooo! $!";
147              
148             POE::Session->create(
149             package_states => [
150             'main' => [ qw(_start irc_001 irc_join irc_rssheadlines_items) ],
151             ],
152             );
153              
154             $poe_kernel->run();
155             exit 0;
156              
157             sub _start {
158             # Create and load our plugin
159             $irc->plugin_add( 'RSSHead' =>
160             POE::Component::IRC::Plugin::RSS::Headlines->new() );
161              
162             $irc->yield( register => 'all' );
163             $irc->yield( connect => { } );
164             undef;
165             }
166              
167             sub irc_001 {
168             $irc->yield( join => $channel );
169             undef;
170             }
171              
172             sub irc_join {
173             my ($kernel,$sender,$channel) = @_[KERNEL,SENDER,ARG1];
174             print STDERR "$channel $rss_url\n";
175             $kernel->yield( 'get_headline', { url => $rss_url, _channel => $channel } );
176             undef;
177             }
178              
179             sub irc_rssheadlines_items {
180             my ($kernel,$sender,$args) = @_[KERNEL,SENDER,ARG0];
181             my $channel = delete $args->{_channel};
182             $kernel->post( $sender, 'privmsg', $channel, join(' ', @_[ARG1..$#_] ) );
183             undef;
184             }
185              
186             =head1 DESCRIPTION
187              
188             POE::Component::IRC::Plugin::RSS::Headlines, is a L<POE::Component::IRC> plugin that provides
189             a mechanism for retrieving RSS headlines from given URLs.
190              
191             =for Pod::Coverage PCI_register PCI_unregister
192              
193             =head1 CONSTRUCTOR
194              
195             =over
196              
197             =item C<new>
198              
199             Creates a new plugin object. Takes the following optional arguments:
200              
201             'http_alias', you may provide the alias of an existing POE::Component::Client::HTTP
202             component that the plugin will use instead of spawning it's own;
203             'follow_redirects', this argument is passed to PoCoCl::HTTP to inform it how to deal with
204             following redirects, default is 2;
205              
206             =back
207              
208             =head1 INPUT EVENTS
209              
210             The plugin registers the following state handler within your session:
211              
212             =over
213              
214             =item C<get_headline>
215              
216             Takes a hashref as an argument with the following keys:
217              
218             'url', the RSS based url to retrieve items for;
219              
220             You may pass arbitary key/value pairs, but the keys must be prefixed with an underscore.
221              
222             =back
223              
224             =head1 OUTPUT
225              
226             The following irc event is generated with the result of a 'get_headline' command:
227              
228             =over
229              
230             =item C<irc_rssheadlines_items>
231              
232             Has the following parameters:
233              
234             'ARG0', the original hashref that was passed;
235             'ARG1' .. $#_, RSS headline item titles;
236              
237             =item C<irc_rssheadlines_error>
238              
239             Has the following parameters:
240              
241             'ARG0', the original hashref that was passed;
242             'ARG1', the error text;
243              
244             =back
245              
246             =head1 SEE ALSO
247              
248             L<POE::Component::IRC>
249              
250             =head1 AUTHOR
251              
252             Chris Williams
253              
254             =head1 COPYRIGHT AND LICENSE
255              
256             This software is copyright (c) 2017 by Chris Williams.
257              
258             This is free software; you can redistribute it and/or modify it under
259             the same terms as the Perl 5 programming language system itself.
260              
261             =cut