File Coverage

blib/lib/POE/Component/SmokeBox/Uploads/NNTP.pm
Criterion Covered Total %
statement 73 88 82.9
branch 11 22 50.0
condition 2 5 40.0
subroutine 15 19 78.9
pod 3 3 100.0
total 104 137 75.9


line stmt bran cond sub pod time code
1             package POE::Component::SmokeBox::Uploads::NNTP;
2             $POE::Component::SmokeBox::Uploads::NNTP::VERSION = '1.02';
3             #ABSTRACT: Obtain uploaded CPAN modules via NNTP.
4              
5 1     1   86503 use strict;
  1         1  
  1         24  
6 1     1   4 use warnings;
  1         1  
  1         24  
7 1     1   3 use Carp;
  1         1  
  1         45  
8 1     1   4 use POE qw(Component::Client::NNTP);
  1         1  
  1         10  
9 1     1   21162 use Email::Simple;
  1         3543  
  1         752  
10              
11             sub spawn {
12 1     1 1 1977 my $package = shift;
13 1         4 my %opts = @_;
14 1         10 $opts{lc $_} = delete $opts{$_} for keys %opts;
15 1 50       4 croak "$package requires an 'event' argument\n" unless $opts{event};
16 1 50       3 $opts{nntp} = 'nntp.perl.org' unless $opts{nntp};
17 1 50       6 $opts{group} = 'perl.cpan.uploads' unless $opts{group};
18 1         3 my $options = delete $opts{options};
19 1         2 my $self = bless \%opts, $package;
20 1 50       22 $self->{session_id} = POE::Session->create(
21             object_states => [
22             $self => { shutdown => '_shutdown',
23             connect => '_connect',
24             poll => '_poll',
25             nntp_registered => '_nntp_registered',
26             nntp_socketerr => '_nntp_socketerr',
27             nntp_disconnected => '_nntp_disconnected',
28             nntp_200 => '_nntp_200',
29             nntp_211 => '_nntp_211',
30             nntp_220 => '_nntp_220',
31             },
32             $self => [ qw(_start _dispatch) ],
33             ],
34             heap => $self,
35             ( ref($options) eq 'HASH' ? ( options => $options ) : () ),
36             )->ID();
37 1         65 return $self;
38             }
39              
40             sub session_id {
41 0     0 1 0 return $_[0]->{session_id};
42             }
43              
44             sub shutdown {
45 0     0 1 0 my $self = shift;
46 0         0 $poe_kernel->post( $self->{session_id}, 'shutdown' );
47 0         0 return;
48             }
49              
50             sub _shutdown {
51 1     1   780 my ($kernel,$self) = @_[KERNEL,OBJECT];
52 1         27 $kernel->alias_remove( $_ ) for $kernel->alias_list();
53 1 50       35 $kernel->refcount_decrement( $self->{session_id}, __PACKAGE__ ) unless $self->{alias};
54 1         22 $kernel->refcount_decrement( $self->{sender_id}, __PACKAGE__ );
55 1         25 $kernel->post( $self->{nntpclient}->session_id(), 'shutdown' );
56 1         57 return;
57             }
58              
59             sub _start {
60 1     1   169 my ($kernel,$session,$sender,$self) = @_[KERNEL,SESSION,SENDER,OBJECT];
61 1         3 $self->{session_id} = $session->ID();
62 1 50 33     7 if ( $kernel == $sender and !$self->{session} ) {
63 0         0 croak "Not called from another POE session and 'session' wasn't set\n";
64             }
65 1         1 my $sender_id;
66 1 50       3 if ( $self->{session} ) {
67 0 0       0 if ( my $ref = $kernel->alias_resolve( $self->{session} ) ) {
68 0         0 $sender_id = $ref->ID();
69             }
70             else {
71 0         0 croak "Could not resolve 'session' to a valid POE session\n";
72             }
73             }
74             else {
75 1         2 $sender_id = $sender->ID();
76             }
77 1         7 $kernel->refcount_increment( $sender_id, __PACKAGE__ );
78 1         17 $self->{sender_id} = $sender_id;
79             $self->{nntpclient} = POE::Component::Client::NNTP->spawn( 'nntp' . $self->{session_id},
80 1         12 { NNTPServer => $self->{nntp}, Port => $self->{nntp_port} } );
81 1         591 return;
82             }
83              
84             sub _nntp_registered {
85 1     1   141 my ($kernel,$self,$sender) = @_[KERNEL,OBJECT,SENDER];
86 1         3 $kernel->yield( 'connect', $sender->ID() );
87 1         36 return;
88             }
89              
90             sub _connect {
91 1     1   133 my ($kernel,$self,$sender) = @_[KERNEL,OBJECT,ARG0];
92 1         3 $kernel->post( $sender, 'connect' );
93 1         51 return;
94             }
95              
96             sub _nntp_socketerr {
97 0     0   0 my ($kernel,$self,$sender,$error) = @_[KERNEL,OBJECT,SENDER,ARG0];
98 0         0 warn "Socket error: $error\n";
99 0         0 $kernel->delay( 'connect', 60, $sender->ID() );
100 0         0 return;
101             }
102              
103             sub _nntp_disconnected {
104 0     0   0 my ($kernel,$self,$sender) = @_[KERNEL,OBJECT,SENDER];
105 0         0 $kernel->delay( 'connect', 60, $sender->ID() );
106 0         0 return;
107             }
108              
109             sub _poll {
110 3     3   19978425 my ($kernel,$self) = @_[KERNEL,OBJECT];
111 3         21 $kernel->post ( $self->{nntpclient}->session_id(), 'group', $self->{group} );
112 3         237 undef;
113             }
114              
115             sub _nntp_200 {
116 1     1   3377 my ($kernel,$self) = @_[KERNEL,OBJECT];
117 1         4 $kernel->yield( 'poll' );
118 1         35 undef;
119             }
120              
121             sub _nntp_211 {
122 2     2   4022 my ($kernel,$self,$sender) = @_[KERNEL,OBJECT,SENDER];
123 2         12 my ($estimate,$first,$last,$group) = split( /\s+/, $_[ARG0] );
124              
125 2 100       8 if ( defined $self->{articles}->{ $group } ) {
126             # Check for new articles
127 1 50       5 if ( $estimate >= $self->{articles}->{ $group } ) {
128 1         4 for my $article ( $self->{articles}->{ $group } .. $estimate ) {
129 1         4 $kernel->post ( $sender => article => $article );
130             }
131 1         75 $self->{articles}->{ $group } = $estimate + 1;
132             }
133             }
134             else {
135 1         4 $self->{articles}->{ $group } = $estimate + 1;
136             }
137 2   50     9 $kernel->delay( 'poll' => ( $self->{poll} || 60 ) );
138 2         120 undef;
139             }
140              
141             sub _nntp_220 {
142 1     1   40359 my ($kernel,$self,$text) = @_[KERNEL,OBJECT,ARG0];
143 1         2 my $article = Email::Simple->new( join "\n", @{ $_[ARG1] } );
  1         14  
144 1         382 my $subject = $article->header('Subject');
145 1 50       66 if ( my ($upload) = $subject =~ m!^CPAN Upload:\s+(\w+/\w+/\w+/.+(\.tar\.(gz|bz2)|\.tgz|\.zip))$!i ) {
146 1         9 $kernel->call( $self->{session_id}, '_dispatch', $upload );
147             }
148 1         20 return;
149             }
150              
151             sub _dispatch {
152 1     1   30 my ($kernel,$self,$module) = @_[KERNEL,OBJECT,ARG0];
153 1         3 $kernel->post( $self->{sender_id}, $self->{event}, $module );
154 1         57 return;
155             }
156              
157             1;
158              
159             __END__