Team Forrest offers complete Internet Consulting services, specializing in VoIP and Asterisk solutions. Contact us today to see how we can help.

Using AGI to get Caller ID Name CNAM

Everyone has them — and here’s Team Forrest’s version of a Caller ID to Name (CNAM, CIDNAME, etc.) lookup using AnyWho, Google, and 411.com. The first file is the calleridname.pl:

UPDATE April 4, 2009 — Frank (user comment) let us know that AnyWho had changed their website. As a result the code has been updated. Thanks Frank!

#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
$|=1;
sub trim($);

my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; my $result = ""; my $cidnum = ""; my $cidname = "";
my $npa = ""; my $nxx = ""; my $station = ""; my $name = "";

$cidnum = $ARGV[0];

while(<STDIN>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$AGI{$1} = $2;
}
}

my $AnyWho = '1' ;
my $Google = '1' ;
my $www411 = '1' ;

if(substr($cidnum,0,1) eq '1'){
$cidnum=substr($cidnum,1);
}

if(substr($cidnum,0,2) eq '+1'){
$cidnum=substr($cidnum,2);
}

if ($cidnum =~ /^(\d{3})(\d{3})(\d{4})$/) {
$npa = $1;
$nxx = $2;
$station = $3;
}
elsif($cidnum =~/\<(\d{3})(\d{3})(\d{4})\>/){
$npa = $1;
$nxx = $2;
$station = $3;
}
else {
print qq(VERBOSE "ERROR: unable to parse caller id" 2\n);
exit(0);
}

if ($AnyWho > '0') {
print qq(VERBOSE "STATUS: checking AnyWho for name lookup" 2\n);
if ($name = &anywho_lookup ($npa, $nxx, $station)) {
$cidname = $name;
print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
print qq(VERBOSE "STATUS: AnyWho said name was $cidname " 2\n);
exit(0);
}
else {
print qq(VERBOSE "STATUS: unable to find name with AnyWho" 2\n);
}
}
else {
print qq(VERBOSE "STATUS: AnyWho lookup disabled" 2\n);
}

if ($Google > '0') {
print qq(VERBOSE "STATUS: checking Google for name lookup" 2\n);
if ($name = &google_lookup ($npa, $nxx, $station)) {
$cidname = $name;
print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
print qq(VERBOSE "STATUS: Google said name was $cidname " 2\n);
exit(0);
}
else {
print qq(VERBOSE "STATUS: unable to find name with Google" 2\n);
}
}
else {
print qq(VERBOSE "STATUS: Google lookup disabled" 2\n);
}

if ($www411 > '0') {
print qq(VERBOSE "STATUS: checking www411 for name lookup" 2\n);
if ($name = &www411_lookup ($npa, $nxx, $station)) {
$cidname = $name;
print qq(SET VARIABLE CALLERID\(name\) "$cidname"\n);
print qq(VERBOSE "STATUS: www411 said name was $cidname " 2\n);
exit(0);
}
else {
print qq(VERBOSE "STATUS: unable to find name with www411" 2\n);
}
}
else {
print qq(VERBOSE "STATUS: www411 lookup disabled" 2\n);
}

print qq(SET VARIABLE CALLERID\(name\) "$cidnum"\n);
print qq(VERBOSE "STATUS: Unknown name for $cidnum " 2\n);
exit(0);

sub anywho_lookup {
my ($npa, $nxx, $station) = @_;
my $ua = LWP::UserAgent->new( timeout => 45);
my $URL = 'http://whitepages.anywho.com/results.php?ReportType=33';
$URL .= '&qnpa=' . $npa . '&qp=' . $nxx . $station;
$ua->agent('AsteriskAGIQuery/1');
my $req = new HTTP::Request GET => $URL;
my $res = $ua->request($req);
if ($res->is_success()) {
if ($res->content =~ /Find More Information for (.*)<\/a>/) {
my $listing = $1;
return $listing;
}
}
return "";
}

