SlideShare a Scribd company logo
1 of 63
(Ab)Using the
MetaCPAN API for
 Fun and Profit
  Olaf Alders (OALDERS)
     @wundercounter
Architecture


• Built on ElasticSearch
• Uses Catalyst as a thin wrapper
• You don’t need to know this
Real life examples
iCPAN - iPhone
iCPAN - iPad
Android
What can we build?
What can we build?


• Do something with Github
What can we build?


• Do something with Github
• Get a list of all CPAN authors who
  have enabled the “hireable” flag in
  their Github profiles
Let’s Get Started
Let’s Get Started



• We want to fetch some data
Let’s Get Started



• We want to fetch some data
• We’ll use Sawyer’s MetaCPAN::API
#!/usr/bin/env perl

use strict;
use warnings;

use MetaCPAN::API;

my $mcpan = MetaCPAN::API->new();
my $author = $mcpan->author('MSTROUT');
{
    dir            =>   "id/M/MS/MSTROUT",
    email          =>   ["perl-stuff@trout.me.uk"],
    gravatar_url   =>   "https://secure.gravatar.com/avatar/...",
    name           =>   "Matt S Trout",
    pauseid        =>   "MSTROUT",
    website        =>   ["http://www.trout.me.uk/"],
}
MetaCPAN Explorer
my $author = $mcpan->author('MSTROUT');
my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        size => 1,
    },
);
{
    _shards => { failed => 0, successful => 5, total => 5 },
    hits => {
       hits => [
          {
             _id     => "KHAMPTON",
             _index => "cpan_v1",
             _score => 1,
             _source => {
                           city         => "Los Angeles",
                           country      => "US",
                           dir          => "id/K/KH/KHAMPTON",
                           email        => ["khampton@totalcinema.com", "kip.hampton@tamarou.com"],
                           gravatar_url => "http://www.gravatar.com/avatar/...",
                           name         => "Kip Hampton",
                           pauseid      => "KHAMPTON",
                           profile      => [
                                              { id => "ubu", name => "coderwall" },
                                              { id => "ubu", name => "github" },
                                              { id => "kiphampton", name => "twitter" },
                                           ],
                           region       => "CA",
                           updated      => "2011-07-22T20:42:06",
                           website      => ["http://totalcinema.com/"],
                        },
             _type   => "author",
          },
       ],
       max_score => 1,
       total => 9780,
    },
    timed_out => bless(do{(my $o = 0)}, "JSON::XS::Boolean"),
    took => 1,
}
my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        size => 1,
    },
);

# dump $result->{hits}->{hits}->[0]->{_source};
{
  city         =>   "Los Angeles",
  country      =>   "US",
  dir          =>   "id/K/KH/KHAMPTON",
  email        =>   ["khampton@totalcinema.com", "kip.hampton
@tamarou.com"],
  gravatar_url => "http://www.gravatar.com/avatar/...",
  name         => "Kip Hampton",
  pauseid      => "KHAMPTON",
  profile      => [
                     { id => "ubu", name => "coderwall" },
                     { id => "ubu", name => "github" },
                     { id => "kiphampton", name => "twitter" },
                  ],
    region     => "CA",
    updated    => "2011-07-22T20:42:06",
    website    => ["http://totalcinema.com/"],
}
my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        size   => 100,
    },
);
my $filter = {
        { term   => { 'author.profile.name' => 'stackoverflow', } },
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
    },
);
use Pithub;
my $p = Pithub->new;

AUTHOR:
foreach my $author ( @{ $result->{hits}->{hits} } ) {

    foreach my $profile ( @{ $author->{_source}->{profile} } ) {

        if ( $profile->{name} eq 'github' ) {

            my $username = $profile->{id};
            $username =~ s{https?://github.com/(w*)/?}{$1}i;
            next AUTHOR if !$username;

            if ( $p->users->get( user => $username )->content->{hireable} ) {
                # do something...
            }
            next AUTHOR;
        }
    }
}
Getting fancy
my $filter = {
    and => [
        { term   => { 'author.profile.name' => 'github', } },
        { term   => { 'author.country'      => 'US', } }
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
    },
);
my $filter = {
    and => [
        { term     => { 'author.profile.name' => 'github', } },
        { term     => { 'author.country'      => 'US', } },
        { exists   => { 'field'               => 'author.region' } },
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
    },
);
my $filter = {
    and => [
        { term      =>   {   'author.profile.name'   =>   'github', } },
        { term      =>   {   'author.country'        =>   'US', } },
        { exists    =>   {   'field'                 =>   'author.region' } },
        { missing   =>   {   'field'                 =>   'author.location' } },
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
    },
);

# “missing” isn’t really helpful in this search
# just an example of how you might use it
my $filter = {
    or => [
        { term      =>   {   'author.profile.name'   =>   'github', } },
        { term      =>   {   'author.country'        =>   'US', } },
        { exists    =>   {   'field'                 =>   'author.region' } },
        { missing   =>   {   'field'                 =>   'author.location' } },
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
    },
);
my $filter = {
    or => [
        { term      =>   {   'author.profile.name'   =>   'github', } },
        { term      =>   {   'author.country'        =>   'US', } },
        { exists    =>   {   'field'                 =>   'author.region' } },
        { missing   =>   {   'field'                 =>   'author.location' } },
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
        fields => [ 'pauseid', 'country' ],
    },
);
my $filter = {
    or => [
        { term      =>   {   'author.profile.name'   =>   'github', } },
        { term      =>   {   'author.country'        =>   'US', } },
        { exists    =>   {   'field'                 =>   'author.region' } },
        { missing   =>   {   'field'                 =>   'author.location' } },
    ]
};

my $result = $mcpan->post(
    'author',
    {   query => { match_all => {} },
        filter => $filter,
        size   => 100,
        sort   => [ { 'author.pauseid' => 'ASC' } ],
    },
);
Getting Help



• #metacpan or irc.perl.org
• https://metacpan.org/about/resources
Resources


• https://github.com/CPAN-API/cpan-
  api/wiki/Beta-API-docs
• http://www.slideshare.net/
  clintongormley/terms-of-endearment-
  the-elasticsearch-query-dsl-explained
Bonus Slides
Base URL



• http://api.metacpan.org/v0
Convenience Endpoints
Convenience Endpoints

• /author/DOY
• /distribution/Moose
• /release/Moose
• /module/Moose
• /pod/Moose
Exporting Pod


• /pod/Moose?content-type=text/html (default)
• /pod/Moose?content-type=text/plain
• /pod/Moose?content-type=text/x-pod
• /pod/Moose?content-type=text/x-markdown
The (real) Endpoints
The (real) Endpoints
• /author
The (real) Endpoints
• /author
• /distribution
The (real) Endpoints
• /author
• /distribution
• /favorite
The (real) Endpoints
• /author
• /distribution
• /favorite
• /rating
The (real) Endpoints
• /author
• /distribution
• /favorite
• /rating
• /release
The (real) Endpoints
• /author
• /distribution
• /favorite
• /rating
• /release
• /file
The (real) Endpoints
• /author
• /distribution
• /favorite
• /rating
• /release
• /file
Using a cache

use HTTP::Tiny::Mech;
use MetaCPAN::API;
use WWW::Mechanize::Cached;

my $mcpan = MetaCPAN::API->new(
    ua => HTTP::Tiny::Mech->new(
        mechua => WWW::Mechanize::Cached->new()
    )
);
Enable Compression


• use WWW::Mechanize::Gzip
• use WWW::Mechanize::Cached::Gzip
• Or set the appropriate request header
Use the scrolling API


• The scrolling API allows you to iterate
  over an arbitrary number of results
• Be aware that when you scroll, your
  docs will come back unsorted

More Related Content

What's hot

Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Masahiro Nagano
 
Why Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary ThingWhy Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary ThingChris Reynolds
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helperslicejack
 
DPC 2012 : PHP in the Dark Workshop
DPC 2012 : PHP in the Dark WorkshopDPC 2012 : PHP in the Dark Workshop
DPC 2012 : PHP in the Dark WorkshopJeroen Keppens
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a bossgsterndale
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway ichikaway
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
全裸でワンライナー(仮)
全裸でワンライナー(仮)全裸でワンライナー(仮)
全裸でワンライナー(仮)Yoshihiro Sugi
 
DBIx::Class beginners
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginnersleo lapworth
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)Nikita Popov
 
