initial commit
authorIvan Kohler <ivan@freeside.biz>
Thu, 13 Dec 2012 00:31:06 +0000 (16:31 -0800)
committerIvan Kohler <ivan@freeside.biz>
Thu, 13 Dec 2012 00:31:06 +0000 (16:31 -0800)
15 files changed:
Changes [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
MYMETA.yml [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README [new file with mode: 0644]
lib/Net/VoIP_Innovations.pm [new file with mode: 0644]
pm_to_blib [new file with mode: 0644]
t/00-load.t [new file with mode: 0644]
t/01-login.t [new file with mode: 0644]
t/41-auditDIDs.t [new file with mode: 0644]
t/61-getDID.t [new file with mode: 0644]
t/62-getDIDs.t [new file with mode: 0644]
t/lib/test_account.pl [new file with mode: 0644]
t/pod-coverage.t [new file with mode: 0644]
t/pod.t [new file with mode: 0644]

diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..95c439c
--- /dev/null
+++ b/Changes
@@ -0,0 +1,14 @@
+Revision history for Net-VoIP_Innovations
+
+2.00    unreleased
+        - update for VoIP Innovations API 2.0, rename to Net::VoIP_Innovations
+
+0.03    unreleased
+        - test updates, turn down debugging verbosity
+
+0.02    unreleased
+        - update for Net::HTTPS::Any 0.10 without HTTP in response code
+
+0.01    unreleased
+        First version, (not) released on an unsuspecting world.
+
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..60ec711
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,13 @@
+Changes
+MANIFEST
+Makefile.PL
+README
+lib/Net/VoIP_Innovations.pm
+t/00-load.t
+t/01-login.t
+t/41-auditDIDs.t
+t/61-getDID.t
+t/62-getDIDs.t
+t/pod-coverage.t
+t/pod.t
+t/lib/test_account.pl
diff --git a/MYMETA.yml b/MYMETA.yml
new file mode 100644 (file)
index 0000000..b1501c1
--- /dev/null
@@ -0,0 +1,26 @@
+---
+abstract: 'Interface to VoIP_Innovations API'
+author:
+  - 'Ivan Kohler <ivan-net-voipinnovations@freeside.biz>'
+build_requires:
+  ExtUtils::MakeMaker: 0
+configure_requires:
+  ExtUtils::MakeMaker: 0
+distribution_type: module
+dynamic_config: 0
+generated_by: 'ExtUtils::MakeMaker version 6.57_05'
+license: unknown
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: Net-VoIP_Innovations
+no_index:
+  directory:
+    - t
+    - inc
+requires:
+  Net::HTTPS::Any: 0.1
+  Test::More: 0
+  XML::Simple: 0
+  XML::Writer: 0
+version: 2.00
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..74049bb
--- /dev/null
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+    NAME                => 'Net::VoIP_Innovations',
+    AUTHOR              => 'Ivan Kohler <ivan-net-voipinnovations@freeside.biz>',
+    VERSION_FROM        => 'lib/Net/VoIP_Innovations.pm',
+    ABSTRACT_FROM       => 'lib/Net/VoIP_Innovations.pm',
+    PL_FILES            => {},
+    PREREQ_PM => {
+        'Test::More'      => 0,
+        'XML::Simple'     => 0,
+        'XML::Writer'     => 0,
+        'Net::HTTPS::Any' => 0.10
+    },
+    dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
+    clean               => { FILES => 'Net-VoIP_Innovations-*' },
+);
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0f64da5
--- /dev/null
+++ b/README
@@ -0,0 +1,56 @@
+Net-VoIP_Innovations
+
+This is an interface to the VoIP Innovations (formerly GlobalPOPs) API for
+wholesale DID (phone number) provisioning.  It is only useful if you have an
+account with GlobalPOPs wholesale VoIP 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::VoIP_Innovations
+
+You can also look for information at:
+
+    RT, CPAN's request tracker
+        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-VoIP_Innovations
+
+    AnnoCPAN, Annotated CPAN documentation
+        http://annocpan.org/dist/Net-VoIP_Innovations
+
+    CPAN Ratings
+        http://cpanratings.perl.org/d/Net-VoIP_Innovations
+
+    Search CPAN
+        http://search.cpan.org/dist/Net-VoIP_Innovations
+
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2008 Freeside Internet Services, Inc. (http://freeside.biz/)
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+
+ADVERTISEMENT
+
+Need a complete, open-source back-office and customer self-service solution?
+The Freeside software includes support for VoIP Innovations integration, CDR
+rating, invoicing, credit card and electronic check processing, integrated
+trouble ticketing, and customer signup and self-service web interfaces.
+
+http://freeside.biz/freeside/
+
diff --git a/lib/Net/VoIP_Innovations.pm b/lib/Net/VoIP_Innovations.pm
new file mode 100644 (file)
index 0000000..bd56c8b
--- /dev/null
@@ -0,0 +1,252 @@
+package Net::VoIP_Innovations;
+
+use warnings;
+use strict;
+use Data::Dumper;
+use XML::Simple;
+use XML::Writer;
+use Net::HTTPS::Any qw( 0.10 https_post );
+
+=head1 NAME
+
+Net::VoIP_Innovations - Interface to VoIP_Innovations API
+
+=cut
+
+our $VERSION = '2.00';
+our $URL     = 'https://www.loginto.us/VOIP/api2.pl';
+#could be parsed from URL, if it mattered...
+our $HOST    = 'www.loginto.us';
+our $PATH    = '/VOIP/api2.pl';
+our $PORT    = 443; #to allow testing to override
+
+our $AUTOLOAD;
+our $errstr = '';
+
+=head1 SYNOPSIS
+
+    use Net::VoIP_Innovations;
+
+    my $handle = Net::VoIP_Innovations->new(
+        'login'    => 'tofu',
+        'password' => 'beast',
+        'debug'    => 1,
+    );
+
+    #DID functions
+    #auditDIDs
+    #queryDID
+    #reserveDID
+    #assignDID
+    #configDID
+    #releaseDID
+
+    #911 Functions
+
+    #Locator Functions
+
+    ...
+
+=head1 METHODS
+
+=head2 new HASHREF | OPTION, VALUE ...
+
+Creates a new Net::VoIP_Innovations object.  Options may be passed
+as a hash reference or a flat list of names and values.
+
+=over 4
+
+=item login (required)
+
+=item password (required)
+
+=item login (required)
+
+=back
+
+=cut
+
+#  If there is an error,
+#returns false and sets an error string which may be queried with the I<errstr>
+#class method.
+
+sub new {
+  my $proto = shift;
+  my $class = ref($proto) || $proto;
+  my $self = ref($_[0]) ? shift : { @_ };
+  $self->{'debug'} ||= 0;
+  bless($self, $class);
+}
+
+=head2 errstr
+
+=cut
+
+sub errstr {
+  my $class = shift;
+
+  return $errstr
+    unless ref($class) && $class->isa('Net::VoIP_Innovations');
+
+  my $self = $class;
+  $self->{errstr};
+}
+
+sub DESTROY { }; # no-op
+
+sub AUTOLOAD {
+  my $self = shift;
+  my $opts = ref($_[0]) ? shift : { @_ };
+
+  $AUTOLOAD =~ /(^|::)(\w+)$/ or die "unparsable AUTOLOAD: $AUTOLOAD";
+  my $function = $2;
+
+  my $output;
+  my $w = new XML::Writer(OUTPUT => \$output, DATA_MODE => 1, DATA_INDENT => 3);
+
+  $w->xmlDecl('ISO-8859-1');
+  $w->doctype('request', undef, $URL);
+
+  $w->startTag('request', 'id' => '');  #XXX request ID???
+    $w->startTag('header');
+      $w->startTag('sender');
+
+        if ( $self->{'sessionid'} ) {
+
+          #$w->dataElement( 'login'     => ''                   );
+          #$w->dataElement( 'password'  => ''                   );
+          $w->dataElement( 'sessionid' => $self->{'sessionid'} );
+
+        } else {
+
+          $w->dataElement( 'login'     => $self->{'login'}     );
+          $w->dataElement( 'password'  => $self->{'password'}  );
+          #$w->dataElement( 'sessionid' => ''                   );
+
+        }
+
+      $w->endTag('sender');
+    $w->endTag('header');
+
+    $w->startTag('body');
+
+      $w->dataElement( 'requesttype' => $function );
+
+      if ( keys %$opts ) {
+        $w->startTag('item');
+          foreach my $opt ( keys %$opts ) {
+            $w->dataElement( $opt => $opts->{$opt} );
+          }
+        $w->endTag('item');
+      }
+
+    $w->endTag('body');
+
+  $w->endTag('request');
+
+  #$output =~ s/\n+/\n/g;
+
+  warn "XML Request for $function function:\n$output"
+    if $self->{'debug'} > 1;
+
+  my( $page, $response, %reply_headers ) = https_post(
+    'host'         => $HOST,
+    'port'         => $PORT,
+    'path'         => ($PATH||443),
+    'args'         => { 'apidata' => $output, },
+    #'content'      => $output,
+    #'Content-Type' => 'text/plain',
+    #'Content-Type' => 'text/xml',
+    'Content-Type' => 'application/xml',
+    #'headers' => {},
+    'debug'        => ( $self->{'debug'} > 1 ? 1 : 0 ),
+  );
+
+  unless ( $response =~ /^200/i ) {
+    $self->{'errstr'} = $response;
+    return '';
+  }
+
+  warn "XML Response for $function function:\n: $page"
+    if $self->{'debug'} > 1;
+
+  my $hashref = XMLin( $page );
+
+  warn "Parsed response for $function funtion:\n". Dumper($hashref)
+    if $self->{'debug'} > 1;
+
+  my $return = $hashref->{'body'};
+
+  warn "Returning data:\n". Dumper($return)
+    if $self->{'debug'} > 1;
+
+  $return;
+
+}
+
+=head1 AUTHOR
+
+Ivan Kohler, C<< <ivan-net-voipinnovations at freeside.biz> >>
+
+=head1 BUGS
+
+Please report any bugs or feature requests to C<bug-net-voip_innovations at rt.cpan.org>, or through
+the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-VoIP_Innovations>.  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::VoIP_Innovations
+
+
+You can also look for information at:
+
+=over 4
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-VoIP_Innovations>
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Net-VoIP_Innovations>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Net-VoIP_Innovations>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Net-VoIP_Innovations>
+
+=back
+
+
+=head1 ACKNOWLEDGEMENTS
+
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright 2008-2012 Freeside Internet Services, Inc. (http://freeside.biz/)
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+
+=head1 ADVERTISEMENT
+
+Need a complete, open-source back-office and customer self-service solution?
+The Freeside software includes support for VoIP Innovations integration, CDR
+rating, invoicing, credit card and electronic check processing, integrated
+trouble ticketing, and customer signup and self-service web interfaces.
+
+http://freeside.biz/freeside/
+
+=cut
+
+1; # End of Net::VoIP_Innovations
diff --git a/pm_to_blib b/pm_to_blib
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/t/00-load.t b/t/00-load.t
new file mode 100644 (file)
index 0000000..ddd413c
--- /dev/null
@@ -0,0 +1,9 @@
+#!perl -T
+
+use Test::More tests => 1;
+
+BEGIN {
+       use_ok( 'Net::VoIP_Innovations' );
+}
+
+diag( "Testing Net::VoIP_Innovations $Net::VoIP_Innovations::VERSION, Perl $], $^X" );
diff --git a/t/01-login.t b/t/01-login.t
new file mode 100644 (file)
index 0000000..2642b59
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+require 't/lib/test_account.pl';
+
+my($login, $password) = test_account_or_skip;
+plan tests => 2;
+
+use_ok 'Net::VoIP_Innovations';
+
+my $gp = Net::VoIP_Innovations->new('login'    => $login,
+                                    'password' => $password );
+
+#eww.  what is the right, TEST_VERBOSE-aware way to do this
+warn Net::VoIP_Innovations->errstr unless $gp;
+
+ok( $gp, 'Login sucessful' );
diff --git a/t/41-auditDIDs.t b/t/41-auditDIDs.t
new file mode 100644 (file)
index 0000000..6793931
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+
+use Test::More skip_all => "not working with current test account?";
+
+require 't/lib/test_account.pl';
+require Net::VoIP_Innovations;
+
+my($login, $password) = test_account_or_skip();
+plan tests => 3;
+
+my $debug = $ENV{TEST_VERBOSE};
+
+my $gp = Net::VoIP_Innovations->new( 'login'    => $login,
+                                     'password' => $password,
+                                     #'debug'    => $debug,
+                                   );
+my $return = $gp->auditDIDs();
+
+use Data::Dumper;
+diag( Dumper($return) ); # if $debug;
+
+ok( $return, 'auditDIDs returned something' );
+
+#         'did' => [
+#                   {
+#                     'statuscode' => '100',
+#                     'status' => 'Number currently assigned to you with refid  rewritten as \'\' to endpoint 521',
+#                     'cnam' => 'False',
+#                     'expire_seconds' => {},
+#                     'availability' => 'assigned',
+#                     'tn' => '2137851430',
+#                     'rewrite' => {},
+#                     'endpoint' => '521',
+#                     'refid' => {}
+#                   },
+#                   {
+#                     'statuscode' => '100',
+#                     'status' => 'Number currently assigned to you with refid  rewritten as \'\' to endpoint 521',
+#                     'cnam' => 'False',
+#                     'expire_seconds' => {},
+#                     'availability' => 'assigned',
+#                     'tn' => '5109626974',
+#                     'rewrite' => {},
+#                     'endpoint' => '521',
+#                     'refid' => {}
+#                   }
+#                 ]
+
+
+ok( $return->{'did'}, 'auditDIDs returned did data' );
+
+ok( ref($return->{'did'}) eq 'ARRAY', 'auditDIDs did data is a list' );
+
diff --git a/t/61-getDID.t b/t/61-getDID.t
new file mode 100644 (file)
index 0000000..15dfe54
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+#BEGIN {
+#  $Net::HTTPS::Any::skip_NetSSLeay = 1;
+#  $Net::HTTPS::Any::skip_NetSSLeay = 1;
+#}
+
+use Test::More;
+
+require 't/lib/test_account.pl';
+require Net::VoIP_Innovations;
+
+my($login, $password) = test_account_or_skip();
+plan tests => 1;
+
+my $debug = $ENV{TEST_VERBOSE};
+
+my $gp = Net::VoIP_Innovations->new( 'login'    => $login,
+                                     'password' => $password,
+                                     #'debug'    => $debug,
+                                   );
+my $return = $gp->getDID();
+
+use Data::Dumper;
+diag( Dumper($return) ) if $debug;
+
+#XXX test some things about the return...
+ok( $return, 'getDID returned something' );
diff --git a/t/62-getDIDs.t b/t/62-getDIDs.t
new file mode 100644 (file)
index 0000000..52f0170
--- /dev/null
@@ -0,0 +1,34 @@
+#!/usr/bin/perl -w
+
+#BEGIN {
+#  $Net::HTTPS::Any::skip_NetSSLeay = 1;
+#  $Net::HTTPS::Any::skip_NetSSLeay = 1;
+#}
+
+use Test::More;
+
+require 't/lib/test_account.pl';
+require Net::VoIP_Innovations;
+
+my($login, $password) = test_account_or_skip();
+plan tests => 1;
+
+
+my $debug = $ENV{TEST_VERBOSE};
+
+my $gp = Net::VoIP_Innovations->new( 'login'    => $login,
+                                     'password' => $password,
+                                     #'debug'    => $debug,
+                                   );
+my $return = $gp->getDIDs(
+  'state'   => 'CA',
+  'lata'    => '722',
+  #'npa'   => '415',
+  'orderby' => 'ORDER BY npa', #?
+);
+
+use Data::Dumper;
+diag( Dumper($return) ); # if $debug;
+
+#XXX test some things about the return...
+ok( $return, 'getDIDs returned something' );
diff --git a/t/lib/test_account.pl b/t/lib/test_account.pl
new file mode 100644 (file)
index 0000000..c52067d
--- /dev/null
@@ -0,0 +1,29 @@
+use Test::More;
+
+sub test_account_or_skip {
+    my($login, $password) = test_account();
+
+    unless( defined $login ) {
+        plan skip_all => "No test account";
+    }
+
+    return($login, $password);
+}
+
+sub test_account {
+    open TEST_ACCOUNT, "t/test_account" or return;
+    my($login, $password, $hostport) = <TEST_ACCOUNT>;
+    chomp $login;
+    chomp $password;
+    chomp $hostport;
+
+    if ( $hostport =~ /^\s*([\w\.]+)(:(\d+))?\s*$/ ) {
+      my($host, $port) = ($1, $3);
+      $Net::VoIP_Innovations::HOST = $host;
+      $Net::VoIP_Innovations::PORT = $port;
+    }
+
+    return($login, $password);
+}
+
+1;
diff --git a/t/pod-coverage.t b/t/pod-coverage.t
new file mode 100644 (file)
index 0000000..fc40a57
--- /dev/null
@@ -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 (file)
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();