Net-Indosoft-QSuite
-The README is used to introduce the module and provide instructions on
-how to install the module, any machine dependencies it may have (for
-example C compilers and installed libraries) and any other information
-that should be provided before the module is installed.
-
-A README file is required for CPAN modules since CPAN extracts the README
-file from a module distribution so that people browsing the archive
-can use it to get an idea of the module's uses. It is usually a good idea
-to provide version information here so that people can decide whether
-fixes for the module are worth downloading.
+This is an interface to the Indosoft Q-Suite API for wholesale PBX (and call
+center) tenant provisioning.
INSTALLATION
make test
make install
+
SUPPORT AND DOCUMENTATION
After installing, you can find documentation for this module with the
LICENSE AND COPYRIGHT
-Copyright (C) 2014 Ivan Kohler
+Copyright (C) 2014 Freeside Internet Services, Inc. (http://freeside.biz/)
This program is free software; you can redistribute it and/or modify it
-under the terms of the the Artistic License (2.0). You may obtain a
-copy of the full license at:
-
-L<http://www.perlfoundation.org/artistic_license_2_0>
-
-Any use, modification, and distribution of the Standard or Modified
-Versions is governed by this Artistic License. By using, modifying or
-distributing the Package, you accept this license. Do not use, modify,
-or distribute the Package, if you do not accept this license.
-
-If your Modified Version has been derived from a Modified Version made
-by someone other than you, you are nevertheless required to ensure that
-your Modified Version complies with the requirements of this license.
-
-This license does not grant you the right to use any trademark, service
-mark, tradename, or logo of the Copyright Holder.
-
-This license includes the non-exclusive, worldwide, free-of-charge
-patent license to make, have made, use, offer to sell, sell, import and
-otherwise transfer the Package with respect to any patent claims
-licensable by the Copyright Holder that are necessarily infringed by the
-Package. If you institute patent litigation (including a cross-claim or
-counterclaim) against any party alleging that the Package constitutes
-direct or contributory patent infringement, then this Artistic License
-to you shall terminate on the date that such litigation is filed.
-
-Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
-AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
-THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
-YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
-CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
-CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+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 Indosoft 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/
package Net::Indosoft::QSuite;
-use 5.006;
use strict;
-use warnings FATAL => 'all';
+use warnings;
+use vars qw( $AUTOLOAD );
+use JSON;
+use Net::HTTPS::Any qw( https_post );
=head1 NAME
-Net::Indosoft::QSuite - The great new Net::Indosoft::QSuite!
+Net::Indosoft::QSuite - Interface to Indosoft Q-Suite API
=head1 VERSION
=head1 SYNOPSIS
-Quick summary of what the module does.
+ use Net::Indosoft::QSuite;
-Perhaps a little code snippet.
+ my $qsuite = Net::Indosoft::QSuite->new(
+ host => 'server.example.com',
+ gateway_key => '09ad8f6b692717316913809f9903fd08',
+ );
+
+
+ ###
+ # Manage Tenant
+ ###
+
+ my $uuid = $qsuite->editTenant(
+ mode => 'create',
+ name => 'Tenant One',
+ shortname => 'one',
+ hostname => 'one.tenant.com',
+ callerid_name => 'Tenant One',
+ callerid_number => '5551112222',
+ )
+ or die "can't create tenant: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editTenant(
+ mode => 'edit',
+ uuid => 'Tenant UUID',
+ name => 'Tenant Name',
+ shortname => 'Tenant shortname',
+ hostname => 'Tenant hostname',
+ callerid_name => 'Nailup caller ID name',
+ callerid_number => 'Nailup caller ID number',
+ )
+ or die "can't edit tenant: ". $qsuite->errstr;
+
+ $qsuite->editTenant(
+ mode => 'delete',
+ uuid => 'Tenant UUID',
+ )
+ or die "can't delete tenant: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Trunk Assignments
+ ###
+
+ my $uuid = $qsuite->assignTrunkToTenant(
+ mode => 'assign',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ trunk_id => '1', #provided by indosoft
+ )
+ or die "can't assign trunk to tenant ". $qsuite->errstr;
+
+ my $uuid = $qsuite->assignTrunkToTenant(
+ mode => 'unassign',
+ tenant_uuid => 'Tenant UUID',
+ trunk_id => 'trunk ID, #provided by indosoft
+ )
+ or die "can't trunk from tenant: ". $qsuite->errstr;
+
+
+ ###
+ # Manage DID
+ ###
+
+ my $number = $qsuite->editDID(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ number => '4445550011',
+ auto_attendant_uuid => 'c4367c52bf45525bfbb7614b167a5335',
+ )
+ or die "can't create DID: ". $qsuite->errstr;
+
+
+ my $number = $qsuite->editDID(
+ mode => 'edit'
+ tenant_uuid => 'Tenant UUID',
+ number => 'The DID number',
+ auto_attendant_uuid => 'UUID of the assigned auto attendant',
+ )
+ or die "can't edit DID: ". $qsuite->errstr;
+
+ my $number = $qsuite->editDID(
+ mode => 'delete'
+ tenant_uuid => 'Tenant UUID',
+ )
+ or die "can't delete DID: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Auto Attendant
+ ###
+
+ my $uuid = $qsuite->editAutoAttendant(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ name => 'Auto F. Atttendant',
+ repeat_limit => 54,
+ response_limit => 32,
+ allow_extension-dialing => 0, # 0 or 1
+ )
+ or die "can't create auto attendant: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editAutoAttendant(
+ mode => 'edit'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'UUID of the assigned auto attendant',
+ name => 'Auto Attenant name',
+ repeat_limit => 54, # The number of time to attempt to gather input
+ response_limit => 32, # The timeout on the response
+ allow_extension-dialing => 0, # "Allow the caller to dial extensions with the menu
+ )
+ or die "can't edit auto attendant: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editAutoAttendant(
+ mode => 'delete'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'UUID of the assigned auto attendant',
+ )
+ or die "can't delete auto attendant: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Ring Group
+ ###
+
+ my $uuid = $qsuite->editRingGroup(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ #docs say uuid ('ring group uuid') for create, but prob. wrong
+ name => 'Ring Group',
+ timeout => 54,
+ extension_uuids => '432789473febdf00fe1ee77777777777,ab98342efabc43',
+ )
+ or die "can't create ring group: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editRingGroup(
+ mode => 'edit'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'Ring group UUID',
+ name => 'Ring group name',
+ timeout => 54, # Ring group timeout
+ extension_uuids => '1234abc,999fefefefe', # Comma-separated list of extension UUIDs that make up the ring group
+ )
+ or die "can't edit ring group: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editRingGroup(
+ mode => 'delete'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'Ring group UUID',
+ )
+ or die "can't delete ring group: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Employee/User
+ ###
+
+ my $uuid = $qsuite->editEmployee(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ #docs say uuid ('employee uuid') for create, but prob. wrong
+ username => 'tofub',
+ password => 'beast1',
+ firstname => 'Tofu',
+ lastname => 'Beast',
+ )
+ or die "can't create employee: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editEmployee(
+ mode => 'edit'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'Employee UUID',
+ username => 'tofub',
+ password => 'beast1',
+ firstname => 'Tofu',
+ lastname => 'Beast',
+ )
+ or die "can't edit employee: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editEmployee(
+ mode => 'delete'
+ tenant_uuid => 'Tenant UUID',
+ uuid => 'Employee UUID',
+ )
+ or die "can't delete employee: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Extension
+ ###
+
+ #or does this return an "extension uuid"? its wanted for devices...
+ my $number = $qsuite->editExtension(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ number => '101',
+ )
+ or die "can't create extension: ". $qsuite->errstr;
+
+ #this is documented but seems to make no sense
+ #my $number = $qsuite->editExtension(
+ # mode => 'edit'
+ # tenant_uuid => 'Tenant UUID',
+ # number => '101',
+ # )
+ # or die "can't edit extension: ". $qsuite->errstr;
+
+ #or does this want an "extension uuid"?
+ my $number = $qsuite->editExtension(
+ mode => 'delete'
+ tenant_uuid => 'Tenant UUID',
+ number => '101',
+ )
+ or die "can't delete extension: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Device
+ ###
+
+ my $uuid = $qsuite->editDevice(
+ mode => 'create',
+ tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ employee_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ #docs say "device uuid" for create, but i doubt it
+ protocol => 'sip', #sip iax or dahdi
+ )
+ or die "can't create device: ". $qsuite->errstr;
+
+ my $uuid = $qsuite->editDevice(
+ mode => 'edit'
+ tenant_uuid => 'Tenant UUID',
+ employee_uuid => 'Employee UUID',
+ extension_uuid => 'Extension UUID',
+ uuid => 'Device UUID',
+ protocol => 'sip', #sip iax or dahdi
+ )
+ or die "can't edit device: ". $qsuite->errstr;
+
+ #docs for required fields here appear to be on crack (tenant_uuid only?),
+ # so my best guess
+ my $uuid = $qsuite->editDevice(
+ mode => 'delete'
+ #perhaps? tenant_uuid => 'Tenant UUID',
+ #perhaps? employee_uuid => 'Employee UUID',
+ #perhaps? extension_uuid => 'Extension UUID',
+ uuid => 'Device UUID',
+ )
+ or die "can't delete device: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Voicemail Settings
+ ###
+
+ my $uuid = $qsuite->editVoicemailSettings(
+ extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ pin => '5454',
+ )
+ or die "can't edit voicemail: ". $qsuite->errstr;
+
+
+ ###
+ # Manage Extension Forwarding Settings
+ ###
+
+ my $uuid = $qsuite->editForwardingSettings(
+ #perhaps? docs say yes, exampe no tenant_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ extension_uuid => 'f269fa3480e739d77e4fee61f94575e2',
+ number => '555-888-2222',
+ )
+ or die "can't edit forwarding: ". $qsuite->errstr;
+
+
+=head1 METHODS
+
+=head2 new
+
+Creates a new Net::Indosoft:QSuite object. Options may be passed
+as a hash reference or a flat list of names and values.
- use Net::Indosoft::QSuite;
+=over 4
- my $foo = Net::Indosoft::QSuite->new();
- ...
+=item host (required)
-=head1 EXPORT
+=item gateway_key - A valid API gateway key (required)
-A list of functions that can be exported. You can delete this section
-if you don't export anything, such as for a purely object-oriented module.
+=item debug (optional)
-=head1 SUBROUTINES/METHODS
+=back
-=head2 function1
+=cut
+
+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 function1 {
+sub errstr {
+ #my $class = shift;
+ #return $errstr
+ # unless ref($class) && $class->isa('Net::VoIP_Innovations');
+
+ my $self = shift; #$class;
+ $self->{errstr};
}
-=head2 function2
+=head2 editTenant
+
+=head2 assignTrunkToTenant
+
+=head2 editDID
+
+=head2 editAutoAttendant
=cut
-sub function2 {
+#our %return = (
+# 'Tenant' => 'uuid',
+# 'DID' => 'number',
+# 'AutoAttendant' => 'uuid',
+# 'RingGroup' => 'uuid', #? its undocumented
+# 'Employee' => 'uuid',
+# 'Extension' => 'number',
+# 'Device' => 'uuid',
+# 'VoicemailSettings' => 'uuid',
+# 'ForwardingSettings' => 'uuid',
+#);
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $opts = ref($_[0]) ? shift : { @_ };
+
+ $AUTOLOAD =~ /(^|::)(\w+)$/ or die "unparsable AUTOLOAD: $AUTOLOAD";
+ my $func = $2;
+ my $path = "/cti/api/external/$func.json";
+
+ my ( $page, $https_response, %reply_headers ) =
+ https_post({ host => $self->{host},
+ port => 443,
+ path => $path,
+ });
+
+ unless ( $https_response =~ /^200/i ) {
+ #this is a lower-layer communication error, so it warrants an exception
+ die "Error POSTing to https://". $self->{host}. "$path : $https_response\n";
+ #$self->{'errstr'} = $https_response;
+ #return '';
+ }
+
+ my $response = decode_json( $page );
+
+ #use Data::Dumper;
+ #warn Dumper($response); #if $self->{debug};
+
+ unless ( $response->{success} ) { # == 1
+ $self->{errstr} = $response->{error};
+ return '';
+ }
+
+ $self->{errstr} = '';
+
+ # use %return if it gets more complicated
+ if ( $func =~ /(DID|Extension)$/ ) {
+ return $response->{data}{number};
+ } else {
+ return $response->{data}{uuid};
+ }
+
}
=head1 AUTHOR
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Indosoft-QSuite>. 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.
=head1 LICENSE AND COPYRIGHT
-Copyright 2014 Ivan Kohler.
+Copyright (C) 2014 Freeside Internet Services, Inc. (http://freeside.biz/)
This program is free software; you can redistribute it and/or modify it
-under the terms of the the Artistic License (2.0). You may obtain a
-copy of the full license at:
-
-L<http://www.perlfoundation.org/artistic_license_2_0>
-
-Any use, modification, and distribution of the Standard or Modified
-Versions is governed by this Artistic License. By using, modifying or
-distributing the Package, you accept this license. Do not use, modify,
-or distribute the Package, if you do not accept this license.
-
-If your Modified Version has been derived from a Modified Version made
-by someone other than you, you are nevertheless required to ensure that
-your Modified Version complies with the requirements of this license.
-
-This license does not grant you the right to use any trademark, service
-mark, tradename, or logo of the Copyright Holder.
-
-This license includes the non-exclusive, worldwide, free-of-charge
-patent license to make, have made, use, offer to sell, sell, import and
-otherwise transfer the Package with respect to any patent claims
-licensable by the Copyright Holder that are necessarily infringed by the
-Package. If you institute patent litigation (including a cross-claim or
-counterclaim) against any party alleging that the Package constitutes
-direct or contributory patent infringement, then this Artistic License
-to you shall terminate on the date that such litigation is filed.
-
-Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
-AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
-THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
-YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
-CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
-CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+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 Indosoft 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::Indosoft::QSuite
+1;