HappyKardashian.com for #FVCP
HappyKardashian.com for #FVCPHappyKardashian.com for #FVCP
HappyKardashian.com for #FVCPEric Michalsen
 

What's hot (20)

Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
 
Why Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary ThingWhy Hacking WordPress Search Isn't Some Big Scary Thing
Why Hacking WordPress Search Isn't Some Big Scary Thing
 
My First Ruby
My First RubyMy First Ruby
My First Ruby
 
Inc
IncInc
Inc
 
PHP code examples
PHP code examplesPHP code examples
PHP code examples
 
WordPress Cuztom Helper
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helper
 
DPC 2012 : PHP in the Dark Workshop
DPC 2012 : PHP in the Dark WorkshopDPC 2012 : PHP in the Dark Workshop
DPC 2012 : PHP in the Dark Workshop
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
 
wget.pl
wget.plwget.pl
wget.pl
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
My shell
My shellMy shell
My shell
 
全裸でワンライナー(仮)
全裸でワンライナー(仮)全裸でワンライナー(仮)
全裸でワンライナー(仮)
 
DBIx::Class beginners
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginners
 
PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)
 
Fantom and Tales
Fantom and TalesFantom and Tales
Fantom and Tales
 
HappyKardashian.com for #FVCP
HappyKardashian.com for #FVCPHappyKardashian.com for #FVCP
HappyKardashian.com for #FVCP
 

Viewers also liked

The MetaCPAN VM for Dummies Part One (Installation)
The MetaCPAN VM for Dummies Part One (Installation)The MetaCPAN VM for Dummies Part One (Installation)
The MetaCPAN VM for Dummies Part One (Installation)Olaf Alders
 
The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)Olaf Alders
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No LearningOlaf Alders
 
Ab(Using) the MetaCPAN API for Fun and Profit v2013
Ab(Using) the MetaCPAN API for Fun and Profit v2013Ab(Using) the MetaCPAN API for Fun and Profit v2013
Ab(Using) the MetaCPAN API for Fun and Profit v2013Olaf Alders
 
Modern Perl for Non-Perl Programmers
Modern Perl for Non-Perl ProgrammersModern Perl for Non-Perl Programmers
Modern Perl for Non-Perl ProgrammersDave Cross
 

Viewers also liked (8)

Mangling
Mangling Mangling
Mangling
 
The MetaCPAN VM for Dummies Part One (Installation)
The MetaCPAN VM for Dummies Part One (Installation)The MetaCPAN VM for Dummies Part One (Installation)
The MetaCPAN VM for Dummies Part One (Installation)
 
The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)The MetaCPAN VM Part II (Using the VM)
The MetaCPAN VM Part II (Using the VM)
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No Learning
 
Ab(Using) the MetaCPAN API for Fun and Profit v2013
Ab(Using) the MetaCPAN API for Fun and Profit v2013Ab(Using) the MetaCPAN API for Fun and Profit v2013
Ab(Using) the MetaCPAN API for Fun and Profit v2013
 
Git submodule
Git submoduleGit submodule
Git submodule
 
Modern Perl for Non-Perl Programmers
Modern Perl for Non-Perl ProgrammersModern Perl for Non-Perl Programmers
Modern Perl for Non-Perl Programmers
 
Medium Perl
Medium PerlMedium Perl
Medium Perl
 

Similar to (Ab)Using the MetaCPAN API for Fun and Profit

Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaiMasters
 
20 modules i haven't yet talked about
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked aboutTatsuhiko Miyagawa
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webclkao
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongersbrian d foy
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6garux
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScriptniklal
 
C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample PhpJH Lee
 
Simple Ways To Be A Better Programmer (OSCON 2007)
Simple Ways To Be A Better Programmer (OSCON 2007)Simple Ways To Be A Better Programmer (OSCON 2007)
Simple Ways To Be A Better Programmer (OSCON 2007)Michael Schwern
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairMark
 
Hidden treasures of Ruby
Hidden treasures of RubyHidden treasures of Ruby
Hidden treasures of RubyTom Crinson
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 DatasourceKaz Watanabe
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)Jeff Eaton
 

Similar to (Ab)Using the MetaCPAN API for Fun and Profit (20)

Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
20 modules i haven't yet talked about
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked about
 
