Skip to content

Instantly share code, notes, and snippets.

@tomill

tomill/cpanmeta-fav.pl

Last active Dec 20, 2015
Embed
What would you like to do?
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use utf8;
our $VERSION = '1.0.0';
use Docopt;
sub main {
my $opts = shift;
my $app = App::CPANMetaFav->new(
api => $opts->{'--api'},
token => $opts->{'--token'},
);
$app->get_modules($opts->{'<META.json | META.yml>'});
warn "\nPlease review your fav++ modules! [ENTER]\n";
my $yes = <STDIN>;
$app->edit_modules();
local $| = 1;
for my $module (@{ $app->modules }) {
print $module, ' - ';
my $info = $app->fetch_distinfo($module);
if (not $info) {
print "NOT FOUND\n";
next;
}
print sprintf 'https://metacpan.org/module/%s - ', $info->{documentation};
printf "%s\n", $app->fav_dist($info);
}
}
package App::CPANMetaFav;
use autodie;
use CPAN::Meta;
use File::Temp;
use JSON;
use LWP::UserAgent;
use Moo;
has api => (is => 'rw', requires => 1);
has token => (is => 'rw', requires => 1);
has modules => (is => 'rw', default => sub { [] });
has agent => (is => 'rw', default => sub {
LWP::UserAgent->new;
});
sub fetch_distinfo {
my ($self, $module) = @_;
my $res = $self->agent->get($self->api . '/module/' . $module);
return unless $res->is_success;
return decode_json($res->decoded_content);
}
sub fav_dist {
my ($self, $info) = @_;
my $res = $self->agent->post($self->api . '/user/favorite?access_token=' . $self->token,
Content_Type => 'application/json',
Content => encode_json({
release => $info->{release},
author => $info->{author},
distribution => $info->{distribution},
}),
);
return $res->status_line;
}
sub get_modules {
my ($self, $files) = @_;
my %modules;
for my $file (@$files) {
my $meta = CPAN::Meta->load_file($file);
my $reqs = $meta->effective_prereqs->as_string_hash;
map { $modules{ $_ }++ } keys %{ $_->{requires} } for values %$reqs;
}
$self->modules([ sort keys %modules ]);
}
sub edit_modules {
my ($self) = @_;
my $temp = File::Temp->new;
$temp->print("$_\n") for @{ $self->modules };
system($ENV{EDITOR}, $temp->filename); # ignore windows
open my $fh, '<', $temp->filename;
$self->modules([ map { chomp; $_ } <$fh> ]);
}
package main;
my $opts = docopt( version => $VERSION );
main($opts);
exit;
__END__
=head1 NAME
cpanmeta-fav.pl - fav modules from META
=head1 SYNOPSIS
cpanmeta-fav.pl --token=<token> [ --api=URL ] <META.json|META.yml>...
cpanmeta-fav.pl -h | --help
Options:
-h --help Show this screen.
--version Show version.
--api=URL MetaCPAN API URL [default: https://api.metacpan.org/]
--token=token Get your MetaCPAN token from https://api.metacpan.org/user
=head1 DESCRIPTION
This is my first script based on Docopt :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment