[howto] Lookup caller name or area code

I expect this as easy as falling off a log for most of you dialplanners but it may not be for some newbies, so here goes.

The problem:
In the UK, although most phone numbers have a total of 11 digits, we have variable length area codes. For example, London numbers begin 020, Manchester numbers start 0161, Warrington numbers begin 01925 and Wigton numbers start 016973.

Importing the area codes:
First we need to generate a list of area codes and then import them into Asterisk. The definitive list is available from Ofcom. But we need to get this into the Asterisk database. I made heavy use of the macro facility in TextPad to turn this list into a script that I could run on the Asterisk server. While I was about it, I cut out all the codes marked as ‘expansion’ or ‘not in use’ and added a few more international prefixes. For the lazy, I’ve made this available here. Then I copied this to the Asterisk server using PSFTP and then ran it with the command ‘bash areacode.sh’. You can confirm the database is set up by typing ‘database show areacode’ at the Asterisk prompt.

Lookup area code:
Because of its variable length, looking up the area code from the caller ID requires a little ingenuity. Here is some of the code that handles our incomming calls. First it checks to see we have a caller ID number longer than 4 digits. If not we flag an invalid CID and pass it on to the office. Next we check to see if the number is in our own list of customers. If it is then their name is used as the CID name and the call passed on. If both of these fail then we look up the area code. We start with the first 6 digits of the CID number and try to match those in the areacode database. If no match is found then we drop to 5 digits and so on down to 3. If there is still no match then the CID name is set to ‘unknown’ and the number logged for later analysis.

[code][macro-incomming]
exten => s,n,Answer

; check we have a sensible caller id number
exten => s,n,Set(TRY=INVALID CID)
exten => s,n,Set(NUM=${CALLERID(num)})
exten => s,n,GotoIf($[${LEN(${NUM})} < 5]?pass) ; jump if we have a short caller ID

; if we can, lookup name in our own list
exten => s,n,Set(TRY=${DB(cidname/${NUM})})
exten => s,n,GotoIf($[${LEN(${TRY})} > 0]?pass) ; jump if we know the caller

; lookup area code (match first 6 digits and work down to 3)
exten => s,n,Set(DIG=6)
exten => s,n,While($[${DIG} > 2])
exten => s,n,Set(NUM=${NUM:0:${DIG}})
exten => s,n,Set(TRY=${DB(areacode/${NUM})})
exten => s,n,GotoIf($[${LEN(${TRY})} > 0]?pass) ; jump if we know the area code
exten => s,n,Set(DIG=$[${DIG} - 1])
exten => s,n,EndWhile

; record unknown area code
exten => s,n,Set(DB(unknown/${TIMESTAMP})=${CALLERID})
exten => s,n,Set(TRY=UNKNOWN AREA)

; pass call thru to office
exten => s,n(pass),Set(CALLERID(name)=${TRY})
exten => s,n,Background(our/u1) ; "Welcome to our company…"
exten => s,n,Queue(Qoffice,tr,20)
exten => s,n,Background(our/u2) ; "Trying more phones"
exten => s,n,Queue(Qall,tr,10)
exten => s,n,Background(our/u3) ; "Office hours are…"
exten => s,n,VoiceMail(s00@default)
exten => s,n,Hangup[/code]