App-Twitch
view release on metacpan or search on metacpan
lib/App/Twitch.pm view on Meta::CPAN
package App::Twitch;
BEGIN {
$App::Twitch::AUTHORITY = 'cpan:GETTY';
}
BEGIN {
$App::Twitch::VERSION = '0.904';
}
# ABSTRACT: Your personal Twitter b...... lalalala
# Speed up complete POE Kernel
sub POE::Kernel::USE_SIGCHLD () { 1 }
use MooseX::POE;
with qw(
MooseX::Getopt
MooseX::SimpleConfig
MooseX::LogDispatch
MooseX::Daemonize
);
use POE qw(
Component::Client::HTTP
Component::Client::Keepalive
Component::FeedAggregator
Component::WWW::Shorten
);
use HTTP::Request;
use Text::Trim;
use URI;
use POSIX;
use IO::All;
use String::Truncate qw(elide);
use utf8;
use Text::Keywords;
use Text::Keywords::Container;
use Text::Keywords::List;
use Text::Tweet;
use HTML::ExtractContent;
use Carp qw( croak );
use YAML qw( DumpFile );
# could be ... ah forget it :-P
use Net::Twitter;
our $VERSION ||= '0.0development';
before run => sub {
my $package = __PACKAGE__;
print <<"END_OF_INTRO";
_ _ _ _
| |_ _ _(_) |_ ___| |___
| _\\ \\ /\\ / / | __/ __| '_ \\
| |_ \\ V V /| | || (__| | | | $package $VERSION
\\__| \\_/\\_/ |_|\\__\\___|_| |_| Usage with --help
More information under http://search.cpan.org/perldoc/twitch
Commands:
start Start the twitch
stop Stop the running twitch
restart Restart the twitch, or start it up if not running
status Give current status of the twitch
END_OF_INTRO
};
after start => sub {
my $self = shift;
return unless $self->is_daemon;
# Required, elsewhere your POE goes nuts
POE::Kernel->has_forked if !$self->foreground;
POE::Kernel->run;
};
has '+pidbase' => (
default => sub { shift->tmpdir },
documentation => 'Directory for the pid file (default: tmpdir)',
);
has '+pidfile' => (
documentation => 'Filename for the pidfile (default: basedir/progname.pid)',
lib/App/Twitch.pm view on Meta::CPAN
tmpdir => $self->tmpdir,
logger => $self->logger,
http_agent => $self->http_agent,
);
},
);
has _twitter => (
traits => [ 'NoGetopt' ],
isa => 'Net::Twitter',
is => 'ro',
lazy => 1,
default => sub {
my $self = shift;
$self->logger->debug($self->logger_prefix.'Starting Net::Twitter');
Net::Twitter->new(
traits => [qw/ API::REST API::Search OAuth /],
consumer_key => $self->consumer_key,
consumer_secret => $self->consumer_secret,
access_token => $self->access_token,
access_token_secret => $self->access_token_secret,
),
},
);
has _session => (
is => 'rw',
isa => 'POE::Session',
traits => [ 'NoGetopt' ],
);
has _keywords => (
is => 'ro',
isa => 'Text::Keywords',
traits => [ 'NoGetopt' ],
lazy => 1,
default => sub {
Text::Keywords->new(
containers => shift->_containers,
)
},
);
has _tweet => (
is => 'ro',
isa => 'Text::Tweet',
traits => [ 'NoGetopt' ],
lazy => 1,
default => sub {
Text::Tweet->new()
},
);
has _http_alias => (
is => 'rw',
isa => 'Str',
traits => [ 'NoGetopt' ],
default => sub { 'http' },
);
has _keepalive => (
isa => 'POE::Component::Client::Keepalive',
is => 'ro',
traits => [ 'NoGetopt' ],
lazy => 1,
default => sub {
my ( $self ) = @_;
$self->logger->debug($self->logger_prefix.'Startup POE::Component::Client::Keepalive');
POE::Component::Client::Keepalive->new(
keep_alive => 20, # seconds to keep connections alive
max_open => 100, # max concurrent connections - total
max_per_host => 100, # max concurrent connections - per host
timeout => 10, # max time (seconds) to establish a new connection
)
},
);
has _shorten => (
isa => 'POE::Component::WWW::Shorten',
is => 'ro',
traits => [ 'NoGetopt' ],
lazy => 1,
default => sub {
my ( $self ) = @_;
$self->logger->debug($self->logger_prefix.'Startup '.$self->shorten_type.' Shorten Service...');
return POE::Component::WWW::Shorten->spawn(
alias => $self->_shorten_alias,
type => $self->shorten_type,
params => $self->shorten_params,
);
},
);
has _shorten_alias => (
is => 'rw',
isa => 'Str',
traits => [ 'NoGetopt' ],
default => sub { 'shorten' },
);
has _entry_count => (
traits => [ 'Counter', 'NoGetopt' ],
is => 'ro',
isa => 'Num',
default => 0,
handles => {
_entry_count_inc => 'inc',
},
);
sub running_config { shift->_running_config(@_) }
has _running_config => (
is => 'rw',
isa => 'HashRef',
traits => [ 'NoGetopt' ],
lazy => 1,
default => sub {
my $self = shift;
my %attributes;
for ($self->meta->get_all_attributes) {
if (!$_->does('MooseX::Getopt::Meta::Attribute::Trait::NoGetopt')) {
my $value = $_->get_value($self);
$value = $value->file if (blessed $value and $value->isa('MooseX::Daemonize::Pid::File'));
$value = $value->stringify if (blessed $value and ( $value->isa('Path::Class::Dir') or $value->isa('Path::Class::File') ));
$attributes{$_->name} = $value;
}
}
$attributes{INC} = \@INC;
$attributes{PACKAGE} = __PACKAGE__;
lib/App/Twitch.pm view on Meta::CPAN
$0 = __PACKAGE__.' '.$VERSION.' using '.( getcwd ).'/'.$self->configfile;
}
sub run {
my ( $self ) = @_;
POE::Kernel->run;
if (!blessed $self) {
$self = $self->new_with_options;
}
my ( $cmd ) = @{$self->extra_argv};
$cmd = 'start' if !$cmd;
print "Using configfile: ".( getcwd ).'/'.$self->configfile."\n";
print "Status: ".$self->status_message."\n" if ($cmd ne 'status' && $self->status);
print "\n";
die __PACKAGE__." already running...\n" if ($cmd eq 'start' && $self->status);
die __PACKAGE__." not running...\n" if ($cmd eq 'stop' && !$self->status);
if ($cmd eq 'start') {
print "Starting up ".__PACKAGE__."...\n";
$self->start;
};
if ($cmd eq 'status') {
print "Status: ".__PACKAGE__." is ".( $self->status ? '' : 'not ')."running...\n";
exit $self->status ? 0 : 1;
}
if ($cmd eq 'restart') {
if ($self->status) {
print __PACKAGE__." not running, starting up...\n";
} else {
print __PACKAGE__." restarting...\n";
}
$self->restart;
}
if ($cmd eq 'stop') {
print "Stopping ".__PACKAGE__."...\n";
$self->stop;
};
exit $self->exit_code;
}
sub START {
my ( $self, $session ) = @_[ OBJECT, SESSION ];
$self->set_process_name;
$self->logger->info($self->logger_prefix.'Starting up App::Twitch '.$App::Twitch::VERSION.'... ');
$self->logger->debug($self->logger_prefix.'Assigning POE::Session');
$self->_session($session);
$self->_containers;
$self->_twitter if !$self->dryrun;
$self->_tweet;
$self->_keywords;
$self->_feedaggregator;
$self->_shorten if !$self->dryrun;
$self->logger->info($self->logger_prefix.'Startup HTTP Service...');
POE::Component::Client::HTTP->spawn(
Agent => $self->http_agent,
Alias => $self->_http_alias,
Timeout => 30,
ConnectionManager => $self->_keepalive,
FollowRedirects => 5,
);
$self->_max_feeds_count;
my $running_config_dumpfile = $self->tmpdir.'/'.$self->configfile;
$running_config_dumpfile =~ s/\.yml/\.running_config\.yml/;
DumpFile($running_config_dumpfile,$self->running_config);
chmod 0600, $running_config_dumpfile;
$self->yield('add_feed');
}
event add_feed => sub {
my ( $self, $kernel ) = @_[ OBJECT, KERNEL ];
my $feed_url = $self->feeds_shift;
$self->logger->info($self->logger_prefix.'Adding feed: '.$feed_url);
eval {
my $feed = {
url => $feed_url,
delay => $self->feed_delay,
max_headlines => 100,
ignore_first => $self->ignore_first,
};
$self->_feedaggregator->add_feed($feed);
};
$self->logger->error($self->logger_prefix.'ERROR ['.$feed_url.']: '.$@) if $@;
my $delay = floor( $self->feed_delay / $self->_max_feeds_count );
$kernel->delay('add_feed',$delay) if $self->feeds_count;
};
event new_feed_entry => sub {
my ( $self, $feed, $entry ) = @_[ OBJECT, ARG0..$#_ ];
$self->_entry_count_inc;
my $url = $entry->link;
$url =~ s/ //g;
my $event = {
entry => $entry,
url => $url,
run_id => $self->_entry_count,
};
$self->logger->debug($self->logger_prefix.'{'.$event->{run_id}.'} New feed entry: '.$url);
POE::Kernel->post(
$self->_http_alias,
'request',
'new_content',
HTTP::Request->new(GET => $url),
$event,
);
};
use Encode;
require Encode::Detect;
event new_content => sub {
my ( $self, $request_packet, $response_packet ) = @_[ OBJECT, ARG0..$#_ ];
my $event = $request_packet->[1];
my $response = $response_packet->[0];
eval {
if ($response->code == 200) {
my $extractor = HTML::ExtractContent->new;
my $content = $response->decoded_content;
my $title = $event->{entry}->title;
( run in 0.861 second using v1.01-cache-2.11-cpan-df04353d9ac )