package Feed; use Moose; use namespace::autoclean; use 5.012; use MooseX::Types::URI 'Uri'; use Moose::Util::TypeConstraints; with 'MooseX::Traits'; use XML::Feed; use Log::Log4perl; use LWP::UserAgent; use URI::Fetch; use Moose::Util 'ensure_all_roles'; sub log { my ($self) = @_; my $caller = caller(); return Log::Log4perl->get_logger($caller) } has '+_trait_namespace' => ( default => __PACKAGE__ . '::Role' ); has uri => ( is => 'ro', isa => Uri, coerce => 1, required => 1, ); duck_type 'UA' => [ 'get' ]; coerce 'UA', from 'Str', via { __PACKAGE__->build_user_agent($_) }; has user_agent => ( is => 'ro', isa => 'UA', coerce => 1, lazy_build => 1, builder => 'build_user_agent', ); has feed => ( is => 'ro', isa => 'XML::Feed', lazy_build => 1, builder => 'get_feed', ); has title => ( is => 'ro', isa => 'Str', lazy_build => 1, builder => 'extract_title', ); sub BUILD { my ($self) = @_; Log::Log4perl::MDC->put( uri => $self->uri->as_string ); return; } sub DEMOLISH { Log::Log4perl::MDC->put( uri => undef ); return; } sub extract_title { my ($self) = @_; return $self->feed->title; } has _entries => ( is => 'ro', isa => 'ArrayRef[XML::Feed::Entry]', traits => [ 'Array' ], lazy_build => 1, builder => 'extract_entries', handles => { entries => 'elements', count_entries => 'count', }, ); sub build_user_agent { my ($self,$agent_id) = @_; $agent_id //= 'curl/7.26.0'; require IO::Socket::SSL; require HTTP::Headers; return LWP::UserAgent->new( agent => $agent_id, ssl_opts => { verify_hostname => 0, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(), }, timeout => 30, cookie_jar => {}, protocols_allowed => [ 'http', 'https', 'file' ], default_headers => HTTP::Headers->new( Accept => '*/*', ), ); } sub process { my ($self) = @_; $self->log->trace('process - begin'); for my $entry ($self->entries) { ensure_all_roles($entry,'Feed::HelperRole::FeedEntry'); $self->process_entry($entry); } $self->log->trace('process - end'); return; } sub get_feed { my ($self) = @_; $self->log->trace('get_feed ' . $self->uri); my $response = $self->user_agent->get($self->uri); die sprintf('Got code "%s" processing feed %s',$response->status_line,$self->uri) unless $response->is_success; my $content = $response->decoded_content; $content =~ s{^\s*}{}; # some feed have invalid whitespace at the beginning return( XML::Feed->parse(\$content) or die XML::Feed->errstr ); } sub extract_entries { my ($self) = @_; $self->log->trace('extract_entries'); return [$self->feed->entries]; } sub process_entry { my ($self) = @_; $self->log->trace('process_entry - stub'); } __PACKAGE__->meta->make_immutable; 1;