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 penny-pinching Asterisk & VoIP fans want CallerID with Name too. Unfortunately, too often the SIP trunks or traditional PSTN trunks (analog, T1/E1) connected to your Asterisk IP-PBX don't provide CallerID with Name - just regular CallerID (number only). So how do we solve this dilemma?Well, Asterisk sits on an IP network, which of course means it can access the Internet. With access to the Internet, "in theory" a special Asterisk script can take the CallerID number, perform a reverse lookup on AnyWho, Google, and 411.com and then change the CallerID data string before it gets passed to the Asterisk extension.
Well, theory is all well and good, but has it been done? Oh yes it has!
Check out this Perl script I found on Team Forrest's website that leverages AGI (Asterisk Gateway Interface), a powerful interface that lets your programmatically control Asterisk.
Calling the CallerID with Name Perl script (calleridname.pl) is as simple as calling this single line of code:
exten => s,n(getname),AGI(calleridname.pl,${CALLERID(NUM)}) Here's the calleridname.pl script:
#!/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://www.anywho.com/qry/wp_rl';
$URL .= '?npa=' . $npa . '&telephone=' . $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 =~ /<!-- listing -->(.*)<!-- \/listing -->/s) {
my $listing = $1;
if ($listing =~ /<B>(.*)<\/B>/) {
my $clidname = $1;
return $clidname;
}
}
}
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 "";
} For more details, head on over here.



Technorati
Del.icio.us
Slashdot
Digg
twitter
Great code and it looks so familiar. Attribution is a wonderful thing. If you use someone else's term paper, at least give them credit. And this isn't directed toward you, Tom!
In fact, this code includes numerous chunks of code that several Nerd Vittles' contributors wrote several years ago coupled with more recent PERL code from Titanous. For some more current and more flexible CallerID solutions, here are some links:
http://bestof.nerdvittles.com/applications/callerid/
http://pbxinaflash.com/forum/showthread.php?t=65
http://pbxinaflash.com/forum/showthread.php?t=2919
What's ironic is that I thought this code might have existed elsewhere. Performing reverse number lookup is such an obvious thing to do on Asterisk. So I googled "asterisk callerid" and your site came up on Page 1.
callerid+Asterisk Google Search
Your 'Asterisk CallerID on Steroids: Here’s How' article came up. I checked it out, but it had nothing to do with reverse number lookup. Tried a few other searches but came up empty. Though I didn't try googling pieces of the source code. Maybe would have had a 'hit' that way.
I definitely want to give proper attribution and credit, so thanks Ward for providing some insight to who created this code, as well as links to more info.
.., I cant understand your codes, though i agree that the usage of CNAM is really helpful..
I appreciate the links regarding the flexible caller ID solutions.