App-cpanthanks

 view release on metacpan or  search on metacpan

cpanthanks  view on Meta::CPAN

#!/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 )