Created
July 27, 2011 13:55
-
-
Save hideo55/1109405 to your computer and use it in GitHub Desktop.
MetaCPAN Growler - Growl::GNTP version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!perl | |
use strict; | |
use warnings; | |
use Growl::GNTP; | |
use AnyEvent; | |
use AnyEvent::HTTP; | |
use JSON; | |
use Data::MessagePack; | |
use Cache::LRU; | |
use Encode; | |
our $VERSION = '0.02'; | |
my $app_name = 'MetaCPAN Growler'; | |
my $app_domain = 'org.github.hideo55.metacpangrowler'; | |
my $search_uri = 'http://api.metacpan.org/v0/release/_search'; | |
my $post_data = JSON::encode_json( | |
{ 'size' => 20, | |
'from' => 0, | |
'sort' => [ { 'date' => { 'order' => 'desc', }, }, ], | |
'query' => { match_all => {} }, | |
'fields' => [qw(name author id)], | |
} | |
); | |
my $author_api = 'http://api.metacpan.org/v0/author'; | |
my $growl = Growl::GNTP->new( AppName => $app_name ); | |
$growl->register([ | |
{ Name => "Update", }, | |
{ Name => "Error",}, | |
]); | |
my %options = ( interval => 300, maxGrowls => 10, cacheSize => 100, ); | |
my $Cache = Cache::LRU->new( size => $options{'cacheSize'} ); | |
my $t; | |
$t = AnyEvent->timer( | |
after => 0, | |
interval => $options{'interval'}, | |
cb => sub { | |
get_metacpan_info( $options{'maxGrowls'} ); | |
} | |
); | |
AE::cv->recv; | |
my %Seen; | |
sub get_metacpan_info { | |
my $max_growls = shift; | |
for my $uri ($search_uri) { | |
http_post $uri, $post_data, | |
headers => {}, | |
persistent => 0, | |
sub { | |
my $mod_info | |
= $_[1]->{Status} == 200 | |
? eval { JSON::decode_json( $_[0] ) } | |
: undef; | |
unless ($mod_info) { | |
$growl->notify( | |
Event => 'Error', | |
Title => $app_name, | |
Message => "Can't parse the metacpan response.", | |
); | |
return; | |
} | |
my @to_growl; | |
for my $entry ( @{ $mod_info->{hits}{hits} } ) { | |
my $id = $entry->{fields}{id}; | |
next if $Seen{$id}++; | |
next | |
if @to_growl >= $max_growls | |
; # not last, so that we can cache them in %Seen | |
push @to_growl, $entry; | |
} | |
for my $entry (@to_growl) { | |
my $author_id = $entry->{fields}{author}; | |
get_author( | |
$author_id, | |
sub { | |
my $author = shift; | |
$author->{name} ||= $author_id; | |
my $title = $author->{name}; | |
my $name = $entry->{fields}{name}; | |
my $description = $name; | |
$description = ' : ' . $entry->{fields}{abstract} | |
if $entry->{fields}{abstract}; | |
my $icon | |
= $author->{avatar} ? "$author->{avatar}" : q{}; | |
my $link | |
= "http://metacpan.org/release/${author_id}/${name}"; | |
$growl->notify( | |
Event => 'Update', | |
Title => encode_utf8($title), | |
Message => encode_utf8($description), | |
Icon => $author->{avatar}, | |
CallbackTarget => $link, | |
); | |
$growl->wait(1); | |
} | |
); | |
} | |
}; | |
} | |
} | |
sub get_author { | |
my ( $author, $cb ) = @_; | |
if ( my $cache = $Cache->get($author) ) { | |
$cb->( Data::MessagePack->unpack($cache) ); | |
} | |
else { | |
http_get "$author_api/$author", sub { | |
if ( $_[1]->{Status} == 200 ) { | |
my $content = JSON::decode_json( $_[0] ); | |
my $author_info = { | |
name => $content->{name}, | |
avatar => $content->{gravatar_url}, | |
}; | |
$Cache->set( | |
$author => Data::MessagePack->pack($author_info) ); | |
$cb->($author_info); | |
} | |
else { | |
$cb->( {} ); | |
} | |
}; | |
} | |
} | |
1; | |
__END__ | |
=head1 NAME | |
metacpan-growler | |
=head1 AUTHOR | |
Hideaki Ohno E<lt>hide.o.j55 {at} gmail.comE<gt> | |
=head1 SEE ALSO | |
=head1 LICENSE | |
This library is free software; you can redistribute it and/or modify | |
it under the same terms as Perl itself. | |
=cut |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment