Copying Switchvox Phonebooks

One of the powerful features of Switchvox is its ability for each user to have their own phonebooks. Quick and easy dialing and monitoring, both on the phone and in Switchboard. Sometimes, however, it's really nice to be able to copy a phonebook from one user to another. Maybe it's a change in job and responsibilities, or maybe there's a master corporate contact list that needs to be distributed to a bunch of users.

The Switchvox API is a very powerful interface into Switchvox. What if we could marry the need to copy phonebooks with the API? Well, it's already in there and the code is remarkably simple!

Here is some sample code written in Perl that makes copying phonebooks a piece of cake. It has been tested both on Linux and on Mac OS, so it works on a wide variety of platforms. In the header is some information about Perl modules that need to be installed.

There is a single option for the script, -A, which simply tells the script that you want to use Switchvox administrative credentials to make the copy, rather than the user/extension owner credentials. The script will prompt for the Switchvox IP address, and will walk you through the rest of the copy process. It is important to realize that the destination phonebook must already exist. Give it a try, what do you have to lose?


#! /usr/bin/perl
#
# copies Switchvox phonebook contents from one user to another.
# will prompt for proper credentials.
# -A option will prompt for administrative credentials
#
#
# requires the following packages to be installed:
#   perl
#   perl-XML-Simple
#   perl-Crypt-SSLeay
#   perl-CPAN
#
# install the switchvox api code with
#   cpan -i Switchvox::API
#
#

use strict;
use Switchvox::API;
use LWP::Simple;
use Getopt::Std;
use Term::ReadPassword;

$|=1;
my $SV;

$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'}=0;

our ($opt_A);
getopts('A');

sub string_fix_up {
    my ($str) = @_;

    $str =~ s/\(/\\\(/g;
    $str =~ s/\)/\\\)/g;

    return($str);
}


sub user_prompt {
    my($prompt, $hide) = @_;
    my $rc;

    if($hide) {
	$rc = read_password($prompt);
    } else {
        print $prompt;
        $rc = <>;
        chomp $rc;
    }

    return($rc);
}

sub get_extension_account_id {
    my ($ext) = @_;
    my @exts = ($ext);
    my $rc = 0;
    my $method = 'switchvox.users.extensions.getInfo';

    my $response = $SV->api_request(
        method => $method,
        parameters =>
        {
            extensions =>
                { 'extension' => [ @exts ] },
        }
        );

    if($response->{api_status} eq 'success')
    {
        my $extensions = $response->{api_result}{response}[0]{result}[0]{extensions}[0]{extension};
        foreach my $extension (@$extensions)
        {
            $rc = $extension->{account_id};
        }
    }
    else
    {
        print "$method Errors:\n";
        foreach my $error ( @{$response->{api_errors}} )
        {
            print "-Code:$error->{code}, Message: $error->{message}\n";
        }
        die;
    }

  return($rc);
}



sub get_phonebook_list
{
    my ($account_id) = @_;
    my %phonebooks;
    my $method = 'switchvox.users.phonebooks.getList';

    my $response = $SV->api_request(
	method => $method,
	parameters => 
	{
	  account_id => $account_id,
	}
	);
    
    if($response->{api_status} eq 'success')
    {
	my $pbs = $response->{api_result}{response}[0]{result}[0]{phonebooks}[0]{phonebook};
        foreach my $pb (@$pbs)
        {
	    $phonebooks{$pb->{id}} = $pb->{name};
        }
    }
    else
    {
	print "$method Encountered Errors:\n";
	foreach my $error ( @{$response->{api_errors}} )
	{
	    print "-Code:$error->{code}, Message: $error->{message}\n";
	}
	die;
    }

    return %phonebooks;
}


