more steps to netsapiens export, RT#5226
[freeside.git] / FS / FS / part_export / netsapiens.pm
1 package FS::part_export::netsapiens;
2
3 use vars qw(@ISA %info);
4 use URI;
5 use MIME::Base64;
6 use Tie::IxHash;
7 use FS::part_export;
8
9 @ISA = qw(FS::part_export);
10
11 tie my %options, 'Tie::IxHash',
12   'login'           => { label=>'NetSapiens tac2 User API username' },
13   'password'        => { label=>'NetSapiens tac2 User API password' },
14   'url'             => { label=>'NetSapiens tac2 User URL' },
15   'device_login'    => { label=>'NetSapiens tac2 Device API username' },
16   'device_password' => { label=>'NetSapiens tac2 Device API password' },
17   'device_url'      => { label=>'NetSapiens tac2 Device URL' },
18   'domain'          => { label=>'NetSapiens Domain' },
19 ;
20
21 %info = (
22   'svc'      => 'svc_phone',
23   'desc'     => 'Provision phone numbers to NetSapiens',
24   'options'  => \%options,
25   'notes'    => <<'END'
26 Requires installation of
27 <a href="http://search.cpan.org/dist/REST-Client">REST::Client</a>
28 from CPAN.
29 END
30 );
31
32 sub rebless { shift; }
33
34 sub ns_command {
35   my $self = shift;
36   $self->_ns_command('', @_);
37 }
38
39 sub ns_device_command { 
40   my $self = shift;
41   $self->_ns_command('device', @_);
42 }
43
44 sub ns_command {
45   my( $self, $prefix, $method, $command ) = splice(@_,0,4);
46
47   eval 'use REST::Client';
48   die $@ if $@;
49
50   my $ns = new REST::Client 'host'=>$self->option($prefix.'url');
51
52   my @args = ( $command );
53
54   if ( $method eq 'PUT' ) {
55     my $content = $ns->buildQuery( { @_ } );
56     $content =~ s/^\?//;
57     push @args, $content;
58   } elsif ( $method eq 'GET' ) {
59     $args[0] .= $ns->buildQuery( { @_ } );
60   }
61
62   my $auth = encode_base64( $self->option($prefix.'login'). ':'.
63                             $self->option($prefix.'password')    );
64   push @args, { 'Authorization' => "Basic $auth" };
65
66   $ns->$method( @args );
67   $ns;
68 }
69
70 sub ns_subscriber {
71   my($self, $svc_phone) = (shift, shift);
72
73   my $domain = $self->option('domain');
74   my $phonenum = $svc_phone->phonenum;
75
76   "/domains_config/$domain/subscriber_config/$phonenum";
77 }
78
79 sub ns_registrar {
80   my($self, $svc_phone) = (shift, shift);
81
82   my $domain = $self->option('domain');
83   my $countrycode = $svc_phone->countrycode;
84   my $phonenum    = $svc_phone->phonenum;
85
86   $self->ns_subscriber($svc_phone).
87     '/registrar_config/'. $self->ns_devicename($svc_phone);
88 }
89
90 sub ns_devicename {
91   my( $self, $svc_phone ) = (shift, shift);
92
93   my $domain = $self->option('domain');
94   my $countrycode = $svc_phone->countrycode;
95   my $phonenum    = $svc_phone->phonenum;
96
97   "sip:$countrycode$phonenum@$domain";
98 }
99
100 sub ns_dialplan {
101   my($self, $svc_phone) = (shift, shift);
102
103   my $countrycode = $svc_phone->countrycode;
104   my $phonenum    = $svc_phone->phonenum;
105
106   "/dialplans/DID+Table/dialplan_config/sip:$countrycode$phonenum@*"
107 }
108
109 sub ns_device {
110   my($self, $svc_phone, $phone_device ) = (shift, shift, shift);
111
112   #my $countrycode = $svc_phone->countrycode;
113   #my $phonenum    = $svc_phone->phonenum;
114
115   "/phones_config/". $phone_device->mac_addr;
116 }
117
118 sub ns_create_or_update {
119   my($self, $svc_phone, $dial_policy) = (shift, shift, shift);
120
121   my $domain = $self->option('domain');
122   my $countrycode = $svc_phone->countrycode;
123   my $phonenum    = $svc_phone->phonenum;
124
125   my( $firstname, $lastname );
126   if ( $svc_phone->phone_name =~ /^\s*(\S+)\s+(\S.*\S)\s*$/ ) {
127     $firstname = $1;
128     $lastname  = $2;
129   } else {
130     #deal w/unaudited netsapiens services?
131     my $cust_main = $svc_phone->cust_svc->cust_pkg->cust_main;
132     $firstname = $cust_main->get('first');
133     $lastname  = $cust_main->get('last');
134   }
135
136   # Piece 1 (already done) - User creation
137
138   my $ns = $self->ns_command( 'PUT', $self->ns_subscriber($svc_phone), 
139     'subscriber_login' => $phonenum.'@'.$domain,
140     'firstname'        => $firstname,
141     'lastname'         => $lastname,
142     'subscriber_pin'   => $svc_phone->pin,
143     'dial_plan'        => 'Default', #config?
144     'dial_policy'      => $dial_policy,
145   );
146
147   if ( $ns->responseCode !~ /^2/ ) {
148      return $ns->responseCode. ' '.
149             join(', ', $self->ns_parse_response( $ns->responseContent ) );
150   }
151
152   #Piece 2 - sip device creation 
153
154   my $ns2 = $self->ns_command( 'PUT', $self->ns_registrar($svc_phone),
155   );
156
157   if ( $ns2->responseCode !~ /^2/ ) {
158      return $ns2->responseCode. ' '.
159             join(', ', $self->ns_parse_response( $ns2->responseContent ) );
160   }
161
162   #Piece 3 - DID mapping to user
163
164   my $ns3 = $self->ns_command( 'PUT', $self->ns_dialplan($svc_phone),
165     'to_user' => $countrycode.$phonenum,
166     'to_host' => $domain,
167   );
168
169   if ( $ns3->responseCode !~ /^2/ ) {
170      return $ns3->responseCode. ' '.
171             join(', ', $self->ns_parse_response( $ns3->responseContent ) );
172   }
173
174   '';
175 }
176
177 sub ns_delete {
178   my($self, $svc_phone) = (shift, shift);
179
180   my $ns = $self->ns_command( 'DELETE', $self->ns_subscriber($svc_phone) );
181
182   #delete other things?
183
184   if ( $ns->responseCode !~ /^2/ ) {
185      return $ns->responseCode. ' '.
186             join(', ', $self->ns_parse_response( $ns->responseContent ) );
187   }
188
189   '';
190
191 }
192
193 sub ns_parse_response {
194   my( $self, $content ) = ( shift, shift );
195
196   #try to screen-scrape something useful
197   tie my %hash, Tie::IxHash;
198   while ( $content =~ s/^.*?<p>\s*<b>(.+?)<\/b>\s*(.+?)\s*<\/p>//is ) {
199     ( $hash{$1} = $2 ) =~ s/^\s*<(\w+)>(.+?)<\/\1>/$2/is;
200   }
201
202   %hash;
203 }
204
205 sub _export_insert {
206   my($self, $svc_phone) = (shift, shift);
207   $self->ns_create_or_update($svc_phone, 'Permit All');
208 }
209
210 sub _export_replace {
211   my( $self, $new, $old ) = (shift, shift, shift);
212   return "can't change phonenum with NetSapiens (unprovision and reprovision?)"
213     if $old->phonenum ne $new->phonenum;
214   $self->_export_insert($new);
215 }
216
217 sub _export_delete {
218   my( $self, $svc_phone ) = (shift, shift);
219
220   $self->ns_delete($svc_phone);
221 }
222
223 sub _export_suspend {
224   my( $self, $svc_phone ) = (shift, shift);
225   $self->ns_create_or_update($svc_phone, 'Deny');
226 }
227
228 sub _export_unsuspend {
229   my( $self, $svc_phone ) = (shift, shift);
230   #$self->ns_create_or_update($svc_phone, 'Permit All');
231   $self->_export_insert($svc_phone);
232 }
233
234 sub export_device_insert {
235   my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
236
237   #my $domain = $self->option('domain');
238   my $countrycode = $svc_phone->countrycode;
239   my $phonenum    = $svc_phone->phonenum;
240
241   my $device = $self->ns_devicename($svc_phone);
242
243   my $ns = $self->ns_device_command(
244     'PUT', $self->ns_device($svc_phone, $phone_device),
245       'line1_enable' => 'yes',
246       'device1'      => $self->ns_devicename($svc_phone),
247       'line1_ext'    => $countrycode.$phonenum,
248 ,
249       #'line2_enable' => 'yes',
250       #'device2'      =>
251       #'line2_ext'    =>
252
253       #'notes' => 
254       'server'       => 'SiPbx',
255       'domain'       => $self->option('domain'),
256
257       'brand'        => $phone_device->part_device->devicename,
258       
259   );
260
261   if ( $ns->responseCode !~ /^2/ ) {
262      return $ns->responseCode. ' '.
263             join(', ', $self->ns_parse_response( $ns->responseContent ) );
264   }
265
266   '';
267
268 }
269
270 sub export_device_delete {
271   my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
272
273   my $ns = $self->ns_device_command(
274     'DELETE', $self->ns_device($svc_phone, $phone_device),
275   );
276
277   if ( $ns->responseCode !~ /^2/ ) {
278      return $ns->responseCode. ' '.
279             join(', ', $self->ns_parse_response( $ns->responseContent ) );
280   }
281
282   '';
283
284
285 }
286
287
288 sub export_device_replace {
289   my( $self, $svc_phone, $new_phone_device, $old_phone_device ) =
290     (shift, shift, shift, shift);
291
292   #?
293   $self->export_device_insert( $svc_phone, $new_phone_device );
294
295 }
296
297 sub export_links {
298   my($self, $svc_phone, $arrayref) = (shift, shift, shift);
299   #push @$arrayref, qq!<A HREF="http://example.com/~!. $svc_phone->username.
300   #                 qq!">!. $svc_phone->username. qq!</A>!;
301   '';
302 }
303
304 1;