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 'debug' => { label => 'Checkbox label', type => 'checkbox' },
22 # 'select_option' => { label => 'Select option description',
23 # type => 'select', options=>[qw(chocolate vanilla)],
24 # default => 'vanilla',
26 # 'textarea_option' => { label => 'Textarea option description',
28 # default => 'Default text.',
33 'svc' => [qw( svc_pbx svc_phone svc_acct )],
35 'Export tenants, DIDs and admins to Thirdlane PBX manager',
36 'options' => \%options,
38 Exports tenants, DIDs and admins to Thirdlane PBX manager using the XML-RPC API.
42 sub rebless { shift; }
45 my($self, $svc_x) = (shift, shift);
47 if ( $svc_x->isa('FS::svc_pbx') ) {
49 return 'Name must be 19 characters or less (thirdlane restriction?)'
50 if length($svc_x->title) > 19;
52 return 'Name must consist of alphanumerics and spaces only (thirdlane restriction?)'
53 unless $svc_x->title =~ /^[\w\s]+$/;
56 'tenant' => $svc_x->title,
57 'maxusers' => $svc_x->max_extensions,
58 #others? will they not clone?
61 @what_to_clone = qw(routes schedules menus queues voiceprompts moh);
63 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_create',
65 $self->option('prototype_tenant'),
70 #warn Dumper(\$result);
71 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_create)';
73 } elsif ( $svc_x->isa('FS::svc_phone') ) {
75 my $result = $self->_thirdlane_command(
76 'asterisk::rpc_did_create',
77 $svc_x->countrycode. $svc_x->phonenum,
81 #warn Dumper(\$result);
82 $result eq '0' or return 'Thirdlane API failure (rpc_did_create)';
84 return '' unless $svc_x->pbxsvc;
86 $result = $self->_thirdlane_command(
87 'asterisk::rpc_did_assign',
88 $svc_x->countrycode. $svc_x->phonenum,
93 #warn Dumper(\$result);
94 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_assign)';
96 } elsif ( $svc_x->isa('FS::svc_acct') ) {
98 return 'Must select a PBX' unless $svc_x->pbxsvc;
100 my $result = $self->_thirdlane_command(
101 'asterisk::rpc_admin_create',
108 #warn Dumper(\$result);
109 $result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_create)';
112 die "guru meditation #10: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
117 sub _export_replace {
118 my($self, $new, $old) = (shift, shift, shift);
120 # #return "can't change username with thirdlane"
121 # # if $old->username ne $new->username;
122 # #return '' unless $old->_password ne $new->_password;
123 # $err_or_queue = $self->thirdlane_queue( $new->svcnum,
124 # 'replace', $new->username, $new->_password );
125 # ref($err_or_queue) ? '' : $err_or_queue;
127 if ( $new->isa('FS::svc_pbx') ) {
129 #need more info on how the API works for changing names.. can it?
130 return "can't change PBX name with thirdlane (yet?)"
131 if $old->title ne $new->title;
134 'tenant' => $old->title,
135 'maxusers' => $new->max_extensions,
136 #others? will they not clone?
139 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_update',
144 #warn Dumper(\$result);
145 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_update)';
147 } elsif ( $new->isa('FS::svc_phone') ) {
149 return "can't change DID countrycode with thirdlane"
150 if $old->countrycode ne $new->countrycode;
151 return "can't change DID number with thirdlane"
152 if $old->phonenum ne $new->phonenum;
154 if ( $old->pbxsvc != $new->pbxsvc ) {
156 if ( $old->pbxsvc ) {
157 my $result = $self->_thirdlane_command(
158 'asterisk::rpc_did_unassign',
159 $new->countrycode. $new->phonenum,
161 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
164 if ( $new->pbxsvc ) {
165 my $result = $self->_thirdlane_command(
166 'asterisk::rpc_did_assign',
167 $new->countrycode. $new->phonenum,
170 $result eq '0' or return 'Thirdlane API failure (rpc_did_assign)';
178 } elsif ( $new->isa('FS::svc_acct') ) {
180 return "can't change uesrname with thirdlane"
181 if $old->username ne $new->username;
183 return "can't change password with thirdlane"
184 if $old->_password ne $new->_password;
186 return "can't change PBX for user with thirdlane"
187 if $old->pbxsvc != $new->pbxsvc;
189 ''; #we don't care then
192 die "guru meditation #11: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
198 my($self, $svc_x) = (shift, shift);
199 #my( $self, $svc_something ) = (shift, shift);
200 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
201 # 'delete', $svc_something->username );
202 #ref($err_or_queue) ? '' : $err_or_queue;
204 if ( $svc_x->isa('FS::svc_pbx') ) {
206 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_delete',
211 #warn Dumper(\$result);
212 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_delete)';
213 warn "Thirdlane API failure (rpc_tenant_delete); deleting anyway\n"
217 } elsif ( $svc_x->isa('FS::svc_phone') ) {
219 if ( $svc_x->pbxsvc ) {
220 my $result = $self->_thirdlane_command(
221 'asterisk::rpc_did_unassign',
222 $svc_x->countrycode. $svc_x->phonenum,
224 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
227 my $result = $self->_thirdlane_command(
228 'asterisk::rpc_did_delete',
229 $svc_x->countrycode. $svc_x->phonenum,
231 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_delete)';
233 } elsif ( $svc_x->isa('FS::svc_acct') ) {
235 return '' unless $svc_x->pbxsvc; #error out? nah
237 my $result = $self->_thirdlane_command(
238 'asterisk::rpc_admin_delete',
244 #warn Dumper(\$result);
245 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_delete)';
246 warn "Thirdlane API failure (rpc_admin_delete); deleting anyway\n"
251 die "guru meditation #12: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
256 sub _thirdlane_command {
257 my($self, @param) = @_;
259 my $url = $self->option('ssl') ? 'https://' : 'http://';
260 $url .= uri_escape($self->option('username')). ':'.
261 uri_escape($self->option('password')). '@'.
263 $url .= ':'. $self->option('port') if $self->option('port');
264 $url .= '/xmlrpc.cgi';
266 warn "$me connecting to $url\n"
267 if $self->option('debug');
268 my $conn = Frontier::Client->new( 'url' => $url,
269 #no, spews output to browser
270 #'debug' => $self->option('debug'),
273 warn "$me sending command: ". join(' ', @param). "\n"
274 if $self->option('debug');
279 #my( $self, $svc_something ) = (shift, shift);
280 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
281 # 'delete', $svc_something->username );
282 #ref($err_or_queue) ? '' : $err_or_queue;
284 #these three are optional
285 ## fallback for svc_acct will change and restore password
286 #sub _export_suspend {
287 # my( $self, $svc_something ) = (shift, shift);
288 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
289 # 'suspend', $svc_something->username );
290 # ref($err_or_queue) ? '' : $err_or_queue;
293 #sub _export_unsuspend {
294 # my( $self, $svc_something ) = (shift, shift);
295 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
296 # 'unsuspend', $svc_something->username );
297 # ref($err_or_queue) ? '' : $err_or_queue;
301 # my($self, $svc_something, $arrayref) = (shift, shift, shift);
302 # #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_something->username.
303 # # qq!">!. $svc_something->username. qq!</A>!;
309 ##a good idea to queue anything that could fail or take any time
310 #sub thirdlane_queue {
311 # my( $self, $svcnum, $method ) = (shift, shift, shift);
312 # my $queue = new FS::queue {
313 # 'svcnum' => $svcnum,
314 # 'job' => "FS::part_export::thirdlane::thirdlane_$method",
316 # $queue->insert( @_ ) or $queue;
319 #sub thirdlane_insert { #subroutine, not method
320 # my( $username, $password ) = @_;
321 # #do things with $username and $password
324 #sub thirdlane_replace { #subroutine, not method
327 #sub thirdlane_delete { #subroutine, not method
328 # my( $username ) = @_;
329 # #do things with $username
332 #sub thirdlane_suspend { #subroutine, not method
335 #sub thirdlane_unsuspend { #subroutine, not method