sub get_phonebook_contents
{
    my ($account_id, $pb_id) = @_;
    my @pb_entries = ();
    my $method = 'switchvox.users.phonebooks.getInfo';

    my $response = $SV->api_request(
	method => $method,
	parameters => 
	{
	  account_id => $account_id,
	  phonebook_id => $pb_id,
	});

    if($response->{api_status} eq 'success')
    {
        my $entries = $response->{api_result}{response}[0]{result}[0]{phonebook}[0]{entries}[0]{entry};
        # print "==> " . $response->{_content} . "\n\n";
        foreach my $entry (@$entries)
        {
            my $pb_entry = {
                    extension => $entry->{extension},
                    extension_type => $entry->{extension_type},
                    display => $entry->{display},
                    permission_type => $entry->{permission_type}};
            $pb_entries[++$#pb_entries] = $pb_entry;
        }
    }
    else
    {
	print "$method Encountered Errors:\n";
	foreach my $error ( @{$response->{api_errors}} )
	{
	    print "-Code:$error->{code}, Message: $error->{message}\n";
	}
	die;
    }
 
    return(@pb_entries);
}

sub copy_phonebook_entries
{
    my $account_id = $_[0];
    my $pb_id = $_[1];
    my @entries = @{$_[2]};
    my $method = 'switchvox.users.phonebooks.entries.add';

    foreach my $entry (@entries) 
    {
	my %command;
	if(($entry->{extension_type} eq 'sip') or 
	   ($entry->{extension_type} eq 'zap'))
	{
            %command = (
       	        method => $method,
	        parameters => 
	        {
	          account_id => $account_id,
	          phonebook_id => $pb_id,
	          entry_type => 'extension',
	 	  extension => $entry->{extension},
		  permission_type => $entry->{permission_type},
	        });
	} 
	elsif($entry->{extension_type} eq 'external')
	{
            %command = (
       	        method => $method,
	        parameters => 
	        {
	          account_id => $account_id,
	          phonebook_id => $pb_id,
	          entry_type => $entry->{extension_type},
	 	  number => $entry->{extension},
		  name => $entry->{display},
	        });
	}
	else # external
	{
	    print("Skipping: " . $entry->{display} . " of type " .
		  $entry->{extension_type} . "\n");
	    next;
            %command = (
       	        method => $method,
	        parameters => 
	        {
	          account_id => $account_id,
	          phonebook_id => $pb_id,
	          entry_type => $entry->{extension_type},
	 	  extension => $entry->{extension},
		  permission_type => $entry->{permission_type},
	        });
	}

        my $response = $SV->api_request(%command);

        if($response->{api_status} eq 'success')
        {
	  print("Added: " . $entry->{display} . "\n");
        }
	else
        {
	    my $kill_me = 0;
	    foreach my $error ( @{$response->{api_errors}} )
	    {
              if($error->{code} eq 15688)
              {
	  	  print("Skipping: " . $entry->{display} . 
			"--already exists\n");
              }
	      else
	      {
	          if(!$kill_me)
		  {
		      $kill_me = 1;
    	              print "$method Encountered Errors:\n";
		  }
	          print "-Code:$error->{code}, Message: $error->{message}\n";
	      }
	    }
	    die if($kill_me);
        }
    }
}

my $admin_user;
my $admin_pass;
my $sv_user;
my $sv_pass;
my $sv_address;

$sv_address = user_prompt("Enter Switchvox address: ", 0);

if($opt_A)
{
    $admin_user = user_prompt("Enter admin userid: ", 0);
    $admin_pass = user_prompt("Enter admin password: ", 1);
}

my $from_ext = user_prompt("Enter extension to get phonebook FROM: ", 0);

if($opt_A)
{
    $sv_user = $admin_user;
    $sv_pass = $admin_pass;    
}
else
{
    $sv_pass = user_prompt("Enter numeric password for extension $from_ext: ", 1);

    $sv_user = $from_ext;
}

print "\n";

$SV = new Switchvox::API(
    hostname => $sv_address,
    username => $sv_user,
    password => $sv_pass);

my $from_account_id = get_extension_account_id($from_ext);
my %phonebooks = get_phonebook_list($from_account_id);

my $prompt = "Enter the number for the SOURCE phonebook:\n";
foreach my $i (sort keys %phonebooks) 
{
    $prompt .= "$i: " . $phonebooks{$i} . "\n";
}
my $source_pb = user_prompt($prompt, 0);

my @source_entries = get_phonebook_contents($from_account_id, $source_pb);

my $to_ext = user_prompt("Enter extension to send phonebook TO: ", 0);

if(!$opt_A)
{
    $sv_pass = user_prompt("Enter numeric password for extension $to_ext: ", 1);

    $SV = new Switchvox::API(
        hostname => $sv_address,
        username => $to_ext,
        password => $sv_pass);
}

print "\n";

my $to_account_id = get_extension_account_id($to_ext);
my %phonebooks = get_phonebook_list($to_account_id);

$prompt = "Enter the number for the DESTINATION phonebook:\n";
foreach my $i (sort keys %phonebooks) 
{
    $prompt .= "$i: " . $phonebooks{$i} . "\n";
}
my $dest_pb = user_prompt($prompt, 0);

print "\n";

copy_phonebook_entries($to_account_id, $dest_pb, \@source_entries);

print "Done.\n";