Skip to content

Instantly share code, notes, and snippets.

@s1037989
Created September 28, 2018 05:09
Show Gist options
  • Save s1037989/4ea17f078b3601d82376d4f55cefce4a to your computer and use it in GitHub Desktop.
Save s1037989/4ea17f078b3601d82376d4f55cefce4a to your computer and use it in GitHub Desktop.
hubspot api export
use Mojo::Base -strict;
use Mojo::File 'path';
use Mojo::JSON 'j';
use Mojo::UserAgent;
use Mojo::URL;
# Usage:
# HUBSPOT_HAPIKEY=8....d HUBSPOT_USERID=3....0 perl export 3 2 1
our $base = 'https://api.hubapi.com';
our %api_urls = (
companies => '/companies/v2/companies/paged', # limit, offset, has-more
company_properties => '/properties/v1/companies/properties/',
contacts => '/contacts/v1/lists/all/contacts/all', # count, vid-offset, has-more
contact_properties => '/properties/v1/contacts/properties',
engagements => '/engagements/v1/engagements/paged', # limit, offset, hasMore
);
my $max_depth = 10;
Mojo::Promise->all(companies($ARGV[0]||$max_depth), contacts($ARGV[1]||$max_depth), engagements($ARGV[2]||$max_depth))->then(sub {
say "Finished!";
printf " Companies: %d\n", shift->[0];
printf " Contacts: %d\n", shift->[0];
printf " Engagements: %d\n", shift->[0];
})->catch(sub {
my $err = shift;
warn "Something went wrong: $err";
})->wait;
sub companies {
my $max_depth = shift;
my %args = (hapikey => $ENV{HUBSPOT_HAPIKEY}, userId => $ENV{HUBSPOT_USERID}, @_);
$args{limit} ||= 250;
$args{offset} ||= 0;
my $properties_url = Mojo::URL->new($base)->path($api_urls{company_properties});
my $url = Mojo::URL->new($base)->path(delete $args{companies_url} || $api_urls{companies});
my $ua = Mojo::UserAgent->new;
my $ua_p = $ua->get_p($properties_url->query(map { $_ => $args{$_} } qw/hapikey userid/)->to_abs)->then(sub {
my $tx = shift;
my $properties = $tx->result->json;
$url = $url->query(%args);
$url = $url->query({property => $_}) foreach map { $_->{name} } @$properties;
$ua->get_p($url->to_abs);
});
for my $c ( 1..$max_depth ) {
say "Companies => Queueing $c...";
$ua_p = $ua_p->then(sub {
my $tx = shift;
return $tx unless ref $tx;
my $results = $tx->result->json('/companies');
my $file = path('.')->child('companies', "$args{limit}-$c");
$file->spurt(j($results));
my $hasmore = $tx->result->json('/has-more');
my $offset = $tx->result->json('/offset');
printf "Companies $c / $max_depth => hasMore: %d, offset: %d, results: %d, file size: %d\n", $hasmore, $offset, scalar @$results, -s $file;
$c < $max_depth && $hasmore ? $ua->get_p($url->query([offset => $offset])) : $c;
});
}
$ua_p->catch(sub{
my $err = shift;
warn "Connection error: $err";
});
}
sub contacts {
my $max_depth = shift;
my %args = (hapikey => $ENV{HUBSPOT_HAPIKEY}, userId => $ENV{HUBSPOT_USERID}, @_);
$args{count} ||= 100;
$args{vidOffset} ||= 0;
my $properties_url = Mojo::URL->new($base)->path($api_urls{contact_properties});
my $url = Mojo::URL->new($base)->path(delete $args{contacts_url} || $api_urls{contacts});
my $ua = Mojo::UserAgent->new;
my $ua_p = $ua->get_p($properties_url->query(map { $_ => $args{$_} } qw/hapikey userid/)->to_abs)->then(sub {
my $tx = shift;
my $properties = $tx->result->json;
$url = $url->query(%args);
$url = $url->query([property => $_->{name}]) foreach @$properties;
$ua->get_p($url->to_abs);
});
for my $c ( 1..$max_depth ) {
say "Contacts => Queueing $c...";
$ua_p = $ua_p->then(sub {
my $tx = shift;
return $tx unless ref $tx;
my $results = $tx->result->json('/contacts');
my $file = path('.')->child('contacts', "$args{count}-$c");
$file->spurt(j($results));
my $hasmore = $tx->result->json('/has-more');
my $offset = $tx->result->json('/vid-offset');
printf "Contacts $c / $max_depth => hasMore: %d, offset: %d, results: %d, file size: %d\n", $hasmore, $offset, scalar @$results, -s $file;
$c < $max_depth && $hasmore ? $ua->get_p($url->query([vidOffset => $offset])) : $c;
});
}
$ua_p->catch(sub{
my $err = shift;
warn "Connection error: $err";
});
}
sub engagements {
my $max_depth = shift;
my %args = (hapikey => $ENV{HUBSPOT_HAPIKEY}, userId => $ENV{HUBSPOT_USERID}, @_);
$args{limit} ||= 250;
$args{offset} ||= 0;
my $url = Mojo::URL->new($base)->path(delete $args{engagements_url} || $api_urls{engagements});
my $ua = Mojo::UserAgent->new;
my $ua_p = $ua->get_p('https://mojolicious.org')->then(sub {
my $tx = shift;
$url = $url->query(%args);
$ua->get_p($url->to_abs);
});
for my $c ( 1..$max_depth ) {
say "Engagements => Queueing $c...";
$ua_p = $ua_p->then(sub {
my $tx = shift;
return $tx unless ref $tx;
my $results = $tx->result->json('/results');
my $file = path('.')->child('engagements', "$args{limit}-$c");
$file->spurt(j($results));
my $hasmore = $tx->result->json('/hasMore');
my $offset = $tx->result->json('/offset');
printf "Engagements $c / $max_depth => hasMore: %d, offset: %d, results: %d, file size: %d\n", $hasmore, $offset, scalar @$results, -s $file;
$c < $max_depth && $hasmore ? $ua->get_p($url->query([offset => $offset])) : $c;
});
}
$ua_p->catch(sub{
my $err = shift;
warn "Connection error: $err";
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment