1 package FS::part_export::thirdlane;
3 use base qw( FS::part_export );
5 use vars qw(%info $me);
10 $me = '['.__PACKAGE__.']';
12 tie my %options, 'Tie::IxHash',
13 #'server' => { label => 'Thirdlane server name or IP address', },
14 'username' => { label => 'Thirdlane username', },
15 'password' => { label => 'Thirdlane password', },
16 'ssl' => { label => 'Enable HTTPS (SSL) connection',
19 'port' => { label => 'Port number if not 80 or 443', },
20 'prototype_tenant' => { label => 'Prototype tenant name', },
21 'omit_countrycode' => { label => 'Omit country code', type => 'checkbox' },
22 'debug' => { label => 'Checkbox label', type => 'checkbox' },
23 # 'select_option' => { label => 'Select option description',
24 # type => 'select', options=>[qw(chocolate vanilla)],
25 # default => 'vanilla',
27 # 'textarea_option' => { label => 'Textarea option description',
29 # default => 'Default text.',
34 'svc' => [qw( svc_pbx svc_phone svc_acct )],
36 'Export tenants, DIDs and admins to Thirdlane PBX manager',
37 'options' => \%options,
39 Exports tenants, DIDs and admins to Thirdlane PBX manager using the XML-RPC API.
43 sub rebless { shift; }
46 my($self, $svc_x) = (shift, shift);
48 if ( $svc_x->isa('FS::svc_pbx') ) {
50 return 'Name must be 19 characters or less (thirdlane restriction?)'
51 if length($svc_x->title) > 19;
53 return 'Name must consist of alphanumerics and spaces only (thirdlane restriction?)'
54 unless $svc_x->title =~ /^[\w\s]+$/;
57 'tenant' => $svc_x->title,
58 'maxusers' => $svc_x->max_extensions,
59 #others? will they not clone?
62 @what_to_clone = qw(routes schedules menus queues voiceprompts moh);
64 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_create',
66 $self->option('prototype_tenant'),
71 #warn Dumper(\$result);
72 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_create)';
74 } elsif ( $svc_x->isa('FS::svc_phone') ) {
76 my $result = $self->_thirdlane_command(
77 'asterisk::rpc_did_create',
78 $self->_thirdlane_did($svc_x)
82 #warn Dumper(\$result);
83 $result eq '0' or return 'Thirdlane API failure (rpc_did_create)';
85 return '' unless $svc_x->pbxsvc;
87 $result = $self->_thirdlane_command(
88 'asterisk::rpc_did_assign',
89 $self->_thirdlane_did($svc_x),
94 #warn Dumper(\$result);
95 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_assign)';
97 } elsif ( $svc_x->isa('FS::svc_acct') ) {
99 return 'Must select a PBX' unless $svc_x->pbxsvc;
101 my $result = $self->_thirdlane_command(
102 'asterisk::rpc_admin_create',
109 #warn Dumper(\$result);
110 $result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_create)';
113 die "guru meditation #10: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
118 sub _export_replace {
119 my($self, $new, $old) = (shift, shift, shift);
121 # #return "can't change username with thirdlane"
122 # # if $old->username ne $new->username;
123 # #return '' unless $old->_password ne $new->_password;
124 # $err_or_queue = $self->thirdlane_queue( $new->svcnum,
125 # 'replace', $new->username, $new->_password );
126 # ref($err_or_queue) ? '' : $err_or_queue;
128 if ( $new->isa('FS::svc_pbx') ) {
130 #need more info on how the API works for changing names.. can it?
131 return "can't change PBX name with thirdlane (yet?)"
132 if $old->title ne $new->title;
135 'tenant' => $old->title,
136 'maxusers' => $new->max_extensions,
137 #others? will they not clone?
140 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_update',
145 #warn Dumper(\$result);
146 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_update)';
148 } elsif ( $new->isa('FS::svc_phone') ) {
150 return "can't change DID countrycode with thirdlane"
151 if $old->countrycode ne $new->countrycode;
152 return "can't change DID number with thirdlane"
153 if $old->phonenum ne $new->phonenum;
155 if ( $old->pbxsvc != $new->pbxsvc ) {
157 if ( $old->pbxsvc ) {
158 my $result = $self->_thirdlane_command(
159 'asterisk::rpc_did_unassign',
160 $self->_thirdlane_did($old),
162 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
165 if ( $new->pbxsvc ) {
166 my $result = $self->_thirdlane_command(
167 'asterisk::rpc_did_assign',
168 $self->_thirdlane_did($new),
171 $result eq '0' or return 'Thirdlane API failure (rpc_did_assign)';
179 } elsif ( $new->isa('FS::svc_acct') ) {
181 return "can't change uesrname with thirdlane"
182 if $old->username ne $new->username;
184 return "can't change password with thirdlane"
185 if $old->_password ne $new->_password;
187 return "can't change PBX for user with thirdlane"
188 if $old->pbxsvc != $new->pbxsvc;
190 ''; #we don't care then
193 die "guru meditation #11: $new is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
199 my($self, $svc_x) = (shift, shift);
200 #my( $self, $svc_something ) = (shift, shift);
201 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
202 # 'delete', $svc_something->username );
203 #ref($err_or_queue) ? '' : $err_or_queue;
205 if ( $svc_x->isa('FS::svc_pbx') ) {
207 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_delete',
212 #warn Dumper(\$result);
213 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_delete)';
214 warn "Thirdlane API failure (rpc_tenant_delete); deleting anyway\n"
218 } elsif ( $svc_x->isa('FS::svc_phone') ) {
220 if ( $svc_x->pbxsvc ) {
221 my $result = $self->_thirdlane_command(
222 'asterisk::rpc_did_unassign',
223 $self->_thirdlane_did($svc_x),
225 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
228 my $result = $self->_thirdlane_command(
229 'asterisk::rpc_did_delete',
230 $self->_thirdlane_did($svc_x),
232 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_delete)';
234 } elsif ( $svc_x->isa('FS::svc_acct') ) {
236 return '' unless $svc_x->pbxsvc; #error out? nah
238 my $result = $self->_thirdlane_command(
239 'asterisk::rpc_admin_delete',
245 #warn Dumper(\$result);
246 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_delete)';
247 warn "Thirdlane API failure (rpc_admin_delete); deleting anyway\n"
252 die "guru meditation #12: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
257 sub _thirdlane_command {
258 my($self, @param) = @_;
260 my $url = $self->option('ssl') ? 'https://' : 'http://';
261 $url .= uri_escape($self->option('username')). ':'.
262 uri_escape($self->option('password')). '@'.
264 $url .= ':'. $self->option('port') if $self->option('port');
265 $url .= '/xmlrpc.cgi';
267 warn "$me connecting to $url\n"
268 if $self->option('debug');
269 my $conn = Frontier::Client->new( 'url' => $url,
270 #no, spews output to browser
271 #'debug' => $self->option('debug'),
274 warn "$me sending command: ". join(' ', @param). "\n"
275 if $self->option('debug');
281 my($self, $svc_phone) = @_;
282 if ( $self->option('omit_countrycode') ) {
283 $svc_phone->phonenum;
285 $svc_phone->countrycode. $svc_phone->phonenum;
289 #my( $self, $svc_something ) = (shift, shift);
290 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
291 # 'delete', $svc_something->username );
292 #ref($err_or_queue) ? '' : $err_or_queue;
294 #these three are optional
295 ## fallback for svc_acct will change and restore password
296 #sub _export_suspend {
297 # my( $self, $svc_something ) = (shift, shift);
298 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
299 # 'suspend', $svc_something->username );
300 # ref($err_or_queue) ? '' : $err_or_queue;
303 #sub _export_unsuspend {
304 # my( $self, $svc_something ) = (shift, shift);
305 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
306 # 'unsuspend', $svc_something->username );
307 # ref($err_or_queue) ? '' : $err_or_queue;
311 # my($self, $svc_something, $arrayref) = (shift, shift, shift);
312 # #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_something->username.
313 # # qq!">!. $svc_something->username. qq!</A>!;
319 ##a good idea to queue anything that could fail or take any time
320 #sub thirdlane_queue {
321 # my( $self, $svcnum, $method ) = (shift, shift, shift);
322 # my $queue = new FS::queue {
323 # 'svcnum' => $svcnum,
324 # 'job' => "FS::part_export::thirdlane::thirdlane_$method",
326 # $queue->insert( @_ ) or $queue;
329 #sub thirdlane_insert { #subroutine, not method
330 # my( $username, $password ) = @_;
331 # #do things with $username and $password
334 #sub thirdlane_replace { #subroutine, not method
337 #sub thirdlane_delete { #subroutine, not method
338 # my( $username ) = @_;
339 # #do things with $username
342 #sub thirdlane_suspend { #subroutine, not method
345 #sub thirdlane_unsuspend { #subroutine, not method