MetaCPAN FTW!

Dec 20, 2010 / By Yanick Champoux

Tags: , ,

Right now, Galuga has a widget that lists my CPAN distributions. But it’s a boring old static affair that is updated manually. Surely in this age of the Web 2.0, I can do better than that.

My first instinct that to go straight for my CPAN author page and extract the information off the HTML:

sub distributions {
    my $self = shift;

    my $page = get $self->author_cpan_url;

    my $dists = pQuery($page)->find('table:eq(1) tr');

    my @dists;

    $dists->each(
        sub {
            return unless shift;    # first one is headers

            my $row  = pQuery($_);
            my $name = $row->find('td:eq(0) a')->text();

            $name =~ s/-v?([\d._]*)$//;    # remove version

            my $version = $1;

            my $url = "http://search.cpan.org/dist/$name";

            $name =~ s/-/::/g;

            my $desc = $row->find('td:eq(1)')->text();
            my $date = DateTime::Format::Flexible->parse_datetime(
                $row->find('td:eq(3)')->text );

            push @dists,
              { name    => $name,
                url     => $url,
                desc    => $desc,
                date    => $date,
                version => $version,
              };
        } );

    return @dists;
}

Not too painful, all in all. Mind you, it’d be nicer not to have to fiddle with HTML tables, but short of having a bona fide API…

And that’s when Olaf’s blog reminds me of search.metacpan.org and the CPAN-API project. After a few minutes of peering at what they have to offer, the code above got simplified to:

sub distributions {
    my $self = shift;

    my $page =
      get sprintf 'http://api.metacpan.org/dist/_search?q=author:"%s"',
      $self->author_id;

    my $json = from_json($page);

    return map { {
            name    => $_->{name},
            version => $_->{version},
            url     => 'http://search.cpan.org/dist/' . $_->{name},
            date    => DateTime::Format::Flexible->parse_datetime(
                $_->{release_date}
            ), } }
           map { $_->{_source} }
               @{ $json->{hits}{hits} };

}

Sweet, isn’t?

(The code for both variants of the widget is available at my WWW-Widget GitHub repo.)

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>