Php
PhpPhp
Php
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
Perl Bag of Tricks - Baltimore Perl mongers
Perl Bag of Tricks  -  Baltimore Perl mongersPerl Bag of Tricks  -  Baltimore Perl mongers
Perl Bag of Tricks - Baltimore Perl mongers
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
Daily notes
Daily notesDaily notes
Daily notes
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
 
Damn Fine CoffeeScript
Damn Fine CoffeeScriptDamn Fine CoffeeScript
Damn Fine CoffeeScript
 
Ae internals
Ae internalsAe internals
Ae internals
 
Php functions
Php functionsPhp functions
Php functions
 
C A S Sample Php
C A S Sample PhpC A S Sample Php
C A S Sample Php
 
Simple Ways To Be A Better Programmer (OSCON 2007)
Simple Ways To Be A Better Programmer (OSCON 2007)Simple Ways To Be A Better Programmer (OSCON 2007)
Simple Ways To Be A Better Programmer (OSCON 2007)
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love Affair
 
Hidden treasures of Ruby
Hidden treasures of RubyHidden treasures of Ruby
Hidden treasures of Ruby
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 

Recently uploaded

MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxAnupkumar Sharma
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPCeline George
 
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxGrade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxChelloAnnAsuncion2
 
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...Postal Advocate Inc.
 
ENGLISH6-Q4-W3.pptxqurter our high choom
ENGLISH6-Q4-W3.pptxqurter our high choomENGLISH6-Q4-W3.pptxqurter our high choom
ENGLISH6-Q4-W3.pptxqurter our high choomnelietumpap1
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parentsnavabharathschool99
 
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITY
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITYISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITY
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITYKayeClaireEstoconing
 
Roles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceRoles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceSamikshaHamane
 
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptx
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptxECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptx
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptxiammrhaywood
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxDr.Ibrahim Hassaan
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designMIPLM
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTiammrhaywood
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Celine George
 
Earth Day Presentation wow hello nice great
Earth Day Presentation wow hello nice greatEarth Day Presentation wow hello nice great
Earth Day Presentation wow hello nice greatYousafMalik24
 
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...JhezDiaz1
 
Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Celine George
 
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17Celine George
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxthorishapillay1
 

Recently uploaded (20)

MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptxMULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
MULTIDISCIPLINRY NATURE OF THE ENVIRONMENTAL STUDIES.pptx
 
What is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERPWhat is Model Inheritance in Odoo 17 ERP
What is Model Inheritance in Odoo 17 ERP
 
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptxGrade 9 Q4-MELC1-Active and Passive Voice.pptx
Grade 9 Q4-MELC1-Active and Passive Voice.pptx
 
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...
USPS® Forced Meter Migration - How to Know if Your Postage Meter Will Soon be...
 
ENGLISH6-Q4-W3.pptxqurter our high choom
ENGLISH6-Q4-W3.pptxqurter our high choomENGLISH6-Q4-W3.pptxqurter our high choom
ENGLISH6-Q4-W3.pptxqurter our high choom
 
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptxLEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
LEFT_ON_C'N_ PRELIMS_EL_DORADO_2024.pptx
 
Choosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for ParentsChoosing the Right CBSE School A Comprehensive Guide for Parents
Choosing the Right CBSE School A Comprehensive Guide for Parents
 
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITY
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITYISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITY
ISYU TUNGKOL SA SEKSWLADIDA (ISSUE ABOUT SEXUALITY
 
Roles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in PharmacovigilanceRoles & Responsibilities in Pharmacovigilance
Roles & Responsibilities in Pharmacovigilance
 
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdfTataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
 
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptx
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptxECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptx
ECONOMIC CONTEXT - PAPER 1 Q3: NEWSPAPERS.pptx
 
Gas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptxGas measurement O2,Co2,& ph) 04/2024.pptx
Gas measurement O2,Co2,& ph) 04/2024.pptx
 
Keynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-designKeynote by Prof. Wurzer at Nordex about IP-design
Keynote by Prof. Wurzer at Nordex about IP-design
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17
 
