Dubber-API
view release on metacpan or search on metacpan
lib/Dubber/API.pm view on Meta::CPAN
# return the token
return $answer->{content}{access_token};
}
# ------------------------------------------------------------------------
method is_authenticated () {
return 1 if ( ( $self->_has_auth_token ) and ( DateTime->now < $self->_auth_token_expiry ) );
return;
}
# ------------------------------------------------------------------------
method auth_token () {
if ( $self->_has_auth_token ) {
if ( DateTime->now > $self->_auth_token_expiry ) {
$self->_new_auth_token( $self->_auth_refresh_token );
}
}
else {
$self->_new_auth_token();
}
return $self->_auth_token;
}
# ------------------------------------------------------------------------
method auth_lifetime_seconds () {
return 0 unless ( $self->is_authenticated );
my $diff = $self->_auth_token_expiry->delta_ms( DateTime->now );
return ( abs( $diff->minutes * 60 ) + abs( $diff->seconds ) );
}
# ------------------------------------------------------------------------
has header => (
is => 'rw',
isa => 'HashRef',
lazy_build => 1,
);
method _build_header () {
return { Authorization => 'Bearer ' . $self->auth_token };
}
# ------------------------------------------------------------------------
has connection_cache => (
is => 'ro',
isa => 'LWP::ConnCache',
lazy_build => 1,
);
method _build_connection_cache () { return LWP::ConnCache->new( total_capacity => 5 ); }
# ------------------------------------------------------------------------
has json_coder => (
is => 'ro',
isa => 'Cpanel::JSON::XS',
lazy_build => 1,
);
method _build_json_coder () { return Cpanel::JSON::XS->new->utf8; }
# ------------------------------------------------------------------------
has endpoints => (
is => 'ro',
default => sub {
{ root => { path => '/' },
# Group Methods (Group Authentication Required)
get_group_details => { path => 'groups/:group_id' },
get_group_accounts => { path => 'groups/:group_id/accounts' },
create_child_group => { path => 'groups/:group_id/groups', method => 'POST' },
create_account => { path => 'accounts', method => 'POST' },
get_group_unidentified_recordings => { path => 'groups/:group_id/unidentified_recordings' },
create_group_unidentified_recording =>
{ path => 'groups/:group_id/unidentified_recordings', method => 'POST' },
# Account Methods
get_account_details => { path => 'accounts/:account_id' },
update_account_details => { path => 'accounts/:account_id', method => 'PUT' },
# Recording Methods
get_account_recordings => { path => 'accounts/:account_id/recordings', method => 'GET' },
create_recording => { path => 'accounts/:account_id/recordings', method => 'POST' },
get_recording_details => { path => 'recordings/:recording_id', method => 'GET' },
get_recording_waveform => { path => 'recordings/:recording_id/waveform', method => 'GET' },
delete_recording => { path => 'recordings/:recording_id', method => 'DELETE' },
update_recording_metadata => { path => 'recordings/:recording_id/metadata', method => 'PUT' },
add_recording_tags => { path => 'recordings/:recording_id/tags', method => 'POST' },
delete_recording_tags => { path => 'recordings/:recording_id/tags', method => 'DELETE' },
# Multipart Recording Methods
create_multipart_recording => { path => 'accounts/:account_id/recordings', method => 'POST' },
get_recording_upload_part => {
path => 'recordings/:recording_id/upload',
method => 'GET',
#mandatory => [qw(part_number content_md5 content_sha256)]
},
put_complete_multipart_recording_upload =>
#{ path => 'recordings/:recording_id/complete_upload', method => 'PUT', mandatory => [qw(parts)] },
{ path => 'recordings/:recording_id/complete_upload', method => 'PUT', },
abort_multipart_recording_upload => { path => 'recordings/:recording_id', method => 'DELETE' },
# User Methods
get_account_users => { path => 'accounts/:account_id/users', method => 'GET' },
create_account_user => { path => 'accounts/:account_id/users', method => 'POST' },
get_user_details => { path => 'users/:user_id', method => 'GET' },
delete_user => { path => 'users/:user_id', method => 'DELETE' },
update_user => { path => 'users/:user_id', method => 'PUT' },
# Profile Methods
get_profile => { path => 'profile', method => 'GET' },
# Notification (Rest Hook) Methods
create_group_notification => { path => 'groups/:group_id/notifications', method => 'POST' }
, # (Group Authentication Only)
get_group_notifications => { path => 'groups/:group_id/notifications', method => 'GET' }
, # (Group Authentication Only)
create_account_notification => { path => 'accounts/:account_id/notifications', method => 'POST' },
get_account_notifications => { path => 'accounts/:account_id/notifications', method => 'GET' },
get_notification_details => { path => 'notifications/:notification_id', method => 'GET' },
update_notification => { path => 'notifications/:notification_id', method => 'PUT' },
activate_notification => { path => 'notifications/:notification_id/activate', method => 'POST' },
release_unclaimed_notification => { path => 'notifications/:notification_id/unclaimed', method => 'GET' },
delete_notification => { path => 'notifications/:notification_id', method => 'DELETE' },
#Â Dub.Point (Group Authentication Required)
get_group_unidentified_dub_points =>
{ path => 'groups/:group_id/unidentified_dub_points', method => 'GET' },
get_account_dub_points => { path => 'accounts/:account_id/dub_points', method => 'GET' },
create_account_dub_point => { path => 'accounts/:account_id/dub_points', method => 'POST' },
get_dub_point_details => { path => 'dub_points/:dub_point_id', method => 'GET' },
find_dub_point => {
path => 'dub_points/find',
method => 'GET',
mandatory => [qw(external_type service_provider external_group external_identifier)]
},
# OAuth 2 Methods
revoke_access_token => { path => 'revoke', method => 'POST' },
};
},
);
method commands () { return $self->endpoints; }
# ------------------------------------------------------------------------
method upload_recording_mp3_file ($account_id, $call_metadata, $mp3_file_or_data) {
my @data_parts = $self->_split_recording_data($mp3_file_or_data);
# create the recording object
my $res = $self->create_recording( account_id => $account_id, %{$call_metadata} );
if ( $res->{code} eq '201' ) {
my $recording_id = $res->{content}{id};
my $return_status;
try {
my @etag_parts;
my $part_number = 0;
foreach my $part_data (@data_parts) {
my $md5_b64 = md5_b64($part_data);
my $sha256_hex = sha256_hex($part_data);
++$part_number;
# request to upload a recording part
my $upload_req_res = $self->get_recording_upload_part(
recording_id => $recording_id,
part_number => $part_number,
content_md5 => $md5_b64,
content_sha256 => $sha256_hex
);
if ( $upload_req_res->{code} eq '200' ) {
# upload the recording part
my $put_uri = URI->new( $upload_req_res->{content}{url} );
my $put_request = HTTP::Request->new( 'PUT', $put_uri );
$put_request->header(
'Accept' => 'application/json',
'Content-type' => 'audio/mpeg', # apparently right!
'Authorization' => $upload_req_res->{content}{authorization},
'X-Amz-Date' => $upload_req_res->{content}{'X-Amz-Date'},
'Host' => $upload_req_res->{content}{Host},
'Content-Md5' => $md5_b64,
'X-Amz-Content-Sha256' => $sha256_hex
);
$put_request->content($part_data);
my $put_response = $self->request($put_request);
if ( $put_response->is_success ) {
push( @etag_parts, { part_number => $part_number, e_tag => $put_response->header('ETag') } );
}
else {
die "Unable to PUT recording upload - $!";
}
}
else {
die "Unable to request recording upload - $!";
}
}
$return_status = $self->put_complete_multipart_recording_upload(
recording_id => $recording_id,
parts => \@etag_parts
);
}
catch {
# it failed - delete the part uploaded chunk
$self->abort_multipart_recording_upload( recording_id => $recording_id );
( run in 1.793 second using v1.01-cache-2.11-cpan-524268b4103 )