From 57134b4a18772b114a5559a1f19d033b01291f62 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 26 Feb 2009 15:28:31 +0000 Subject: [PATCH 1/1] initial import --- .cvsignore | 10 + Changes | 5 + MANIFEST | 10 + Makefile.PL | 17 ++ README | 43 ++++ lib/Net/Indosoft/Voicebridge.pm | 411 +++++++++++++++++++++++++++++++++++++++ t/00-load.t | 9 + t/01-Account_Client_Conference.t | 262 +++++++++++++++++++++++++ t/pod-coverage.t | 18 ++ t/pod.t | 12 ++ voicebridgeAPI.wsdl | 273 ++++++++++++++++++++++++++ 11 files changed, 1070 insertions(+) create mode 100644 .cvsignore create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100644 lib/Net/Indosoft/Voicebridge.pm create mode 100644 t/00-load.t create mode 100644 t/01-Account_Client_Conference.t create mode 100644 t/pod-coverage.t create mode 100644 t/pod.t create mode 100644 voicebridgeAPI.wsdl diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..a51d4a9 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,10 @@ +blib* +Makefile +Makefile.old +Build +_build* +pm_to_blib* +*.tar.gz +.lwpcookies +Net-Indosoft-Voicebridge-* +cover_db diff --git a/Changes b/Changes new file mode 100644 index 0000000..1d81eb0 --- /dev/null +++ b/Changes @@ -0,0 +1,5 @@ +Revision history for Net-Indosoft-Voicebridge + +0.01 unreleased + First version, released on an unsuspecting world. + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..4e493ed --- /dev/null +++ b/MANIFEST @@ -0,0 +1,10 @@ +Changes +MANIFEST +Makefile.PL +README +voicebridgeAPI.wsdl +lib/Net/Indosoft/Voicebridge.pm +t/00-load.t +t/01-Account_Client_Conference.t +t/pod-coverage.t +t/pod.t diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..1d536a0 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,17 @@ +use strict; +use warnings; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Net::Indosoft::Voicebridge', + AUTHOR => 'Ivan Kohler ', + VERSION_FROM => 'lib/Net/Indosoft/Voicebridge.pm', + ABSTRACT_FROM => 'lib/Net/Indosoft/Voicebridge.pm', + PL_FILES => {}, + PREREQ_PM => { + 'Test::More' => 0, + 'SOAP::Lite' => 0, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Net-Indosoft-Voicebridge-*' }, +); diff --git a/README b/README new file mode 100644 index 0000000..f6a8bd8 --- /dev/null +++ b/README @@ -0,0 +1,43 @@ +Net-Indosoft-Voicebridge + +This is an interface to the Indosoft Voicebridge API. It is only useful if you +have an account with Indosoft to resell confernce bridge service. + +INSTALLATION + +To install this module, run the following commands: + + perl Makefile.PL + make + make test + make install + +SUPPORT AND DOCUMENTATION + +After installing, you can find documentation for this module with the +perldoc command. + + perldoc Net::Indosoft::Voicebridge + +You can also look for information at: + + RT, CPAN's request tracker + http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Indosoft-Voicebridge + + AnnoCPAN, Annotated CPAN documentation + http://annocpan.org/dist/Net-Indosoft-Voicebridge + + CPAN Ratings + http://cpanratings.perl.org/d/Net-Indosoft-Voicebridge + + Search CPAN + http://search.cpan.org/dist/Net-Indosoft-Voicebridge + + +COPYRIGHT AND LICENCE + +Copyright (C) 2009 Freeside Internet Services, Inc. + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + diff --git a/lib/Net/Indosoft/Voicebridge.pm b/lib/Net/Indosoft/Voicebridge.pm new file mode 100644 index 0000000..e493af2 --- /dev/null +++ b/lib/Net/Indosoft/Voicebridge.pm @@ -0,0 +1,411 @@ +package Net::Indosoft::Voicebridge; + +use warnings; +use strict; +use Data::Dumper; +use SOAP::Lite; + +our $AUTOLOAD; +our $DEBUG = 1; + +=head1 NAME + +Net::Indosoft::Voicebridge - Interface to Indosoft Voicebridge API + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '0.01'; + +=head1 SYNOPSYS + + use Net::Indosoft::Voicebridge; + + my $handle = Net::GlobalPOPs::MediaServicesAPI->new( + 'url' => 'http://your_tag.kanobe.net:8080/vbsoap/voicebridgeAPI.php', + ); + +=head1 METHODS + +=head2 new + +Creates a new Net::Indosoft::Voicebridge object. + +=cut + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = ref($_[0]) ? shift : { @_ }; + +# my $soap = new SOAP::Lite ( +# 'service' => $URL.'?wsdl', +# ); +# $self->{soap} = $soap; + + bless($self, $class); +} + +#ideally this could be retreived from the WSDL, but hey +# or at least derived from the method name? +our %requestobj = ( + 'addAccount' => 'Account', + 'modifyAccount' => 'Account', + 'addClient' => 'Client', + 'modifyClient' => 'Client', + 'addConference' => 'Conference', + 'modifyConference' => 'Conference', +); + +#this is think they're just on crack. returnning a string to parse inside +#a ton of XML? somehow that misses the point. +our %returnparse = ( + 'addAccount' => [ qw( account_id ) ], + 'modifyAccount' => [ qw( account_id ) ], + 'addClient' => [ qw( client_id ) ], + 'modifyClient' => [ qw( client_id ) ], + 'addConference' => [ qw( conference_id moderator_pin participant_pin ) ], + 'modifyConference' => [ qw( conference_id ) ], +); + +sub AUTOLOAD { + my $self = shift; + + $AUTOLOAD =~ /(^|::)(\w+)$/ or die "unparsable AUTOLOAD: $AUTOLOAD"; + my $function = $2; + return if $function eq 'DESTROY'; + + my $uri = "voicebridgeAPI/$function"; + + + my $soap = SOAP::Lite +# -> readable(1) + -> proxy($self->{url}) +# -> on_action( sub { join '/', @_ } ) #according to the wsdl, right? +# -> on_action( sub { "urn:voicebridgeAPI/$function" } ) + -> autotype(0) +# -> default_ns("urn:voicebridgeAPI") + ; + + my $request; + my $obj = $requestobj{$function}; + if ( $obj ) { + + my $opts = ref($_[0]) ? shift : { @_ }; + if ( $DEBUG > 1 ) { + warn "$_: ". $opts->{$_}. "\n" foreach keys %$opts; + } + + $request = SOAP::Data->name( $obj => + \SOAP::Data->value( + map SOAP::Data->name( $_ )->value( $opts->{$_} ), keys %$opts + ) + ); + + } else { + + $request = shift; + + } + + my $som = $soap->call( $function, $request ); + + die $som->faultstring if $som->fault; + return { 'error' => $som->faultdetail } if $som->fault; + + warn Dumper($som->body) if $DEBUG > 1; + + my $return = $som->valueof("//${function}Response/return"); + + if ( $return =~ /^deserialize($return); + my @errors = $rsom->valueof('//errors/error'); + return { 'error' => join(' / ', @errors ) } if @errors; + } + + if ( $function =~ /^delete/ && $return !~ /Deleted Success?fully/i ) { + return { 'error' => 'Deletion unsuccessful', + 'return' => $return, + }; + } + + my %return = ( 'return'=>$return ); + foreach my $rp ( @{ $returnparse{$function} || [] } ) { + #are they always numeric? + $return =~ /\W$rp\s*=\s*(\d+)/ and $return{$rp} = $1; + } + + return \%return; +} + +=head2 addAccount + +Pass a list of key=>value pairs or a hash reference: + +i.account_name: Required Field: Alpha Numeric +ii.account_desc: Alpha Numeric +iii.account_addr: Alpha Numeric +iv.account_city: Alpha Numeric +v.account_state: Alpha Numeric +vi.account_country: Alpha Numeric +vii.account_zip: Alpha Numeric +viii.account_phone: Required Field: Alpha Numeric Ex: 123-123-1234 +ix.account_fax: Alpha Numeric +x.account_email: Required Field, have to be in valid email format +xi.account_password: Required Field: Alpha Numeric + +Returns a hash reference with one element, either 'error' for error conditions, +or 'account_id' if the account is created sucessfully. + +=head2 modifyAccount + +Pass a list of key=>value pairs or a hash reference: + +xiv.account_id: Required Field (Provided when the account was created) +xv.account_name: Required Field +xvi.account_desc +xvii.account_addr +xviii.account_city +xix.account_state +xx.account_country +xxi.account_zip +xxii.account_phone: Required Field +xxiii.account_fax +xxiv.account_email: Required Field +xxv.account_password: Required Field + +Returns a hash reference with one element, either 'error' for error conditions, +or 'account_id' if the account is modified sucessfully. + +=head2 addClient + +Pass a list of key=>value pairs or a hash reference: + +account_id: Required Field Alpha Numeric +client_contact_name: Required Field Alpha Numeric +client_contact_addr Alpha Numeric +client_contact_city Alpha Numeric +client_contact_state Alpha Numeric +client_contact_country Alpha Numeric +client_contact_zip Alpha Numeric +client_contact_phone: Required Field Alpha Numeric +client_contact_fax Alpha Numeric +client_contact_email: Required Field Alpha Numeric +client_contact_password: Required Field Alpha Numeric + +Returns a hash reference with one element, either 'error' for error conditions, +or 'client_id' if the account is created sucessfully. + +=head2 modifyClient + +Pass a list of key=>value pairs or a hash reference: + +client_id: Required Field +account_id: Required Field +client_contact_name: Required Field +client_contact_addr +client_contact_city +client_contact_state +client_contact_country +client_contact_zip +client_contact_phone: Required Field +client_contact_fax +client_contact_email: Required Field +client_contact_password: Required Field + +Returns a hash reference with one element, either 'error' for error conditions, +or 'client_id' if the account is modified sucessfully. + +=head2 addConference + +Pass a list of key=>value pairs or a hash reference: + +client_id: Required Field Alpha Numeric (Required to associate conference to client, client ID provided when new client is added) +conference_name: Required Field Alpha Numeric +conference_desc Alpha Numeric +start_time: Required Field Alpha Numeric +moderated_flag: +1 ¿ Presentation mode +0 ¿ Conversation Mode +entry_ann_flag: Integer +0 ¿ None +1 - Tone +2 - Name +record_flag: Integer +0 ¿ Stop Recording +1 ¿ Start Recording +moh_flag: Integer +0 ¿ Stop MOH +1 ¿ Start MOH +talk_detect_flag +play_user_cnt_flag: Integer +1- Announce number of conference members currently in conference +0 ¿ no Announcement +wait_for_admin_flag: Integer +1 - Only start conference once admin enters +0 ¿ all users without admin +stop_on_admin_exit_flag: Integer +1 - End conference when admin exits: +0 - No +second_pin_flag: Integer +1 - Prompt conference members for a second pin/password when logging in? +0 - No Extra conference PIN +secondary_pin: Integer +If second_pin_flag is 1 also pass the PIN +allow_sub_conf: Integer +1 ¿ Allow sub conference for this conference +0 ¿ Donot Allow sub conference +duration: Integer +Duration in minutes e.g 30 for 30 minutes +conference_type: reservationless/reserved + +On errors, returns a hash reference with one element, 'error', otherwise +returns a hash reference with the following keys: conference_id, moderator_pin +and participant_pin. + +=head2 modifyConference + +Pass a list of key=>value pairs or a hash reference: + +conference_id: Required Field +client_id: Required Field +conference_name: Required Field +conference_desc +start_time: Required Field +moderated_flag: +1 ¿ Presentation mode +0 ¿ Conversation Mode +entry_ann_flag: Integer +0 ¿ None +1 - Tone +2 - Name +record_flag: Integer +0 ¿ Stop Recording +1 ¿ Start Recording +moh_flag: Integer +0 ¿ Stop MOH +1 ¿ Start MOH +play_user_cnt_flag: Integer +1- Announce number of conference members currently in conference +0 ¿ no Announcement +wait_for_admin_flag: Integer +1 - Only start conference once admin enters +0 ¿ all users without admin +stop_on_admin_exit_flag: Integer +1 - End conference when admin exits: +0 - No +second_pin_flag: Integer +1 - Prompt conference members for a second pin/password when logging in? +0 - No Extra conference PIN +secondary_pin: Integer +If second_pin_flag is 1 also pass the PIN +allow_sub_conf: Integer +1 ¿ Allow sub conference for this conference +0 ¿ Donot Allow sub conference +duration: Integer +Duration in minutes e.g 30 for 30 minutes + +Returns a hash reference with one element, either 'error' for error conditions, +or 'conference_id' if the conference is modified sucessfully. + +=head2 deleteAccount + +Pass a list of key=>value pairs or a hash reference: + +i.account_id: Required Field + +On errors, should returns a hash reference with one element, 'error'. + +=head2 deleteClient + +Pass a list of key=>value pairs or a hash reference: + +ii.client_id: Required Field + +On errors, should returns a hash reference with one element, 'error'. + +=head2 deleteConference + +Pass a list of key=>value pairs or a hash reference: + +iii.conference_id: Required Field + +On errors, should returns a hash reference with one element, 'error'. + +=head1 The services below are not yet documented/online + +=head2 addConferencePIN + +=head2 modifyConferencePIN + +=head2 deleteConferencePIN + +=head2 addDNIS + +=head2 modifyDNIS + +=head2 deleteDNIS + +=head1 AUTHOR + +Ivan Kohler, C<< >> + +=head1 BUGS + +Please report any bugs or feature requests to C, or through +the web interface at L. I will be notified, and then you'll +automatically be notified of progress on your bug as I make changes. + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Net::Indosoft::Voicebridge + +You can also look for information at: + +=over 4 + +=item * RT: CPAN's request tracker + +L + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * Search CPAN + +L + +=back + +=head1 ACKNOWLEDGEMENTS + +This module was developed by Freeside Internet Services, Inc. +If you need a complete, open-source web-based application to manage your +customers, conferences, billing and trouble ticketing, please visit +http://freeside.biz/ + +Development sponsored by NxxTcom Conferencing. If you need a cost-effective +voice, web or video conference, please visit http://www.nxxtcom.net/ + +=head1 COPYRIGHT & LICENSE + +Copyright (c) 2009 Freeside Internet Services, Inc. +All rights reserved. + +This program is free software; you can redistribute it and/or modify it +under the same terms as Perl itself. + +=cut + +1; + diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..860081a --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,9 @@ +#!perl -T + +use Test::More tests => 1; + +BEGIN { + use_ok( 'Net::Indosoft::Voicebridge' ); +} + +diag( "Testing Net::Indosoft::Voicebridge $Net::Indosoft::Voicebridge::VERSION, Perl $], $^X" ); diff --git a/t/01-Account_Client_Conference.t b/t/01-Account_Client_Conference.t new file mode 100644 index 0000000..21effd9 --- /dev/null +++ b/t/01-Account_Client_Conference.t @@ -0,0 +1,262 @@ +#!perl + +use Test::More; + +open URL, "t/URL" + or do { plan 'skip_all' => 'Put your URL in the t/URL file to test'; exit }; +chomp( my $URL = scalar() ); + +plan tests => 6 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2; + +use Net::Indosoft::Voicebridge; + +my $vb = new Net::Indosoft::Voicebridge( 'url' => $URL ); + +my $return; + +# addAccount (6) + +$return = $vb->addAccount( + 'account_name' => 'aname', #i think this is more like a username + 'account_password' => 'test54', + + 'account_desc' => 'A test account', + + 'account_addr' => '1234 Test Lane', + 'account_city' => 'Testville', + 'account_state' => 'CA', + 'account_zip' => '54321', + 'account_country' => 'US', + + 'account_phone' => '415-555-1212', +# 'account_fax' => '415-555-1212', + 'account_email' => 'ivan-voicebridge-test@freeside.biz', +); + +ok( ! $return->{error}, 'addAccount successful' ) or warn $return->{error}; + +like($return->{account_id}, qr/^(\d+)$/, 'addAccount returned account_id'); + +my $account_id = $return->{account_id}; + +$return = $vb->addAccount( +); + +ok( $return->{error}, 'addAccount empty error test', ); + +like($return->{error}, qr/Please, fill in/, 'addAccount empty error test got expected error'); + +$return = $vb->addAccount( + #'account_name' => 'A. Name', + 'account_desc' => 'A test account', + 'account_addr' => '1234 Test Lane', + 'account_city' => 'Testville', + 'account_state' => 'CA', + 'account_zip' => '54321', + #'account_phone' => '415-555-1212', + 'account_fax' => '415-555-1212', + #'account_email' => 'ivan-voicebridge-test@freeside.biz', + #'account_password' => 'testing', +); + +ok( $return->{error}, 'addAccount bad data error test', ); + +like($return->{error}, qr/Please, fill in/, 'addAccount bad data error test got expected error'); + +# modifyAccount (2) + +$return = $vb->modifyAccount( + 'account_id' => $account_id, + 'account_name' => 'anewname', #i think this is more like a username + 'account_password' => 'test32', + + 'account_desc' => 'A modified test account', + + 'account_addr' => '5432 Test Lane', + 'account_city' => 'Test City', + 'account_state' => 'NY', + 'account_zip' => '12345', + 'account_country' => 'US', + + 'account_phone' => '212-555-1212', + 'account_fax' => '212-555-1212', + 'account_email' => 'ivan-voicebridge-test2@freeside.biz', +); + +ok( ! $return->{error}, 'modifyAccount successful' ) or warn $return->{error}; + +is($return->{account_id}, $account_id, 'modifyAccount returned account_id'); + +# addClient (2) + +$return = $vb->addClient( + 'account_id' => $account_id, + + 'client_contact_name' => 'Tofu Beast', + 'client_contact_password' => 'word54', + + 'client_contact_addr' => '5432 Test Lane Suite 11', + 'client_contact_city' => 'Test City', + 'client_contact_state' => 'NY', + 'client_contact_country' => 'US', + 'client_contact_zip' => '12345', + + 'client_contact_phone' => '212-555-1234', + 'client_contact_fax' => '212-555-1234', + 'client_contact_email' => 'ivan-voicebridge-test3@freeside.biz', + +); + +ok( ! $return->{error}, 'addClient successful' ) or warn $return->{error}; + +like($return->{client_id}, qr/^(\d+)$/, 'addClient returned client_id'); + +my $client_id = $return->{client_id}; + +# modifyClient (2) + +$return = $vb->modifyClient( + 'account_id' => $account_id, + 'client_id' => $client_id, + + 'client_contact_name' => 'Secret Agent X', + 'client_contact_password' => 'word32', + + 'client_contact_addr' => '1234 Test Lane Suite 55', + 'client_contact_city' => 'Testville', + 'client_contact_state' => 'CA', + 'client_contact_country' => 'US', + 'client_contact_zip' => '54321', + + 'client_contact_phone' => '415-555-1234', + 'client_contact_fax' => '415-555-1234', + 'client_contact_email' => 'ivan-voicebridge-test4@freeside.biz', + +); + +ok( ! $return->{error}, 'modifyClient successful' ) or warn $return->{error}; + +is($return->{client_id}, $client_id, 'modifyClient returned client_id'); + +# addConference (2) + +$return = $vb->addConference( + 'client_id' => $client_id, + 'conference_name' => 'Test Conference', + 'conference_desc' => 'Net Indosoft Voicebridge test', + 'start_time' => '2010-20-04 16:20:00', + #'moderated_flag' => 0, + #'entry_ann_flag' => 0 + #'record_flag' => 0 + #'moh_flag' => 0 + #'talk_detect_flag' => 0 + #'play_user_cnt_flag' => 0 + #'wait_for_admin' => 0 + #'stop_on_admin_exit' => 0 + #'second_pin' => 0 + #'secondary_pin' => 0, + #'allow_sub-conf' => 0, + #'duration' => 0, + #'conference_type' => 'reservation', #'reservationless', + +); + +ok( ! $return->{error}, 'addConference successful' ) or warn $return->{error}; + +like($return->{conference_id}, qr/^(\d+)$/, 'addConference returned conference_id'); + +my $conference_id = $return->{conference_id}; + +# modifyConference (2) + +$return = $vb->modifyConference( + 'conference_id' => $conference_id, + 'conference_name' => 'Modified Test Conference', + 'conference_desc' => 'Net Indosoft Voicebridge modify test', + 'start_time' => '2010-20-04 16:20:00', + 'moderated_flag' => 1, + #'entry_ann_flag' => 0 + #'record_flag' => 0 + #'moh_flag' => 0 + #'talk_detect_flag' => 0 + #'play_user_cnt_flag' => 0 + 'wait_for_admin' => 1 + #'stop_on_admin_exit' => 0 + #'second_pin' => 0 + #'secondary_pin' => 0, + #'allow_sub-conf' => 0, + #'duration' => 0, + #'conference_type' => 'reservation', #'reservationless', + +); + +ok( ! $return->{error}, 'modifyConference successful' ) or warn $return->{error}; + +is($return->{conference_id}, $conference_id, 'modifyConference returned conference_id') + or warn $return->{'return'}; + +# deleteConference (2) + +$return = $vb->deleteConference( + 'conference_id' => $conference_id, +); + +ok( ! $return->{error}, 'deleteConference successful' ) + or warn $return->{error}. "\n". $return->{return}. "\n"; + +TODO: { + + local $TODO = 'deleteConference always returns "Deleted successfully", even when nothing was'; + + $return = $vb->deleteConference( + 'conference_id' => '999999999', + ); + + ok( $return->{error}, 'deleteConference bad data error test' ) + ;#or warn $return->{return}; + +} + +# deleteClient (2) + +$return = $vb->deleteClient( + 'client_id' => $client_id, +); + +ok( ! $return->{error}, 'deleteClient successful' ) + or warn $return->{error}. "\n". $return->{return}. "\n"; + +TODO: { + + local $TODO = 'deleteClient always returns "Deleted successfully", even when nothing was'; + + $return = $vb->deleteClient( + 'client_id' => '999999999', + ); + + ok( $return->{error}, 'deleteClient bad data error test' ) + ;#or warn $return->{return}; + +} + +# deleteAccount (2) + +$return = $vb->deleteAccount( + 'account_id' => $account_id, +); + +ok( ! $return->{error}, 'deleteAccount successful' ) + or warn $return->{error}. "\n". $return->{return}. "\n"; + +TODO: { + + local $TODO = 'deleteAccount always returns "Deleted successfully", even when nothing was'; + + $return = $vb->deleteAccount( + 'account_id' => '999999999', + ); + + ok( $return->{error}, 'deleteAccount bad data error test' ) + ;#or warn $return->{return}; + +} diff --git a/t/pod-coverage.t b/t/pod-coverage.t new file mode 100644 index 0000000..fc40a57 --- /dev/null +++ b/t/pod-coverage.t @@ -0,0 +1,18 @@ +use strict; +use warnings; +use Test::More; + +# Ensure a recent version of Test::Pod::Coverage +my $min_tpc = 1.08; +eval "use Test::Pod::Coverage $min_tpc"; +plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" + if $@; + +# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, +# but older versions don't recognize some common documentation styles +my $min_pc = 0.18; +eval "use Pod::Coverage $min_pc"; +plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" + if $@; + +all_pod_coverage_ok(); diff --git a/t/pod.t b/t/pod.t new file mode 100644 index 0000000..ee8b18a --- /dev/null +++ b/t/pod.t @@ -0,0 +1,12 @@ +#!perl -T + +use strict; +use warnings; +use Test::More; + +# Ensure a recent version of Test::Pod +my $min_tp = 1.22; +eval "use Test::Pod $min_tp"; +plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; + +all_pod_files_ok(); diff --git a/voicebridgeAPI.wsdl b/voicebridgeAPI.wsdl new file mode 100644 index 0000000..5e1b921 --- /dev/null +++ b/voicebridgeAPI.wsdl @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- 2.11.0