1 package FS::part_export::thirdlane;
3 use base qw( FS::part_export );
5 use vars qw(%info $me);
9 $me = '['.__PACKAGE__.']';
11 tie my %options, 'Tie::IxHash',
12 #'server' => { label => 'Thirdlane server name or IP address', },
13 'username' => { label => 'Thirdlane username', },
14 'password' => { label => 'Thirdlane password', },
15 'prototype_tenant' => { label => 'Prototype tenant name', },
16 'debug' => { label => 'Checkbox label', type => 'checkbox' },
17 # 'select_option' => { label => 'Select option description',
18 # type => 'select', options=>[qw(chocolate vanilla)],
19 # default => 'vanilla',
21 # 'textarea_option' => { label => 'Textarea option description',
23 # default => 'Default text.',
28 'svc' => [qw( svc_pbx svc_phone svc_acct )],
30 'Export tenants, DIDs and admins to Thirdlane PBX manager',
31 'options' => \%options,
33 Exports tenants and DIDs to Thirdlane PBX manager using the XML-RPC API.
37 sub rebless { shift; }
40 my($self, $svc_x) = (shift, shift);
42 if ( $svc_x->isa('FS::svc_pbx') ) {
44 return 'Name must be 19 characters or less (thirdlane restriction?)'
45 if length($svc_x->title) > 19;
47 return 'Name must consist of alphanumerics and spaces only (thirdlane restriction?)'
48 unless $svc_x->title =~ /^[\w\s]+$/;
51 'tenant' => $svc_x->title,
52 'maxusers' => $svc_x->max_extensions,
53 #others? will they not clone?
56 @what_to_clone = qw(routes schedules menus queues voiceprompts moh);
58 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_create',
60 $self->option('prototype_tenant'),
65 #warn Dumper(\$result);
66 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_create)';
68 } elsif ( $svc_x->isa('FS::svc_phone') ) {
70 my $result = $self->_thirdlane_command(
71 'asterisk::rpc_did_create',
72 $svc_x->countrycode. $svc_x->phonenum,
76 #warn Dumper(\$result);
77 $result eq '0' or return 'Thirdlane API failure (rpc_did_create)';
79 return '' unless $svc_x->pbxsvc;
81 $result = $self->_thirdlane_command(
82 'asterisk::rpc_did_assign',
83 $svc_x->countrycode. $svc_x->phonenum,
88 #warn Dumper(\$result);
89 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_assign)';
91 } elsif ( $svc_x->isa('FS::svc_acct') ) {
93 return 'Must select a PBX' unless $svc_x->pbxsvc;
95 my $result = $self->_thirdlane_command(
96 'asterisk::rpc_admin_create',
103 #warn Dumper(\$result);
104 $result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_create)';
107 die "guru meditation #10: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
112 sub _export_replace {
113 my($self, $new, $old) = (shift, shift, shift);
115 # #return "can't change username with thirdlane"
116 # # if $old->username ne $new->username;
117 # #return '' unless $old->_password ne $new->_password;
118 # $err_or_queue = $self->thirdlane_queue( $new->svcnum,
119 # 'replace', $new->username, $new->_password );
120 # ref($err_or_queue) ? '' : $err_or_queue;
122 if ( $new->isa('FS::svc_pbx') ) {
124 #need more info on how the API works for changing names.. can it?
125 return "can't change PBX name with thirdlane (yet?)"
126 if $old->title ne $new->title;
129 'tenant' => $old->title,
130 'maxusers' => $new->max_extensions,
131 #others? will they not clone?
134 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_update',
139 #warn Dumper(\$result);
140 $result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_update)';
142 } elsif ( $new->isa('FS::svc_phone') ) {
144 return "can't change DID countrycode with thirdlane"
145 if $old->countrycode ne $new->countrycode;
146 return "can't change DID number with thirdlane"
147 if $old->phonenum ne $new->phonenum;
149 if ( $old->pbxsvc != $new->pbxsvc ) {
151 if ( $old->pbxsvc ) {
152 my $result = $self->_thirdlane_command(
153 'asterisk::rpc_did_unassign',
154 $new->countrycode. $new->phonenum,
156 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
159 if ( $new->pbxsvc ) {
160 my $result = $self->_thirdlane_command(
161 'asterisk::rpc_did_assign',
162 $new->countrycode. $new->phonenum,
165 $result eq '0' or return 'Thirdlane API failure (rpc_did_assign)';
173 } elsif ( $new->isa('FS::svc_acct') ) {
175 return "can't change uesrname with thirdlane"
176 if $old->username ne $new->username;
178 return "can't change password with thirdlane"
179 if $old->_password ne $new->_password;
181 return "can't change PBX for user with thirdlane"
182 if $old->pbxsvc != $new->pbxsvc;
184 ''; #we don't care then
187 die "guru meditation #11: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
193 my($self, $svc_x) = (shift, shift);
194 #my( $self, $svc_something ) = (shift, shift);
195 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
196 # 'delete', $svc_something->username );
197 #ref($err_or_queue) ? '' : $err_or_queue;
199 if ( $svc_x->isa('FS::svc_pbx') ) {
201 my $result = $self->_thirdlane_command( 'asterisk::rpc_tenant_delete',
206 #warn Dumper(\$result);
207 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_tenant_delete)';
208 warn "Thirdlane API failure (rpc_tenant_delete); deleting anyway\n"
212 } elsif ( $svc_x->isa('FS::svc_phone') ) {
214 if ( $svc_x->pbxsvc ) {
215 my $result = $self->_thirdlane_command(
216 'asterisk::rpc_did_unassign',
217 $svc_x->countrycode. $svc_x->phonenum,
219 $result eq '0' or return 'Thirdlane API failure (rpc_did_unassign)';
222 my $result = $self->_thirdlane_command(
223 'asterisk::rpc_did_delete',
224 $svc_x->countrycode. $svc_x->phonenum,
226 $result eq '0' ? '' : 'Thirdlane API failure (rpc_did_delete)';
228 } elsif ( $svc_x->isa('FS::svc_acct') ) {
230 return '' unless $svc_x->pbxsvc; #error out? nah
232 my $result = $self->_thirdlane_command(
233 'asterisk::rpc_admin_delete',
239 #warn Dumper(\$result);
240 #$result eq '0' ? '' : 'Thirdlane API failure (rpc_admin_delete)';
241 warn "Thirdlane API failure (rpc_admin_delete); deleting anyway\n"
246 die "guru meditation #12: $svc_x is not FS::svc_pbx, FS::svc_phone or FS::svc_acct";
251 sub _thirdlane_command {
252 my($self, @param) = @_;
255 $self->option('username'). ':'. $self->option('password'). '@'.
256 $self->machine. '/xmlrpc.cgi';
258 warn "$me connecting to $url\n"
259 if $self->option('debug');
260 my $conn = Frontier::Client->new( 'url' => $url,
261 #no, spews output to browser
262 #'debug' => $self->option('debug'),
265 warn "$me sending command: ". join(' ', @param). "\n"
266 if $self->option('debug');
271 #my( $self, $svc_something ) = (shift, shift);
272 #$err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
273 # 'delete', $svc_something->username );
274 #ref($err_or_queue) ? '' : $err_or_queue;
276 #these three are optional
277 ## fallback for svc_acct will change and restore password
278 #sub _export_suspend {
279 # my( $self, $svc_something ) = (shift, shift);
280 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
281 # 'suspend', $svc_something->username );
282 # ref($err_or_queue) ? '' : $err_or_queue;
285 #sub _export_unsuspend {
286 # my( $self, $svc_something ) = (shift, shift);
287 # $err_or_queue = $self->thirdlane_queue( $svc_something->svcnum,
288 # 'unsuspend', $svc_something->username );
289 # ref($err_or_queue) ? '' : $err_or_queue;
293 # my($self, $svc_something, $arrayref) = (shift, shift, shift);
294 # #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_something->username.
295 # # qq!">!. $svc_something->username. qq!</A>!;
301 ##a good idea to queue anything that could fail or take any time
302 #sub thirdlane_queue {
303 # my( $self, $svcnum, $method ) = (shift, shift, shift);
304 # my $queue = new FS::queue {
305 # 'svcnum' => $svcnum,
306 # 'job' => "FS::part_export::thirdlane::thirdlane_$method",
308 # $queue->insert( @_ ) or $queue;
311 #sub thirdlane_insert { #subroutine, not method
312 # my( $username, $password ) = @_;
313 # #do things with $username and $password
316 #sub thirdlane_replace { #subroutine, not method
319 #sub thirdlane_delete { #subroutine, not method
320 # my( $username ) = @_;
321 # #do things with $username
324 #sub thirdlane_suspend { #subroutine, not method
327 #sub thirdlane_unsuspend { #subroutine, not method