App-cpanthanks
view release on metacpan or search on metacpan
#!/usr/bin/env perl
use 5.10.0;
use strict;
use warnings;
use Compiler::Lexer;
use Path::Class::Rule;
use MetaCPAN::Client;
use Term::Encoding ();
use Term::ANSIColor 'colored';
use List::Util 'any';
use Try::Tiny;
use Getopt::Long;
use Pod::Usage;
my $order_by = 'popularity'; # or 'diversity';
my $limit = 5;
my @skip_modules = qw( lib strict warnings );
my @skip_authors = qw( );
GetOptions(
'limit=i' => \$limit,
'order-by=s' => \$order_by,
'skip-modules=s{1,}' => \@skip_modules,
'skip-authors=s{1,}' => \@skip_authors,
) or pod2usage();
my $love = '<3';
if (Term::Encoding::term_encoding() =~ /^utf-?8$/i) {
binmode STDOUT, ':utf8';
$love = "\x{2665}";
}
BEGIN {
if ($^O =~ /Win32/) {
require Win32::Console::ANSI;
Win32::Console::ANSI->import;
}
}
my $lexer = Compiler::Lexer->new;
my $iter = Path::Class::Rule->new->skip_git->perl_file->iter(@ARGV);
my $cpan = MetaCPAN::Client->new;
my (%used, %author);
# fetch the modules you use
while ( defined( my $file = $iter->() )) {
my $modules = $lexer->get_used_modules( scalar $file->slurp );
foreach my $mod (@$modules) {
next if any { $mod->{name} eq $_ } @skip_modules;
$used{ $mod->{name} }++;
}
}
# fetch the modules' authors
local $| = 1;
foreach my $module (keys %used) {
print "you used $module $used{$module} times!" . (' ' x 40) . "\r";
my $id = try { $cpan->module($module)->author };
next unless $id and not any { $id eq $_ } @skip_authors;
no warnings 'uninitialized';
$author{ $id }{diversity}++;
$author{ $id }{popularity} += $used{$module};
push @{ $author{ $id }{modules} }, $module;
}
# order and display authors' informationa
my @thanks = sort { $author{$b}{$order_by} <=> $author{$a}{$order_by} } keys %author;
foreach my $i ( 0 .. $limit ) {
my $id = $thanks[$i] or last;
my $current_author = $author{$id};
say "\n" . colored(['bright_red'], $love)
. " $id wrote $current_author->{diversity} module(s) ("
. join( ',' => @{$current_author->{modules}} )
. "), used $current_author->{popularity} time(s)";
my $profile = try { $cpan->author($id) };
next unless $profile;
say 'Hey! How about ' . colored(['yellow'], 'thanking ' . $profile->name) . '? You can, for example:';
foreach my $site (@{ $profile->profile // [] }) {
if ($site->{name} eq 'gittip' or $site->{name} eq 'gratipay') {
say " * give $id a small tip on Gratipay (" . colored(['bright_blue'], "https://gratipay.com/$site->{id}") . ')';
}
elsif ($site->{name} eq 'github') {
say " * 'like' or 'follow' $id on Github (" . colored(['bright_blue'], "https://github.com/$site->{id}") . ')';
}
( run in 2.243 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )