9 use Net::HTTPS::Any qw(https_post https_get);
11 use FS::UID qw(adminsuidsetup);
12 use FS::Record qw(qsearchs);
18 freeside-cdr-conexiant-import -h -u username -p apikey [-v] freesideuser
20 Downloads any existing CDR files with the BilledCallsOnly flag and
21 imports records that have not been imported yet. Silently skips
22 records that have already been imported.
26 # should really be using a module for this
27 `which unzip` or die "can't find unzip executable";
29 my ($username,$password,$verbose);
31 "password=s" => \$password,
32 "username=s" => \$username,
33 "verbose" => \$verbose,
36 my $fsuser = $ARGV[-1];
38 die usage() unless $fsuser;
40 adminsuidsetup($fsuser);
42 my ( $page, $response, %reply_headers ) = https_post(
43 'host' => 'api.conexiant.net',
45 'path' => '/v1/Cdrs/SearchCdrsDownloads',
47 'Authorization' => 'Basic ' . MIME::Base64::encode("$username:$password",'')
52 die "Bad response from conexiant server: $response"
53 unless $response =~ /^200/;
55 my $result = decode_json($page);
57 die "Error from conexiant: " . ($result->{'ErrorInfo'} || 'No error message')
58 unless $result->{'Success'};
60 my $files = $result->{'Data'}->{'Result'};
62 die "Unexpected results from conexiant, not an array"
63 unless ref($files) eq 'ARRAY';
65 my $dir = $FS::UID::cache_dir. "/cache.". $FS::UID::datasrc;
66 my $ua = LWP::UserAgent->new;
68 # Download files are created automatically at regular frequent intervals,
69 # but they contain overlapping data.
71 # FS::cdr::conexiant automatically skips previously imported cdrs,
72 # though if it does so for all records in a file,
73 # then batch_import thinks the file is empty
74 foreach my $file (@$files) {
75 next unless $file->{'BilledCallsOnly'};
76 my $cdrbatch = 'conexiant-' . $file->{'Identifier'};
77 # files that were "empty" will unfortunately be re-downloaded,
78 # but the alternative is to leave an excess of empty batches in system,
79 # and re-downloading is harmless (all files expire after 48 hours anyway)
80 if (qsearchs('cdr_batch',{ 'cdrbatch' => $cdrbatch })) {
81 print "$cdrbatch already imported\n" if $verbose;
85 print "Downloading $cdrbatch\n".
86 " Created ".$file->{'CreatedOn'}."\n".
87 " Start ".$file->{'QueryStart'}."\n".
88 " End ".$file->{'QueryEnd'}."\n".
89 " Link ".$file->{'ValidLink'}."\n";
91 my $zfh = new File::Temp( TEMPLATE => 'conexiant.XXXXXXXX',
95 or die "can't open temporary file to store download: $!\n";
96 my $cfh = new File::Temp( TEMPLATE => 'conexiant.XXXXXXXX',
100 or die "can't open temporary file to unzip download: $!\n";
101 # yeah, these files ain't secured in any way
102 my $response = $ua->get($file->{'ValidLink'}, ':content_file' => $zfh->filename);
103 unless ($response->is_success) {
104 die "Error downloading $cdrbatch: ".$response->status_line;
106 my $zfilename = $zfh->filename;
107 print $cfh `unzip -p $zfilename 'Conexiant Cdrs.csv'`;
109 print "Importing batch $cdrbatch\n" if $verbose;
110 my $error = FS::cdr::batch_import({
111 'batch_namevalue' => $cdrbatch,
112 'file' => $cfh->filename,
113 'format' => 'conexiant'
115 if ($error eq 'Empty file!') {
116 print "File contains no new cdrs, no batch created\n" if $verbose;
118 } elsif ($verbose && !$error) {
119 print "File successfully imported\n";
121 die "Error importing $cdrbatch: $error" if $error;