sub google_lookup {
my ($npa, $nxx, $station) = @_;
my $ua = LWP::UserAgent->new( timeout => 45);
my $URL = 'http://www.google.com/search?rls=en&q=phonebook:' .  $npa . $nxx . $station . '&ie=UTF-8&oe=UTF-8';
$ua->agent('AsteriskAGIQuery/1');
my $req = new HTTP::Request GET => $URL;
my $res = $ua->request($req);
if ($res->is_success()) {
if ($res->content =~ /<font size=-2><br><\/font><font size=-1>(.+)<font color=green>/) {
my $temp = $1;
my $clidname = "";
if ( $temp =~ /(.+)<font color=green>/o ) {
$clidname = substr($1, 0, -3);
} else {
$clidname = substr($temp, 0, -3);
}
if ($clidname =~ /<a href(.+)\//) {
$clidname = $1 ;
if ($clidname =~ />(.+)</) {
$clidname = $1 ;
}
}
return $clidname;
}
}
return "";
}

sub www411_lookup {
my ($npa, $nxx, $station) = @_;
my $ua = LWP::UserAgent->new( timeout => 45);
my $URL = 'http://www.411.com/search/Reverse_Phone?phone=' .  $npa . $nxx . $station;
$ua->agent('AsteriskAGIQuery/1');
my $req = new HTTP::Request GET => $URL;
my $res = $ua->request($req);
if ($res->is_success()) {
if ($res->content =~ /Location: <strong>(.*)<\/strong>/s) {
my $temp = $1;
my $clidname = "";
$temp =~ s/&\;/&/g;
$temp =~ s/%20/ /g;
$clidname = $temp;
return $clidname;
}
}
return "";
}

This perl script will work well as an AGI script — checking AnyWho, Google, and then 411 for a caller’s name or location. If all else fails, the callerid name is set as the callerid number.

The perl script was designed to only use the Internet with minimal installation; so it will work without a database, Perl Asterisk module, or locally hosted NPA / NXX (phone number to region) file.

Team Forrest recommends using a subroutine context to get the callerid when needed; calling the script with either a GoSub or GosubIf command, such as:

exten => s,n,Gosub(cidname-lookup,s,1)
exten => s,n,dial(${PHONE},30,t)
...

...
[cidname-lookup]
exten => s,1,NoOp(looking up callerid name)
exten => s,n,GotoIf($["foo${CALLERID(NAME)}" = "foo" ]?getname)
exten => s,n,GotoIf($["${CALLERID(NAME)}" = "${CALLERID(NUM)}" ]?getname)
exten => s,n,NoOp(caller id name exists as ${CALLERID(NAME)})
exten => s,n,Return
exten => s,n(getname),AGI(calleridname.pl,${CALLERID(NUM)})
exten => s,n,NoOp(Caller ID Name is now ${CALLERID(NAME)})
exten => s,n,Return

Enjoy the file (download here) and remember, Team Forrest is here to assist you will all of your Asterisk, VoIP, or technical needs.

Posted: January 5th, 2009 | Filed under: VoIP , , , , , , , | 9 Comments »

9 Comments on “Using AGI to get Caller ID Name CNAM”

  1. 1 Asterisk Script: Caller ID Name CNAM Lookup | VoIP Tech Chat said at 11:09 am on January 6th, 2009:

    [...] perl script can be downloaded here, or code viewed online from Team Forrest’s website. There are many, many types of these scripts available online, and using Google, a VoIP enabled [...]

  2. 2 VoIP & Gadgets Blog said at 11:08 am on January 7th, 2009:

    CNAM (CallerID with Name) on Asterisk using Reverse Phone number lookup…

    CallerID is cool, but CallerID with Name (CNAM), — also known as Calling NAMe — is where it’s at. When you go with a traditional phone provider (non-VoIP) they’ll often offer you CallerID with Name for an additional fee. But……

  3. 3 CNAM (CallerID with Name) on Asterisk using Reverse Phone number lookup said at 11:56 am on January 7th, 2009:

    [...] out this Perl script I found on Team Forrest’s website that leverages AGI (Asterisk Gateway Interface), a powerful interface that lets your [...]

  4. 4 mulderlr said at 4:04 pm on March 17th, 2009:

    the google phonebook and anywho never work. Google returns a 403 forbidden every time because using scripts to access its database are against its terms of service. 411.com returns a city and state only on anything it has a listing for, and I haven’t seen anywho return any results for me yet either. I know beggars can’t be choosers, but does anyone actually have this script working?

  5. 5 Team Forrest said at 4:11 pm on March 17th, 2009:

    Mulderlr,

    This works for us consistently. Google will block it if you are hammering it, but I certainly assume that’s not the case here. Anywho also works for us. Why not give us a shout (use the contact page) and let’s see if we can’t help you with this.

    Team Forrest

  6. 6 Geeky Item of the Day - Free CNAM | Fred Posner dot com said at 2:10 pm on March 27th, 2009:

    [...] Since I don’t like installing the module, don’t want to install a local lookup table, and don’t wish to cache CID names in a database, I’ve modified publicly available scripts as follows (also, check up the write up on Team Forrest, with a little more detail): [...]

  7. 7 Frank said at 3:26 pm on April 4th, 2009:

    The Anywho query will not work anymore as their query structure has changed.

  8. 8 Team Forrest said at 4:19 pm on April 4th, 2009:

    Frank, you’re 100% correct. Anywho has changed… this is the hack:

    sub anywho_lookup {
    	my ($npa, $nxx, $station) = @_;
    	my $ua = LWP::UserAgent->new( timeout => 45);
    	my $URL = 'http://whitepages.anywho.com/results.php?ReportType=33';
    	$URL .= '&qnpa=' . $npa . '&qp=' . $nxx . $station;
    	$ua->agent('AsteriskAGIQuery/1');
    	my $req = new HTTP::Request GET => $URL;
    	my $res = $ua->request($req);
    	if ($res->is_success()) {
    		if ($res->content =~ /Find More Information for (.*)< \/a>/) {
    			my $listing = $1;
    			return $listing;
    		}
    	}
    	return "";
    }

    And I will update the post… Thanks!

  9. 9 Joseph Barnes said at 10:34 pm on April 21st, 2009:

    Changed again This retrieves the info but I haven’t parsed it out yet.
    sub anywho_lookup {
    my ($npa, $nxx, $station) = @_;
    my $ua = LWP::UserAgent->new( timeout => 45);
    my $URL = ‘http://whitepages.anywho.com/results.php?ReportType=33&refer=2938&adword=ANYWHO.COM&qi=0&qk=10′;
    #$URL .= ‘&qnpa=’ . $npa . ‘&qp=’ . $nxx . $station;
    $URL .=
    ‘&qnpa=’. $npa .
    ‘&qnpanxx=’. $npa . $nxx .
    ‘&qnpanxx7=’. $npa . $nxx . substr($station,1,1) .
    ‘&qnxx=’ . $nxx .
    ‘&qp=’. $nxx . $station .
    ‘&qstation=’.$station .
    ‘&PHPSESSID=’ . ‘626da7c88dfce19b235ce7088a96a336′;
    $ua->agent(’AsteriskAGIQuery/1′);
    my $req = new HTTP::Request GET => $URL;
    my $res = $ua->request($req);
    if ($res->is_success()) {
    print $res->content;
    if ($res->content =~ /Find More Information for (.*)/) {
    my $listing = $1;
    return $listing;
    }
    }
    return “”;
    }

    Have you used the whitepages api? Net::Whitepages
    I’ve tried to get it working
    my $White_Pages = Net::WhitePages->new( TOKEN => ‘12345′, api_key => ‘mykey’ );
    my $res = $White_Pages->reverse_phone( phone => “7990989890″ );
    print $res;

    What is this TOKEN for? Also where am I supposed to use my api_key?

    What about WWW::WhoCallsMe
    I put in my listed number and it never finds it.

    use WWW::WhoCallsMe;
    my $who = WWW::WhoCallsMe->new;

    my $number = ‘9870709989′;
    my $calledme = $who->fetch($number);
    if ($calledme->{listed})
    {
    my $name = $calledme->{name};
    print “The number $number is listed. “;
    print “It seems that $name was calling.” if $name;
    print “I don’t know who was calling, though.” unless $name;
    print “\n”;
    }
    else
    {
    print “This number is not listed.\n”;
    }


Leave a Reply