diff options
Diffstat (limited to 'FS/FS/part_export/thirdlane.pm')
-rw-r--r-- | FS/FS/part_export/thirdlane.pm | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/FS/FS/part_export/thirdlane.pm b/FS/FS/part_export/thirdlane.pm new file mode 100644 index 0000000..60c0997 --- /dev/null +++ b/FS/FS/part_export/thirdlane.pm @@ -0,0 +1,348 @@ +package FS::part_export::thirdlane; + +use base qw( FS::part_export ); + +use vars qw(%info $me); +use Tie::IxHash; +use URI::Escape; +use Frontier::Client; + +$me = '['.__PACKAGE__.']'; + +tie my %options, 'Tie::IxHash', + #'server' => { label => 'Thirdlane server name or IP address', }, + 'username' => { label => 'Thirdlane username', }, + 'password' => { label => 'Thirdlane password', }, + 'ssl' => { label => 'Enable HTTPS (SSL) connection', + type => 'checkbox', + }, + 'port' => { label => 'Port number if not 80 or 443', }, + 'prototype_tenant' => { label => 'Prototype tenant name', }, + 'omit_countrycode' => { label => 'Omit country code', type => 'checkbox' }, + 'debug' => { label => 'Checkbox label', type => 'checkbox' }, +# 'select_option' => { label => 'Select option description', +# type => 'select', options=>[qw(chocolate vanilla)], +# default => 'vanilla', +# }, +# 'textarea_option' => { label => 'Textarea option description', +# type => 'textarea', +# default => 'Default text.', +# }, +; + +%info = ( + 'svc' => [qw( svc_pbx svc_phone svc_acct )], + 'desc' => + 'Export tenants, DIDs and admins to Thirdlane PBX manager', + 'options' => \%options, + 'notes' => <<'END' +Exports tenants, DIDs and admins to Thirdlane PBX manager using the XML-RPC API. +END +); + +sub rebless { shift; } + +sub _export_insert { + my($self, $svc_x) = (shift, shift); + + if ( $svc_x->isa('FS::svc_pbx') ) { + + return 'Name must be 19 characters or less (thirdlane restriction?)' + if length($svc_x->title) > 19; + + return 'Name must consist of alphanumerics and spaces only (thirdlane restriction?)' + unless $svc_x->title =~ /^[\w\s]+$/; + + my $tenant = { + 'tenant' => $svc_x->title, + 'maxusers' => $svc_x->max_extensions, + #others? will they not clone? + }; + + @what_to_clone = qw(routes schedules menus queues voiceprompts moh); + + my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_create', + $tenant, + $self->option('prototype_tenant'), + \@what_to_clone, + ); + + #use Data::Dumper; + #warn Dumper(\$result); + $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_create)'; + + } elsif ( $svc_x->isa('FS::svc_phone') ) { + + my $result = $self->_thirdlane_command( + 'asterisk::rpc_did_create', + $self->_thirdlane_did($svc_x) + ); + + #use Data::Dumper; + #warn Dumper(\$result); + $result eq '0' or return 'Thirdlane API failure (rpc_did_create)'; + + return '' unless $svc_x->pbxsvc; + + $result = $self->_thirdlane_command( + 'asterisk::rpc_did_assign', + $self->_thirdlane_did($svc_x), + $svc_x->pbx_title, + ); + + #use Data::Dumper; + #warn Dumper(\$result); + $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_assign)'; + + } elsif ( $svc_x->isa('FS::svc_acct') ) { + + return 'Must select a PBX' unless $svc_x->pbxsvc; + + my $result = $self->_thirdlane_command( + 'asterisk::rpc_admin_create', + $svc_x->username, + $svc_x->_password, + $svc_x->pbx_title, + ); + + #use Data::Dumper; + #warn Dumper(\$result); + $result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_create)'; + + } else { + die "guru meditation #10: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct"; + } + +} + +sub _export_replace { + my($self, $new, $old) = (shift, shift, shift); + +# #return "can't change username with thirdlane" +# # if $old->username ne $new->username; +# #return '' unless $old->_password ne $new->_password; +# $err_or_queue = $self->thirdlane_queue( $new->svcnum, +# 'replace', $new->username, $new->_password ); +# ref($err_or_queue) ? '' : $err_or_queue; + + if ( $new->isa('FS::svc_pbx') ) { + + #need more info on how the API works for changing names.. can it? + return "can't change PBX name with thirdlane (yet?)" + if $old->title ne $new->title; + + my $tenant = { + 'tenant' => $old->title, + 'maxusers' => $new->max_extensions, + #others? will they not clone? + }; + + my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_update', + $tenant + ); + + #use Data::Dumper; + #warn Dumper(\$result); + $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_update)'; + + } elsif ( $new->isa('FS::svc_phone') ) { + + return "can't change DID countrycode with thirdlane" + if $old->countrycode ne $new->countrycode; + return "can't change DID number with thirdlane" + if $old->phonenum ne $new->phonenum; + + if ( $old->pbxsvc != $new->pbxsvc ) { + + if ( $old->pbxsvc ) { + my $result = $self->_thirdlane_command( + 'asterisk::rpc_did_unassign', + $self->_thirdlane_did($old), + ); + $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)'; + } + + if ( $new->pbxsvc ) { + my $result = $self->_thirdlane_command( + 'asterisk::rpc_did_assign', + $self->_thirdlane_did($new), + $new->pbx_title, + ); + $result eq '0' or return 'Thirdlane API failure (rpc_did_assign)'; + } + + + } + + ''; + + } elsif ( $new->isa('FS::svc_acct') ) { + + return "can't change uesrname with thirdlane" + if $old->username ne $new->username; + + return "can't change password with thirdlane" + if $old->_password ne $new->_password; + + return "can't change PBX for user with thirdlane" + if $old->pbxsvc != $new->pbxsvc; + + ''; #we don't care then + + } else { + die "guru meditation #11: $new is not FS::svc_pbx, FS::svc_phone or FS::svc_acct"; + } + +} + +sub _export_delete { + my($self, $svc_x) = (shift, shift); + #my( $self, $svc_something ) = (shift, shift); + #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum, + # 'delete', $svc_something->username ); + #ref($err_or_queue) ? '' : $err_or_queue; + + if ( $svc_x->isa('FS::svc_pbx') ) { + + my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_delete', + $svc_x->title, + ); + + #use Data::Dumper; + #warn Dumper(\$result); + #$result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_delete)'; + warn "Thirdlane API failure (rpc_tenant_delete); deleting anyway\n" + if $result ne '0'; + ''; + + } elsif ( $svc_x->isa('FS::svc_phone') ) { + + if ( $svc_x->pbxsvc ) { + my $result = $self->_thirdlane_command( + 'asterisk::rpc_did_unassign', + $self->_thirdlane_did($svc_x), + ); + $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)'; + } + + my $result = $self->_thirdlane_command( + 'asterisk::rpc_did_delete', + $self->_thirdlane_did($svc_x), + ); + $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_delete)'; + + } elsif ( $svc_x->isa('FS::svc_acct') ) { + + return '' unless $svc_x->pbxsvc; #error out? nah + + my $result = $self->_thirdlane_command( + 'asterisk::rpc_admin_delete', + $svc_x->username, + $svc_x->pbx_title, + ); + + #use Data::Dumper; + #warn Dumper(\$result); + #$result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_delete)'; + warn "Thirdlane API failure (rpc_admin_delete); deleting anyway\n" + if $result ne '0'; + ''; + + } else { + die "guru meditation #12: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct"; + } + +} + +sub _thirdlane_command { + my($self, @param) = @_; + + my $url = $self->option('ssl') ? 'https://' : 'http://'; + $url .= uri_escape($self->option('username')). ':'. + uri_escape($self->option('password')). '@'. + $self->machine; + $url .= ':'. $self->option('port') if $self->option('port'); + $url .= '/xmlrpc.cgi'; + + warn "$me connecting to $url\n" + if $self->option('debug'); + my $conn = Frontier::Client->new( 'url' => $url, + #no, spews output to browser + #'debug' => $self->option('debug'), + ); + + warn "$me sending command: ". join(' ', @param). "\n" + if $self->option('debug'); + $conn->call(@param); + +} + +sub _thirdlane_did { + my($self, $svc_phone) = @_; + if ( $self->option('omit_countrycode') ) { + $svc_phone->phonenum; + } else { + $svc_phone->countrycode. $svc_phone->phonenum; + } +} + + #my( $self, $svc_something ) = (shift, shift); + #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum, + # 'delete', $svc_something->username ); + #ref($err_or_queue) ? '' : $err_or_queue; + +#these three are optional +## fallback for svc_acct will change and restore password +#sub _export_suspend { +# my( $self, $svc_something ) = (shift, shift); +# $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum, +# 'suspend', $svc_something->username ); +# ref($err_or_queue) ? '' : $err_or_queue; +#} +# +#sub _export_unsuspend { +# my( $self, $svc_something ) = (shift, shift); +# $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum, +# 'unsuspend', $svc_something->username ); +# ref($err_or_queue) ? '' : $err_or_queue; +#} +# +#sub export_links { +# my($self, $svc_something, $arrayref) = (shift, shift, shift); +# #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_something->username. +# # qq!">!. $svc_something->username. qq!</A>!; +# ''; +#} + +#### +# +##a good idea to queue anything that could fail or take any time +#sub thirdlane_queue { +# my( $self, $svcnum, $method ) = (shift, shift, shift); +# my $queue = new FS::queue { +# 'svcnum' => $svcnum, +# 'job' => "FS::part_export::thirdlane::thirdlane_$method", +# }; +# $queue->insert( @_ ) or $queue; +#} +# +#sub thirdlane_insert { #subroutine, not method +# my( $username, $password ) = @_; +# #do things with $username and $password +#} +# +#sub thirdlane_replace { #subroutine, not method +#} +# +#sub thirdlane_delete { #subroutine, not method +# my( $username ) = @_; +# #do things with $username +#} +# +#sub thirdlane_suspend { #subroutine, not method +#} +# +#sub thirdlane_unsuspend { #subroutine, not method +#} + +1; |