package RSSReader::Fetcher; use strict; use RSSReader; use RSSReader::Feed; use RSSReader::Configuration; use RSSReader::Feed::Message; use RSSReader::Parser; use Data::Dumper; use base qw(RSSReader::Logger); use Date::Manip; use XML::RSS; sub fetch_feed { my $c = shift; my $feed = shift; my ($ret_code, $rss_data) = $c->get_rss($feed->url, modified_since=>$feed->last_fetched); if (! $ret_code ) { $c->log_warn("Could not fetch the feed ".$feed->label()); $feed->fetch_failed("Could not fetch the feed"); return undef; } if ( $c->add_rss_results_to_feed($feed, $rss_data) ) { $feed->fetch_success(); return 1; } $feed->fetch_failed("Invalid XML RSS"); return undef; } sub get_rss { #returns asuccess,success, n array: #(success, return code, content) my $c = shift; my $url = shift; my %a = @_; require LWP::UserAgent; my $ua = LWP::UserAgent->new( env_proxy => 1, keep_alive => 0, timeout => 10, agent => $SYND_AGENT,); my $req = new HTTP::Request('GET', $url); if ($a{modified_since}) { $c->log_spam("I am sending the header If-Modified-Since => ".HTTP::Date::time2str($a{modified_since})); $req->header('If-Modified-Since' => HTTP::Date::time2str($a{modified_since}) ); } if ($a{http_proxy} && (!$a{no_proxy})) { $ua->proxy(['http','https','http_cgi'],$a{http_proxy}); $c->log_warn("Using proxy $a{http_proxy} for $url"); } else { $c->log_warn("NOT using proxy $a{http_proxy} for $url"); } my $cont = ""; my $callback = sub { my ($d, $r, $p) = @_; $cont .= $d if defined($d); }; if ($a{callback}) { $callback = sub { my ($d, $r, $p) = @_; $cont .= $d if defined($d); eval { $a{callback} }; }; } my $response = $ua->request($req, $callback, 512); if ($response->code eq '304') { $c->log_warn("Not modified"); return (1,undef,$response); } elsif ($response->is_success) { $c->log_warn($cont); return (1,$cont,$response); } else { $c->log_warn("FAILLED To get $url"); $@ = "failled to get $url"; return (0,undef,$response); } } sub get_url { return shift->get_rss(@_) } sub parse_feed { my $c = shift; my $rss = shift; my @parsers = RSSReader::Parser->get_parsers(); foreach my $p (@parsers) { my ($is_owner, $could_parse, $data) = $p->parse($rss); if ( $is_owner && $could_parse ) { print STDERR "Could parse with ".ref($p)."\n"; return $data; } elsif ( $is_owner ) { return undef; } } } sub add_msg_to_feed { my $c = shift; my %a = @_; return RSSReader::Feed::Message->create(%a); } sub add_rss_results_to_feed { my $c = shift; my ($feed, $rss, $dont_delete) = @_; return 1 unless $rss; my $rss_o = $c->parse_feed($rss); return undef unless $rss_o; my @added = (); foreach my $item (@{$rss_o->{'items'}}) { my $creation = $c->add_msg_to_feed(feed=>$feed, %$item); if (!$creation) { next unless $@->{message} eq 'Message already inserted'; my $msg = RSSReader::Feed::Message->new(id=>$@->{id}, feed=>$feed); $msg->update(%$item); push @added, $msg if $msg; next; } $c->log_debug("Inserted ".$item->{title}." on ".$feed->id()); push @added, $creation; } unless ($dont_delete) { foreach my $message (@{$feed->messages}) { next if $message->to_keep(); my $was_pulled = 0; foreach my $message_pulled (@added) { if ( $message_pulled->id eq $message->id ) { $c->log_debug("This message (".$message_pulled->title.") came in feed, skip it"); $was_pulled = 1; last; } } if (! $was_pulled ) { if ( $message->get_feed->keep_for_n && $message->fetch_time && ((time() - $message->fetch_time) < $message->get_feed->keep_for_n)) { $c->log_debug("This message feed tells me to keep this message, skip it"); next; } $message->delete(); } } } $feed->description($rss_o->{channel}->{description}); $feed->source_link($rss_o->{channel}->{link}); $feed->rss_version($rss_o->{version}); $feed->extra_info ($rss_o->{channel}); if (exists($rss_o->{image}->{url}) && defined($rss_o->{image}->{url}) && $rss_o->{image}->{url} ne '') { my ($ret_code, $image, $resp) = $c->get_url($rss_o->{image}->{url}, $feed->image_last_fetched); if ($image && $ret_code) { $feed->image($image); $feed->image_last_fetched($resp->last_modified); } else { $c->log_error('URL:['.$rss_o->{image}->{url}.']'); $c->log_error("Image url was defined but could not get it"); } } return 1; } 1;