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 AGI, asterisk, CNAM, communication, Internet, Perl, SIP, VoIP | 9 Comments »
[...] 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 [...]
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……
[...] out this Perl script I found on Team Forrest’s website that leverages AGI (Asterisk Gateway Interface), a powerful interface that lets your [...]
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?
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
[...] 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): [...]
The Anywho query will not work anymore as their query structure has changed.
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!
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”;
}