Skip to content

Instantly share code, notes, and snippets.

@hideo55
Created July 27, 2011 13:55
Show Gist options
  • Save hideo55/1109405 to your computer and use it in GitHub Desktop.
Save hideo55/1109405 to your computer and use it in GitHub Desktop.
MetaCPAN Growler - Growl::GNTP version
#!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