Earth Day Presentation wow hello nice great
Earth Day Presentation wow hello nice greatEarth Day Presentation wow hello nice great
Earth Day Presentation wow hello nice great
 
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...
ENGLISH 7_Q4_LESSON 2_ Employing a Variety of Strategies for Effective Interp...
 
Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17Difference Between Search & Browse Methods in Odoo 17
Difference Between Search & Browse Methods in Odoo 17
 
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17
Incoming and Outgoing Shipments in 3 STEPS Using Odoo 17
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptx
 

(Ab)Using the MetaCPAN API for Fun and Profit

  • 1. (Ab)Using the MetaCPAN API for Fun and Profit Olaf Alders (OALDERS) @wundercounter
  • 2. Architecture • Built on ElasticSearch • Uses Catalyst as a thin wrapper • You don’t need to know this
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17. What can we build?
  • 18. What can we build? • Do something with Github
  • 19. What can we build? • Do something with Github • Get a list of all CPAN authors who have enabled the “hireable” flag in their Github profiles
  • 21. Let’s Get Started • We want to fetch some data
  • 22. Let’s Get Started • We want to fetch some data • We’ll use Sawyer’s MetaCPAN::API
  • 23. #!/usr/bin/env perl use strict; use warnings; use MetaCPAN::API; my $mcpan = MetaCPAN::API->new(); my $author = $mcpan->author('MSTROUT');
  • 24. { dir => "id/M/MS/MSTROUT", email => ["perl-stuff@trout.me.uk"], gravatar_url => "https://secure.gravatar.com/avatar/...", name => "Matt S Trout", pauseid => "MSTROUT", website => ["http://www.trout.me.uk/"], }
  • 25.
  • 26.
  • 28. my $author = $mcpan->author('MSTROUT');
  • 29. my $result = $mcpan->post( 'author', { query => { match_all => {} }, size => 1, }, );
  • 30. { _shards => { failed => 0, successful => 5, total => 5 }, hits => { hits => [ { _id => "KHAMPTON", _index => "cpan_v1", _score => 1, _source => { city => "Los Angeles", country => "US", dir => "id/K/KH/KHAMPTON", email => ["khampton@totalcinema.com", "kip.hampton@tamarou.com"], gravatar_url => "http://www.gravatar.com/avatar/...", name => "Kip Hampton", pauseid => "KHAMPTON", profile => [ { id => "ubu", name => "coderwall" }, { id => "ubu", name => "github" }, { id => "kiphampton", name => "twitter" }, ], region => "CA", updated => "2011-07-22T20:42:06", website => ["http://totalcinema.com/"], }, _type => "author", }, ], max_score => 1, total => 9780, }, timed_out => bless(do{(my $o = 0)}, "JSON::XS::Boolean"), took => 1, }
  • 31. my $result = $mcpan->post( 'author', { query => { match_all => {} }, size => 1, }, ); # dump $result->{hits}->{hits}->[0]->{_source};
  • 32. { city => "Los Angeles", country => "US", dir => "id/K/KH/KHAMPTON", email => ["khampton@totalcinema.com", "kip.hampton @tamarou.com"], gravatar_url => "http://www.gravatar.com/avatar/...", name => "Kip Hampton", pauseid => "KHAMPTON", profile => [ { id => "ubu", name => "coderwall" }, { id => "ubu", name => "github" }, { id => "kiphampton", name => "twitter" }, ], region => "CA", updated => "2011-07-22T20:42:06", website => ["http://totalcinema.com/"], }
  • 33. my $result = $mcpan->post( 'author', { query => { match_all => {} }, size => 100, }, );
  • 34. my $filter = { { term => { 'author.profile.name' => 'stackoverflow', } }, }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, }, );
  • 35. use Pithub; my $p = Pithub->new; AUTHOR: foreach my $author ( @{ $result->{hits}->{hits} } ) { foreach my $profile ( @{ $author->{_source}->{profile} } ) { if ( $profile->{name} eq 'github' ) { my $username = $profile->{id}; $username =~ s{https?://github.com/(w*)/?}{$1}i; next AUTHOR if !$username; if ( $p->users->get( user => $username )->content->{hireable} ) { # do something... } next AUTHOR; } } }
  • 37. my $filter = { and => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } } ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, }, );
  • 38. my $filter = { and => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } }, { exists => { 'field' => 'author.region' } }, ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, }, );
  • 39. my $filter = { and => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } }, { exists => { 'field' => 'author.region' } }, { missing => { 'field' => 'author.location' } }, ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, }, ); # “missing” isn’t really helpful in this search # just an example of how you might use it
  • 40. my $filter = { or => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } }, { exists => { 'field' => 'author.region' } }, { missing => { 'field' => 'author.location' } }, ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, }, );
  • 41. my $filter = { or => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } }, { exists => { 'field' => 'author.region' } }, { missing => { 'field' => 'author.location' } }, ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, fields => [ 'pauseid', 'country' ], }, );
  • 42. my $filter = { or => [ { term => { 'author.profile.name' => 'github', } }, { term => { 'author.country' => 'US', } }, { exists => { 'field' => 'author.region' } }, { missing => { 'field' => 'author.location' } }, ] }; my $result = $mcpan->post( 'author', { query => { match_all => {} }, filter => $filter, size => 100, sort => [ { 'author.pauseid' => 'ASC' } ], }, );
  • 43. Getting Help • #metacpan or irc.perl.org • https://metacpan.org/about/resources
  • 44. Resources • https://github.com/CPAN-API/cpan- api/wiki/Beta-API-docs • http://www.slideshare.net/ clintongormley/terms-of-endearment- the-elasticsearch-query-dsl-explained
  • 48. Convenience Endpoints • /author/DOY • /distribution/Moose • /release/Moose • /module/Moose • /pod/Moose
  • 49.
  • 50. Exporting Pod • /pod/Moose?content-type=text/html (default) • /pod/Moose?content-type=text/plain • /pod/Moose?content-type=text/x-pod • /pod/Moose?content-type=text/x-markdown
  • 53. The (real) Endpoints • /author • /distribution
  • 54. The (real) Endpoints • /author • /distribution • /favorite
  • 55. The (real) Endpoints • /author • /distribution • /favorite • /rating
  • 56. The (real) Endpoints • /author • /distribution • /favorite • /rating • /release
  • 57. The (real) Endpoints • /author • /distribution • /favorite • /rating • /release • /file
  • 58. The (real) Endpoints • /author • /distribution • /favorite • /rating • /release • /file
  • 59.
  • 60. Using a cache use HTTP::Tiny::Mech; use MetaCPAN::API; use WWW::Mechanize::Cached; my $mcpan = MetaCPAN::API->new( ua => HTTP::Tiny::Mech->new( mechua => WWW::Mechanize::Cached->new() ) );
  • 61.
  • 62. Enable Compression • use WWW::Mechanize::Gzip • use WWW::Mechanize::Cached::Gzip • Or set the appropriate request header
  • 63. Use the scrolling API • The scrolling API allows you to iterate over an arbitrary number of results • Be aware that when you scroll, your docs will come back unsorted

