# # Copyright: 2013-2015 Sipwise Development Team # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This package is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # On Debian systems, the complete text of the GNU General # Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". # package Sipwise::API 0.001; use strict; use warnings; use English; use Hash::Merge qw( merge ); use JSON qw(); use LWP::UserAgent; use IO::Socket::SSL; use URI; use Data::Dumper; use File::Slurp; use IO::Uncompress::Unzip; my $default_crt_path = '/usr/share/kamailio-config-tests/apicert.pem'; if(exists $ENV{'BASE_DIR'}){ $default_crt_path = $ENV{'BASE_DIR'}.'/apicert.pem'; } my $opts_default = { host => '127.0.0.1', port => 1443, auth_user => 'administrator', auth_pwd => 'administrator', verbose => 0, sslverify => 'no', admin => 0, crt_path => $default_crt_path }; sub _get_id { my ($baseurl, $location) = @_; my $id; ($id) = ($location =~ m/\Q$baseurl\E(.+)/); return $id; } sub new { my ($class, $opts) = @_; my $self = {}; $self->{opts} = merge($opts, $opts_default); bless $self, $class; return $self; } sub opts { my $self = shift; if (@_) { $self->{opts} = shift; } return $self->{opts}; } sub do_request { my $self = shift; my $ua = shift; my $url = shift; my $data = shift; my $req_type = shift || 'POST'; my $ct = 'application/json'; if($req_type =~ 'PATCH') { $ct = 'application/json-patch+json'; } my $req = HTTP::Request->new($req_type, $url); $req->header('Content-Type' => $ct); $req->header('Prefer' => 'return=representation'); $req->content(JSON::to_json($data)); my $res = $ua->request($req); if(!$res->is_success) { print "$url\n"; if($data) { print Dumper $data unless $self->{opts}->{verbose}; } } return $res; } sub _do_binary_request { my ($self, $ua, $url, $filename, $ct) = @_; my $content; my $req = HTTP::Request->new('POST', $url); $req->header('Content-Type' => $ct); $req->header('Prefer' => 'return=representation'); if(! -f $filename) { die "$filename not found\n"; } my $data_ref; read_file($filename, buf_ref => \$data_ref); $req->content(${data_ref}); my $res = $ua->request($req); if(!$res->is_success) { print "$url\n"; } return $res; } sub do_query { my $self = shift; my $ua = shift; my $url = shift; my $data = shift; my $req_type = shift || 'GET'; my $URL = URI->new($url); $URL->query_form($data); my $req = HTTP::Request->new($req_type, $URL); my $res = $ua->request($req); if(!$res->is_success) { print "$url\n"; if($data) { print Dumper $data unless $self->{opts}->{verbose}; } } return $res; } sub _fetch_cert { my ($self, $ua, $urlbase) = @_; my $res = $ua->post( $urlbase . '/api/admincerts/', Content_Type => 'application/json', Content => '{}' ); unless($res->is_success) { die "failed to fetch client certificate: " . $res->status_line . "\n"; } my $zip = $res->decoded_content; my $z = IO::Uncompress::Unzip->new(\$zip, MultiStream => 0, Append => 1); my $data; while(!$z->eof() && (my $hdr = $z->getHeaderInfo())) { unless($hdr->{Name} =~ /\.pem$/) { # wrong file, just read stream, clear buffer and try next while($z->read($data) > 0) {} $data = undef; $z->nextStream(); next; } while($z->read($data) > 0) {} last; } $z->close(); unless($data) { die "failed to find PEM file in client certificate zip file\n"; } open my $fh, ">:raw", $self->{opts}->{crt_path} or die "failed to open " . $self->{opts}->{crt_path} . ": $!\n"; print { $fh } $data; close $fh; } sub create_ua { my ($self, $urlbase) = @_; my $ua = LWP::UserAgent->new(); if($self->{opts}->{sslverify} eq 'no') { $ua->ssl_opts( verify_hostname => 0, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE, ); } $ua->credentials( $self->{opts}->{host}.':'.$self->{opts}->{port}, 'api_admin_http', $self->{opts}->{auth_user}, $self->{opts}->{auth_pwd} ); # debug!! if($self->{opts}->{verbose}) { $ua->show_progress(1); $ua->add_handler("request_send", sub { shift->dump; return }); $ua->add_handler("response_done", sub { shift->dump; return }); } unless (-f $self->{opts}->{crt_path}) { $self->_fetch_cert($ua, $urlbase); } $ua->ssl_opts( SSL_cert_file => $self->{opts}->{crt_path}, SSL_key_file => $self->{opts}->{crt_path}, ); return $ua; } sub _create { my ($self, $data, $urldata) = @_; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->do_request($ua, $urlbase.$urldata, $data); if($res->is_success) { if($self->{opts}->{verbose}) { print $res->status_line . ' ' . $res->header('Location') . "\n"; } return _get_id($urldata, $res->header('Location')); } else { die $res->as_string; } return; } sub _delete { my ($self, $urldata) = @_; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->do_query($ua, $urlbase.$urldata, undef, 'DELETE'); return $res->is_success; } sub _get_content { my ($self, $data, $urldata) = @_; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->do_query($ua, $urlbase.$urldata, $data); if($res->is_success) { return JSON::from_json( $res->decoded_content ); } else { die $res->as_string; } return; } sub _set_content { my ($self, $data, $urldata) = @_; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->do_request($ua, $urlbase.$urldata, $data, 'PUT'); if($res->is_success) { return JSON::from_json( $res->decoded_content ); } else { die $res->as_string; } return; } sub _post_content { my ($self, $data, $urldata) = @_; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->do_request($ua, $urlbase.$urldata, $data, 'POST'); if($res->is_success) { return $res->status_line #return JSON::from_json( $res->decoded_content ); } else { die $res->as_string; } return; } sub _exists { my ($self, $data, $urldata, $collection_id) = @_; # remove empty values foreach (keys %{$data}) { delete $data->{$_} unless $data->{$_}; } my $collection = $self->_get_content($data, $urldata); if (defined $collection && $collection->{total_count} == 1) { my $tmp = $collection->{_embedded}->{$collection_id}; my $links; if (ref $tmp eq 'ARRAY') { $links = @{$tmp}[0]->{_links}; } else { $links = $tmp->{_links}; } my $href = $links->{self}->{href}; return _get_id($urldata, $href); } return; } sub check_contact_exists { my ($self, $data, $type) = @_; my $urldata = "/api/${type}contacts/"; my $collection_id = "ngcp:${type}contacts"; return $self->_exists($data, $urldata, $collection_id); } sub create_contact { my ($self, $data, $type) = @_; my $urldata = "/api/${type}contacts/"; return $self->_create($data, $urldata); } sub check_contract_exists { my ($self, $data) = @_; my $urldata = '/api/contracts/'; my $collection_id = 'ngcp:contracts'; return $self->_exists($data, $urldata, $collection_id); } sub create_contract { my ($self, $data) = @_; my $urldata = '/api/contracts/'; return $self->_create($data, $urldata); } sub check_reseller_exists { my ($self, $data) = @_; my $urldata = '/api/resellers/'; my $collection_id = 'ngcp:resellers'; return $self->_exists($data, $urldata, $collection_id); } sub create_reseller { my ($self, $data) = @_; my $urldata = '/api/resellers/'; return $self->_create($data, $urldata); } sub get_domains { my ($self, $data) = @_; my $urldata = "/api/domains/"; my $collection_id = 'ngcp:domains'; my $collection = $self->_get_content(undef, $urldata); return $collection->{_embedded}->{$collection_id}; } sub check_domain_exists { my ($self, $data) = @_; my $urldata = "/api/domains/"; my $collection_id = 'ngcp:domains'; return $self->_exists($data, $urldata, $collection_id); } sub get_domain_preferences { my ($self, $id) = @_; my $urldata = "/api/domainpreferences/${id}"; my $collection_id = 'ngcp:domainpreferences'; return $self->_get_content(undef, $urldata); } sub set_domain_preferences { my ($self, $id, $data) = @_; my $urldata = "/api/domainpreferences/${id}"; my $collection_id = 'ngcp:domainpreferences'; return $self->_set_content($data, $urldata); } sub create_domain { my ($self, $data) = @_; my $urldata = '/api/domains/'; return $self->_create($data, $urldata); } sub delete_domain { my ($self, $id) = @_; my $urldata = "/api/domains/${id}"; return $self->_delete($urldata); } sub check_customer_exists { my ($self, $data) = @_; my $urldata = '/api/customers/'; my $collection_id = 'ngcp:customers'; return $self->_exists($data, $urldata, $collection_id); } sub create_customer { my ($self, $data) = @_; my $urldata = '/api/customers/'; return $self->_create($data, $urldata); } sub check_subscriber_exists { my ($self, $data) = @_; my $urldata = '/api/subscribers/'; my $collection_id = 'ngcp:subscribers'; return $self->_exists($data, $urldata, $collection_id); } sub get_subscriber { my ($self, $id) = @_; my $urldata = "/api/subscribers/${id}"; return $self->_get_content(undef, $urldata); } sub get_subscriber_preferences { my ($self, $id) = @_; my $urldata = "/api/subscriberpreferences/${id}"; my $collection_id = 'ngcp:subscriberpreferences'; return $self->_get_content(undef, $urldata); } sub set_subscriber_preferences { my ($self, $id, $data) = @_; my $urldata = "/api/subscriberpreferences/${id}"; my $collection_id = 'ngcp:subscriberpreferences'; return $self->_set_content($data, $urldata); } sub set_subscriber_speeddial { my ($self, $id, $data) = @_; my $urldata = "/api/speeddials/${id}"; my $collection_id = 'ngcp:speeddials'; return $self->_set_content($data, $urldata); } sub get_subscriber_speeddial { my ($self, $id) = @_; my $urldata = "/api/speeddials/${id}"; my $collection_id = 'ngcp:speeddials'; return $self->_get_content(undef, $urldata); } sub set_subscriber_callforward { my ($self, $id, $data) = @_; my $urldata = "/api/callforwards/${id}"; my $collection_id = 'ngcp:callforwards'; return $self->_set_content($data, $urldata); } sub get_subscriber_callforward { my ($self, $id) = @_; my $urldata = "/api/callforwards/${id}"; my $collection_id = 'ngcp:callforwards'; return $self->_get_content(undef, $urldata); } sub set_subscriber_voicemailsettings { my ($self, $id, $data) = @_; my $urldata = "/api/voicemailsettings/${id}"; my $collection_id = 'ngcp:voicemailsettings'; return $self->_set_content($data, $urldata); } sub get_subscriber_voicemailsettings { my ($self, $id) = @_; my $urldata = "/api/voicemailsettings/${id}"; my $collection_id = 'ngcp:voicemailsettings'; return $self->_get_content(undef, $urldata); } sub set_subscriber_cf_destinationset { my ($self, $id, $data) = @_; my $urldata = "/api/cfdestinationsets/"; my $collection_id = 'ngcp:cfdestinationsets'; return $self->_post_content($data, $urldata); } sub get_subscriber_cf_destinationset { my ($self, $id) = @_; my $urldata = "/api/cfdestinationsets/${id}"; my $collection_id = 'ngcp:cfdestinationsets'; return $self->_get_content(undef, $urldata); } sub set_subscriber_cf_sourceset { my ($self, $id, $data) = @_; my $urldata = "/api/cfsourcesets/"; my $collection_id = 'ngcp:cfsourcesets'; return $self->_post_content($data, $urldata); } sub get_subscriber_cf_sourceset { my ($self, $id) = @_; my $urldata = "/api/cfsourcesets/${id}"; my $collection_id = 'ngcp:cfsourcesets'; return $self->_get_content(undef, $urldata); } sub set_subscriber_cf_bnumberset { my ($self, $id, $data) = @_; my $urldata = "/api/cfbnumbersets/"; my $collection_id = 'ngcp:cfbnumbersets'; return $self->_post_content($data, $urldata); } sub get_subscriber_cf_bnumberset { my ($self, $id) = @_; my $urldata = "/api/cfbnumbersets/${id}"; my $collection_id = 'ngcp:cfbnumbersets'; return $self->_get_content(undef, $urldata); } sub set_subscriber_cf_timeset { my ($self, $id, $data) = @_; my $urldata = "/api/cftimesets/"; my $collection_id = 'ngcp:cftimesets'; return $self->_post_content($data, $urldata); } sub get_subscriber_cf_timeset { my ($self, $id) = @_; my $urldata = "/api/cftimesets/${id}"; my $collection_id = 'ngcp:cftimesets'; return $self->_get_content(undef, $urldata); } sub set_subscriber_cf_mapping { my ($self, $id, $data) = @_; my $urldata = "/api/cfmappings/${id}"; my $collection_id = 'ngcp:cfmappings'; return $self->_set_content($data, $urldata); } sub get_subscriber_cf_mapping { my ($self, $id) = @_; my $urldata = "/api/cfmappings/${id}"; my $collection_id = 'ngcp:cfmappings'; return $self->_get_content(undef, $urldata); } sub set_subscriber_trusted_sources { my ($self, $id, $data) = @_; my $urldata = "/api/trustedsources/"; my $collection_id = 'ngcp:trustedsources'; return $self->_post_content($data, $urldata); } sub get_subscriber_trusted_sources { my ($self, $id) = @_; my $urldata = "/api/trustedsources/${id}"; my $collection_id = 'ngcp:trustedsources'; return $self->_get_content(undef, $urldata); } sub check_subscriber_registration_exists { my ($self, $data) = @_; my $urldata = '/api/subscriberregistrations/'; my $collection_id = 'ngcp:subscriberregistrations'; return $self->_exists($data, $urldata, $collection_id); } sub create_subscriber_registration { my ($self, $data) = @_; my $urldata = '/api/subscriberregistrations/'; return $self->_create($data, $urldata); } sub get_subscriber_registration { my ($self, $id) = @_; my $urldata = "/api/subscriberregistrations/${id}"; my $collection_id = 'ngcp:subscriberregistrations'; return $self->_get_content(undef, $urldata); } sub get_subscriber_registrations { my ($self, $subs_id) = @_; my $urldata = '/api/subscriberregistrations/'; my $collection_id = 'ngcp:subscriberregistrations'; my $collection = $self->_get_content({subscriber_id=>$subs_id}, $urldata); my $res = []; if (defined $collection && $collection->{total_count} > 0) { return $collection->{_embedded}->{$collection_id}; } return $res; } sub set_subscriber_registration { my ($self, $id, $data) = @_; my $urldata = "/api/subscriberregistrations/${id}"; my $collection_id = 'ngcp:subscriberregistrations'; return $self->_set_content($data, $urldata); } sub delete_subscriber_registration { my ($self, $subs_id) = @_; my $urldata = '/api/subscriberregistrations/'; my $collection_id = 'ngcp:subscriberregistrations'; my $collection = $self->_get_content(undef, $urldata); my $count = 0; if (defined $collection && $collection->{total_count} > 0) { my $data = $collection->{_embedded}->{$collection_id}; foreach my $r (@{$data}) { if ($r->{subscriber_id} eq $subs_id) { if($self->_delete(${urldata}.$r->{id})) { $count++; } } } } return $count; } sub create_subscriber { my ($self, $data) = @_; my $urldata = '/api/subscribers/'; return $self->_create($data, $urldata); } sub check_rewriterule_exists { my ($self, $data) = @_; my $urldata = '/api/rewriterules/'; my $collection_id = 'ngcp:rewriterules'; return $self->_exists($data, $urldata, $collection_id); } sub create_rewriterule { my ($self, $data) = @_; my $urldata = '/api/rewriterules/'; return $self->_create($data, $urldata); } sub check_rewriteruleset_exists { my ($self, $data) = @_; my $urldata = '/api/rewriterulesets/'; my $collection_id = 'ngcp:rewriterulesets'; return $self->_exists($data, $urldata, $collection_id); } sub create_rewriteruleset { my ($self, $data) = @_; my $urldata = '/api/rewriterulesets/'; return $self->_create($data, $urldata); } sub delete_rewriteruleset { my ($self, $id) = @_; my $urldata = "/api/rewriterulesets/${id}"; return $self->_delete($urldata); } sub check_headerrulecondition_exists { my ($self, $data) = @_; my $urldata = '/api/headerruleconditions/'; my $collection_id = 'ngcp:headerruleconditions'; return $self->_exists($data, $urldata, $collection_id); } sub create_headerrulecondition { my ($self, $data) = @_; my $urldata = '/api/headerruleconditions/'; return $self->_create($data, $urldata); } sub check_headerruleaction_exists { my ($self, $data) = @_; my $urldata = '/api/headerruleactions/'; my $collection_id = 'ngcp:headerruleactions'; return $self->_exists($data, $urldata, $collection_id); } sub create_headerruleaction { my ($self, $data) = @_; my $urldata = '/api/headerruleactions/'; return $self->_create($data, $urldata); } sub check_headerrule_exists { my ($self, $data) = @_; my $urldata = '/api/headerrules/'; my $collection_id = 'ngcp:headerrules'; return $self->_exists($data, $urldata, $collection_id); } sub create_headerrule { my ($self, $data) = @_; my $urldata = '/api/headerrules/'; return $self->_create($data, $urldata); } sub check_headerruleset_exists { my ($self, $data) = @_; my $urldata = '/api/headerrulesets/'; my $collection_id = 'ngcp:headerrulesets'; return $self->_exists($data, $urldata, $collection_id); } sub create_headerruleset { my ($self, $data) = @_; my $urldata = '/api/headerrulesets/'; return $self->_create($data, $urldata); } sub delete_headerruleset { my ($self, $id) = @_; my $urldata = "/api/headerrulesets/${id}"; return $self->_delete($urldata); } sub check_peeringgroup_exists { my ($self, $data) = @_; my $urldata = '/api/peeringgroups/'; my $collection_id = 'ngcp:peeringgroups'; return $self->_exists($data, $urldata, $collection_id); } sub create_peeringgroup { my ($self, $data) = @_; my $urldata = '/api/peeringgroups/'; return $self->_create($data, $urldata); } sub delete_peeringgroup { my ($self, $id) = @_; my $urldata = "/api/peeringgroups/${id}"; return $self->_delete($urldata); } sub check_peeringserver_exists { my ($self, $data) = @_; my $urldata = '/api/peeringservers/'; my $collection_id = 'ngcp:peeringservers'; return $self->_exists($data, $urldata, $collection_id); } sub get_peeringserver_preferences { my ($self, $id) = @_; my $urldata = "/api/peeringserverpreferences/${id}"; my $collection_id = 'ngcp:peeringserverpreferences'; return $self->_get_content(undef, $urldata); } sub set_peeringserver_preferences { my ($self, $id, $data) = @_; my $urldata = "/api/peeringserverpreferences/${id}"; my $collection_id = 'ngcp:peeringserverpreferences'; return $self->_set_content($data, $urldata); } sub create_peeringserver { my ($self, $data) = @_; my $urldata = '/api/peeringservers/'; return $self->_create($data, $urldata); } sub set_peeringserver { my ($self, $id, $data) = @_; my $urldata = "/api/peeringservers/${id}"; my $collection_id = 'ngcp:peeringservers'; return $self->_set_content($data, $urldata); } sub get_peeringserver { my ($self, $id) = @_; my $urldata = "/api/peeringservers/${id}"; my $collection_id = 'ngcp:peeringservers'; return $self->_get_content(undef, $urldata); } sub delete_peeringserver { my ($self, $id) = @_; my $urldata = "/api/peeringservers/${id}"; return $self->_delete($urldata); } sub check_peeringrule_exists { my ($self, $data) = @_; my $urldata = '/api/peeringrules/'; my $collection_id = 'ngcp:peeringrules'; return $self->_exists($data, $urldata, $collection_id); } sub create_peeringrule { my ($self, $data) = @_; my $urldata = '/api/peeringrules/'; return $self->_create($data, $urldata); } sub delete_peeringrule { my ($self, $id) = @_; my $urldata = "/api/peeringrules/${id}"; return $self->_delete($urldata); } sub check_peeringinboundrule_exists { my ($self, $data) = @_; my $urldata = '/api/peeringinboundrules/'; my $collection_id = 'ngcp:peeringinboundrules'; return $self->_exists($data, $urldata, $collection_id); } sub create_peeringinboundrule { my ($self, $data) = @_; my $urldata = '/api/peeringinboundrules/'; return $self->_create($data, $urldata); } sub delete_peeringinboundrule { my ($self, $id) = @_; my $urldata = "/api/peeringinboundrules/${id}"; return $self->_delete($urldata); } sub check_ncoslevel_exists { my ($self, $data) = @_; my $urldata = "/api/ncoslevels/"; my $collection_id = 'ngcp:ncoslevels'; return $self->_exists($data, $urldata, $collection_id); } sub create_ncoslevel { my ($self, $data) = @_; my $urldata = '/api/ncoslevels/'; return $self->_create($data, $urldata); } sub delete_ncoslevel { my ($self, $id) = @_; my $urldata = "/api/ncoslevels/${id}"; return $self->_delete($urldata); } sub check_ncospattern_exists { my ($self, $data) = @_; my $urldata = "/api/ncospatterns/"; my $collection_id = 'ngcp:ncospatterns'; return $self->_exists($data, $urldata, $collection_id); } sub create_ncospattern { my ($self, $data) = @_; my $urldata = '/api/ncospatterns/'; return $self->_create($data, $urldata); } sub delete_ncospattern { my ($self, $id) = @_; my $urldata = "/api/ncospatterns/${id}"; return $self->_delete($urldata); } sub check_lnpcarrier_exists { my ($self, $data) = @_; my $urldata = "/api/lnpcarriers/"; my $collection_id = 'ngcp:lnpcarriers'; return $self->_exists($data, $urldata, $collection_id); } sub create_lnpcarrier { my ($self, $data) = @_; my $urldata = '/api/lnpcarriers/'; return $self->_create($data, $urldata); } sub delete_lnpcarrier { my ($self, $id) = @_; my $urldata = "/api/lnpcarriers/${id}"; return $self->_delete($urldata); } sub check_lnpnumber_exists { my ($self, $data) = @_; my $urldata = "/api/lnpnumbers/"; my $collection_id = 'ngcp:lnpnumbers'; return $self->_exists($data, $urldata, $collection_id); } sub create_lnpnumber { my ($self, $data) = @_; my $urldata = '/api/lnpnumbers/'; return $self->_create($data, $urldata); } sub delete_lnpnumber { my ($self, $id) = @_; my $urldata = "/api/lnpnumbers/${id}"; return $self->_delete($urldata); } sub check_ncoslnpcarrier_exists { my ($self, $data) = @_; my $urldata = "/api/ncoslnpcarriers/"; my $collection_id = 'ngcp:ncoslnpcarriers'; return $self->_exists($data, $urldata, $collection_id); } sub create_ncoslnpcarrier { my ($self, $data) = @_; my $urldata = '/api/ncoslnpcarriers/'; return $self->_create($data, $urldata); } sub delete_ncoslnpcarrier { my ($self, $id) = @_; my $urldata = "/api/ncoslnpcarriers/${id}"; return $self->_delete($urldata); } sub create_ncoslnppattern { my ($self, $data) = @_; my $urldata = '/api/ncoslnppatterns/'; return $self->_create($data, $urldata); } sub check_soundset_exists { my ($self, $data) = @_; my $urldata = "/api/soundsets/"; my $collection_id = 'ngcp:soundsets'; return $self->_exists($data, $urldata, $collection_id); } sub create_soundset { my ($self, $data) = @_; my $urldata = '/api/soundsets/'; return $self->_create($data, $urldata); } sub delete_soundset { my ($self, $id) = @_; my $urldata = "/api/soundsets/${id}"; return $self->_delete($urldata); } sub upload_soundfile { my ($self, $data, $filepath) = @_; my $urldata = "/api/soundfiles/?". "filename=$data->{filename}&handle=$data->{handle}". "&set_id=$data->{set_id}&loopplay=$data->{loopplay}"; my $urlbase = 'https://'.$self->{opts}->{host}.':'.$self->{opts}->{port}; my $ua = $self->create_ua($urlbase); my $res = $self->_do_binary_request($ua, $urlbase.$urldata, $filepath, 'audio/x-wav'); if(! $res->is_success) { die $res->as_string; } return _get_id("/api/soundfiles/", $res->header('Location')); } sub delete_banneduser { my ($self, $id) = @_; my $urldata = "/api/bannedusers/${id}"; return $self->_delete($urldata); } sub create_locationmapping { my ($self, $data) = @_; my $urldata = '/api/subscriberlocationmappings/'; return $self->_create($data, $urldata); } sub check_emergencymappingcontainer_exists { my ($self, $data) = @_; my $urldata = '/api/emergencymappingcontainers/'; my $collection_id = 'ngcp:emergencymappingcontainers'; return $self->_exists($data, $urldata, $collection_id); } sub create_emergencymappingcontainer { my ($self, $data) = @_; my $urldata = '/api/emergencymappingcontainers/'; return $self->_create($data, $urldata); } sub set_emergencymappingcontainer { my ($self, $id, $data) = @_; my $urldata = "/api/emergencymappingcontainers/${id}"; my $collection_id = 'ngcp:emergencymappingcontainers'; return $self->_set_content($data, $urldata); } sub get_emergencymappingcontainer { my ($self, $id) = @_; my $urldata = "/api/emergencymappingcontainers/${id}"; my $collection_id = 'ngcp:emergencymappingcontainers'; return $self->_get_content(undef, $urldata); } sub delete_emergencymappingcontainer { my ($self, $id) = @_; my $urldata = "/api/emergencymappingcontainers/${id}"; my $data = {"emergency_container_id" => $id}; my $mappings = $self->get_emergencymappings($data); foreach my $map (@{$mappings}) { $self->delete_emergencymapping($map->{id}); }; return $self->_delete($urldata); } sub create_emergencymapping { my ($self, $data) = @_; my $urldata = '/api/emergencymappings/'; return $self->_create($data, $urldata); } sub get_emergencymappings { my ($self, $data) = @_; my $urldata = "/api/emergencymappings/"; my $collection_id = 'ngcp:emergencymappings'; my $collection = $self->_get_content($data, $urldata); return $collection->{_embedded}->{$collection_id}; } sub delete_emergencymapping { my ($self, $id) = @_; my $urldata = "/api/emergencymappings/${id}"; return $self->_delete($urldata); } 1;