Editor's Notes

  1. show of hands: \n1) have used the metacpan search site \n2) use it as their default search site \n3) have worked with the API\n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. CPAN visualization tool\n
  11. \n
  12. \n
  13. \n
  14. Exports Pod into a format you can import right into your Kindle app.\n
  15. \n
  16. Drop-in replacement for Perldoc. Read documentation for modules which you haven’t even installed. Genius.\n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. You can see that for the email and website fields, we allow you to provide a list rather than a single value. Now, for our example we need an author’s Github profile. Matt Trout does not provide this, so he’s a bad test case for our script.\n
  23. Things like StackOverflow, Twitter and Github usernames are all provided by authors voluntarily after logging in to MetaCPAN. In order to see what the profiles look like in a data structure, we need to find an author who has filled these fields.\n
  24. You can see from Mo’s example here that he has filled out some of his profile information. He’s a good test case. Note the MetaCPAN explorer link on the bottom left corner. These links can also be found on the module and release pages.\n
  25. This is a great way to explore the various endpoints of the API and practice crafting queries by hand. However, today we’re just concerned with the /author endpoint.\n
  26. \n
  27. \n
  28. You can see here that since we’re no longer using a convenience endpoint, the output is a little busier. What we generally care about here is the list provided inside of hits->{hits}. In each list item, we care about _source and _source->{profile} in particular.\n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n