Solved

Parsing a text file in Asterisk to used in an inbound IVR Campaign

Posted on 2008-10-10
24
660 Views
Last Modified: 2013-11-12
1.  When an inbound call is answered by my IVR campaign, I'd like to parse a text file to see if a 7 digit number exists before letting them into the survey.  Can you direct me to some samples that will parse an entire file (plain ascii text file) and look for the occurrence of a 7 digit number that the caller enters at the beginning of a survey IVR.

As an example.  "please enter your 7 digit customer number followed by the # button".  Store that number in a variable then parse a file and if it matches the record continue with the IVR.

2.  I need to make a recording in the IVR and then rename that recording to the 7 digit number plus the question number.   Say in Question 4 we ask them to tell us about their recent service experience at a dealership.   I'd like to make a recording and call it the Q4-"7 digit number".

0
Comment
Question by:rdelrosario
  • 13
  • 11
24 Comments
 
LVL 4

Expert Comment

by:palner
ID: 22692277
1. Create a perl script (like the code attached) and call it something like searchfile.pl
2. Add it to the agi-bin in var/lib/asterisk
3. Capture the 7 digits with a read or background, something like...

exten => s,n,Read(searchphone,SOUNDFILE,7,,1);variable searchphone will be 7 digits

4. Send that response to an AGI call

exten => s,n,AGI(searchfile.pl,${searchphone})

5. Check the output....

exten => s,n,GotoIf($[${MATH(${SEARCHCOUNT}>=1,i)}=TRUE]?found)


#!/usr/bin/perl -w

use strict;

$|=1;
 

my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; my $result = "";

my $string = ""; my $count = 0;
 

$string = $ARGV[0];

      

while(<STDIN>) {

	chomp;

	last unless length($_);

	if (/^agi_(\w+)\:\s+(.*)$/) {

		$AGI{$1} = $2;

	}

}
 

#Replace the searchfile.txt with the file name

open FILE, "<searchfile.txt";

my @line = <FILE>;

for (@lines) {

    if ($_ =~ /$string/) {

        $count = $count + 1;

    }

}
 

print qq(SET VARIABLE SEARCHCOUNT "$count"\n);

Open in new window

0
 
LVL 4

Expert Comment

by:palner
ID: 22692293
To record a 7 digit number.... (using the same read command)....

exten => s,n,Record(/tmp/Q4-${searchphone}:wav,3,20)
0
 

Author Comment

by:rdelrosario
ID: 22711505
I'm reviewing your information now and will likely have a quick follow-up question.  In the mean time, when you say add it to the agi-bin in asterisk.. are you saying all I have to do is copy the program to that directory.   Must I CHMOD or install any other component or run some other related command?  We are running trixbox and am not sure if any base software is needed to call the perl scripts.  Can you let me know what I'll need to make sure/test that I have sufficient files capable of running these perl scripts?

Thanks
0
 
LVL 4

Expert Comment

by:palner
ID: 22711715
the user you have running asterisk will need read/execute access to the script; so yes chmod. You will also need perl installed; which is most likely already installed.
0
 

Author Comment

by:rdelrosario
ID: 22712836
I created the file below and put it in the /var/lib/asterisk folder as you specified and called it searchinfo.pl and chmod as necessary.   The below dialplan is a sample with 1 question followed by the 7 digit account request to search for.  The following is the exact cut and paste of my fille:

; IVR RoadSide Test Survey
exten => 2222,1,Answer()
exten => 2222,n,set(TRYAGAIN=0)
exten => 2222,n(Q1START),NoOp(Begin Q1)
exten => 2222,n,Wait(.5)I
exten => 2222,n,SayAlpha(Q1)
exten => 2222,n,Read(Q1,,1,,,3)

exten => 2222,n,GotoIf($[${Q1} = 1]?Q2START)
exten => 2222,n,GotoIf($[${Q1} = 2]?Q2START)
exten => 2222,n,GotoIf($[${Q1} = 3]?Q2START)
exten => 2222,n,GotoIf($[${Q1} = 4]?Q2START)
exten => 2222,n,GotoIf($[${Q1} = 5]?Q2START)

exten => 2222,n,NoOp(User entered an invalid entry digits 1-5 allowed, restart Q2 otherwise hangup after 3 tries)
exten => 2222,n,Set(TRYAGAIN=$[${TRYAGAIN} + 1])
exten => 2222,n,GotoIf($[${TRYAGAIN} = 3]?ENDIT)
exten => 2222,n,Playback(vm-sorry)
exten => 2222,n,Goto(Q1START)

exten => 2222,n(Q2START),NoOp(Begin Q2)
exten => 2222,n,Read(searchphone,your-account,7,,1)
exten => 2222,n,AGI(searchfile.pl,${searchphone})
exten => 2222,n,GotoIf($[${MATH(${SEARCHCOUNT}>=1,i)}=TRUE]?found)
exten => 2222,n,PlayBack(no-info-about-number)
exten => 2222,n,Goto(Q2START)  ; ask to re-enter 7 digit account
exten => 2222,n(found),SayAlpha(FOUND)

exten => 2222,n(ENDIT),Playback(goodbye)
exten => 2222,n,Hangup()

*****************************  THE BELOW IS THE CLI OUTPUT OF THE ABOVE DIALPLAN *********************
I entered 1 for question 1 (Q1) then digits 1234567 for the searchphone variable.  the name of the .txt file is roadside.txt and is in the /etc/asterisk folder as roadside.txt.  Is the syntax right, am I missing a bracket or parenthesis?  Anyway.. here is the output of the CLI


    -- Executing Answer("SIP/9981-b7b26b10", "") in new stack
    -- Executing Set("SIP/9981-b7b26b10", "TRYAGAIN=0") in new stack
    -- Executing NoOp("SIP/9981-b7b26b10", "Begin Q1") in new stack
    -- Executing Wait("SIP/9981-b7b26b10", ".5") in new stack
    -- Executing SayAlpha("SIP/9981-b7b26b10", "Q1") in new stack
    -- Playing 'letters/q' (language 'en')
    -- Playing 'digits/1' (language 'en')
    -- Executing Read("SIP/9981-b7b26b10", "Q1||1|||3") in new stack
    -- Accepting a maximum of 1 digits.
    -- User entered '1'
    -- Executing GotoIf("SIP/9981-b7b26b10", "1?Q2START") in new stack
    -- Goto (from-internal,2222,17)
    -- Executing NoOp("SIP/9981-b7b26b10", "Begin Q2") in new stack
    -- Executing Read("SIP/9981-b7b26b10", "searchphone|your-account|7||1") in new stack
    -- Accepting a maximum of 7 digits.
    -- Playing 'your-account' (language 'en')
    -- User entered '1234567'
    -- Executing AGI("SIP/9981-b7b26b10", "searchfile.pl|1234567") in new stack
    -- Launched AGI Script /var/lib/asterisk/agi-bin/searchfile.pl
    -- AGI Script searchfile.pl completed, returning 0
    -- Executing GotoIf("SIP/9981-b7b26b10", "0?found") in new stack
    -- Executing Playback("SIP/9981-b7b26b10", "no-info-about-number") in new stack
    -- Playing 'no-info-about-number' (language 'en')
    -- Executing Goto("SIP/9981-b7b26b10", "Q2START") in new stack
    -- Goto (from-internal,2222,17)
    -- Executing NoOp("SIP/9981-b7b26b10", "Begin Q2") in new stack
    -- Executing Read("SIP/9981-b7b26b10", "searchphone|your-account|7||1") in new stack
    -- Accepting a maximum of 7 digits.
    -- Playing 'your-account' (language 'en')
    -- User disconnected
  == Spawn extension (from-internal, 2222, 18) exited non-zero on 'SIP/9981-b7b26b10'
    -- Executing Macro("SIP/9981-b7b26b10", "hangupcall") in new stack
    -- Executing ResetCDR("SIP/9981-b7b26b10", "w") in new stack
    -- Executing NoCDR("SIP/9981-b7b26b10", "") in new stack
    -- Executing GotoIf("SIP/9981-b7b26b10", "1?skiprg") in new stack
    -- Goto (macro-hangupcall,s,6)
    -- Executing GotoIf("SIP/9981-b7b26b10", "1?theend") in new stack
    -- Goto (macro-hangupcall,s,9)
    -- Executing Wait("SIP/9981-b7b26b10", "5") in new stack
  == Spawn extension (macro-hangupcall, s, 9) exited non-zero on 'SIP/9981-b7b26b10' in macro 'hangupcall'
  == Spawn extension (macro-hangupcall, s, 9) exited non-zero on 'SIP/9981-b7b26b10'
TrixPrimary2*CLI>


******************************************

The text file has the following in it.  Not sure how your perl text search program parses files and such, but the file looks like this.  It is attached as well for review:
[root@TrixPrimary2 asterisk]# vi roadside.txt
1234567
11111
22622
55555
14111
11111
~
~
~
~
~
~
"roadside.txt" 6L, 38C
*********************************

Any help regarding the code or what I might be missing would be great.                                              

0
 

Author Comment

by:rdelrosario
ID: 22712867
I'm sure you know this, but my first sentence in the last post stated I put the dialplan in the /var/lib/asterisk folder.. I meant that I put the searchfile.pl in there.  The file I mentioned was the dialplan. :)
0
 
LVL 4

Expert Comment

by:palner
ID: 22712969
Did you you change the perl script to match your new file name?

Also, put in the full location if it's better and make sure there's good permissions for it...

Remember this part:

#Replace the searchfile.txt with the file name

by default it's going to look in the agi-bin for the text file. If you have it in let's say tmp, change the file to /tmp/filename.txt (or whatever is appropriate).

Also, you can test the perl script itself first....

something like: perl /var/lib/asterisk/agi-bin/searchfile.pl 1234567

That will show you if there's any errors your system is having with the script.
0
 

Author Comment

by:rdelrosario
ID: 22712997
Sorry, here is the exact searchfile.pl cut and pasted with the path of my .txt file.   Am I missing anything syntax wise.

#!/usr/bin/perl -w
use strict;
$|=1;

my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; my $result = "";
my $string = ""; my $count = 0;

$string = $ARGV[0];

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

#Replace the searchfile.txt with the file name
open FILE, "</etc/asterisk/roadside.txt";
my @line = <FILE>;
for (@lines) {
    if ($_ =~ /$string/) {
        $count = $count + 1;
    }
}

print qq(SET VARIABLE SEARCHCOUNT "$count"\n);

                                                 
0
 

Author Comment

by:rdelrosario
ID: 22713034
Here is the output from manually running the program

[root@TrixPrimary2 sounds]# perl /var/lib/asterisk/searchfile.pl 1234567
Global symbol "@lines" requires explicit package name at /var/lib/asterisk/searchfile.pl line 21.
Execution of /var/lib/asterisk/searchfile.pl aborted due to compilation errors.


**  the file path is hardcoded in the searchfile.pl file so I don't believe I need to be in any specific directory unless I got the syntax messed up.
0
 
LVL 4

Expert Comment

by:palner
ID: 22713283
change:

my @line = <FILE>;


to:

my @lines = <FILE>;
0
 

Author Comment

by:rdelrosario
ID: 22714142
OK, that fixed the problem and SEARCHCOUNT is returning a 1 when the digits are found, but in the dial plan syntax, it still isn't matching.  Can you look at the syntax in there again to confirm I have the right brackets or paranthesis in the right places.  Do I need to do something to pipe the SEARCHCOUNT variable back into the asterisk environment.

Here is the perl run at unix:
[root@TrixPrimary2 asterisk]# perl /var/lib/asterisk/searchfile.pl 1234567

SET VARIABLE SEARCHCOUNT "1"    

Here is the snip of the code in my dialplan.

exten => 2222,n,GotoIf($[${MATH(${SEARCHCOUNT}>=1,i)}=TRUE]?found)
exten => 2222,n,PlayBack(no-info-about-number)
exten => 2222,n,Goto(Q2START)  ; ask to re-enter 7 digit account
exten => 2222,n(found),SayAlpha(FOUND)


**  DO I have to initialize or do something with the SEARCHCOUNT variable for it to be passed back to asterisk?
0
 

Author Comment

by:rdelrosario
ID: 22714187
The CLI states:
AGI Script searchfile.pl completed, returning 0
is this suppose to be returning the SEARCHCOUNT of 1?  If so I dont' understand the MATH routine.  Aren't we just checking for a SEARCHCOUNT value of 1?  I think I'm real close, but am missing something very minor I'm assuming.

Thanks
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 4

Expert Comment

by:palner
ID: 22714264
Please show what happens in the CLI after a match (completely including the gotoif statement)


If you only look for 1 and there's more than one match, you will fail. This is why you look for greater than or equal to 1.
0
 

Author Comment

by:rdelrosario
ID: 22714312
If this helps any to the last post I had....  when running the perl command line... for some reason I have to hit a carriage return (enter key) for the SET VARIABLE SEARCHCOUNT "1" shows on screen.  Could it be that the AGI call runs but actually doesn't finish... Do I need something to make a hard carriage return execute without manually hitting the key?

thanks
0
 
LVL 4

Expert Comment

by:palner
ID: 22714556
please post the out put from the cli like in ID:22712836.
0
 

Author Comment

by:rdelrosario
ID: 22714914
I'm sorry, I'm not familiar with the ID term you use.  The CLI output is posted above, but here it is again regarding the AGI execute:  My verbose is already at 25.  Do I need to set it higher to get the ID you speak of?

Executing Read("SIP/9981-b7b26b10", "searchphone|your-account|7||1") in new stack
    -- Accepting a maximum of 7 digits.
    -- Playing 'your-account' (language 'en')
    -- User entered '1234567'
    -- Executing AGI("SIP/9981-b7b26b10", "searchfile.pl|1234567") in new stack
    -- Launched AGI Script /var/lib/asterisk/agi-bin/searchfile.pl
    -- AGI Script searchfile.pl completed, returning 0
    -- Executing GotoIf("SIP/9981-b7b26b10", "0?found") in new stack
    -- Executing Playback("SIP/9981-b7b26b10", "no-info-about-number") in new stack
    -- Playing 'no-info-about-number' (language 'en')

0
 
LVL 4

Expert Comment

by:palner
ID: 22715259
The id is the id of your post here.

Are you sure that the user account used for trixbox has access/permission to the text file?
0
 

Author Comment

by:rdelrosario
ID: 22715342
Hmm.  Thats a good question.  I'm not sure if the asterisk user account is used for execution of a dialplan.   None the less, I'll chmod it to work with ugoa rwx.

I know I already asked, but can you confirm the syntax to the GotoIF Math execution line in your dialplan.  I used it exactly.  

Also, is there a debug line I can put in asterisk to see where its failing.   The AGI perl script seems to work fine other than the carriage return thingy I mentioned (again is that an issue).   I tried to "echo" the output of the SEARCHCOUNT variable in asterisk, but it didn't have a value.  Does this mean that the AGI didn't pass the value back to asterisk?   Anything I can add or try to find out what/where the problem is... again I think we're so close.   In the mean time, I'll make sure the rights are setup.
0
 
LVL 4

Expert Comment

by:palner
ID: 22715440
If the file cannot be opened, the script will fail and nothing will be added. If your test outside the dialplan shows SEARCHCOUNT then it will be there when the script runs scuccessfully. Yes, the Math is correct for the reasons stated above:

"If you only look for 1 and there's more than one match, you will fail. This is why you look for greater than or equal to 1."

You are checking if Searchcount is >= 1.
0
 

Author Comment

by:rdelrosario
ID: 22715578
The rights are correct.  Just to see if SEARCHCOUNT VALUE was being passed back to asterisk I added the following:

exten => 2222,n,GotoIf($[${SEARCHCOUNT} >= 1]?foundit)

It didn't go to the foundit section, but yet when running the perl script outside of asterisk it returns a value of 1.  So the perl script runs fine, but its not getting into asterisk.   what else do you think it could be?
0
 
LVL 4

Expert Comment

by:palner
ID: 22715657
exten => 2222,n,GotoIf($[${SEARCHCOUNT} >= 1]?foundit)

The about statement will fail... the math is needed.

run an agi debug during the session and post the results please.

Also, add something like this after the script:

2222,n,NoOp(Search Count ${SEARCHCOUNT})

Please be detailed here... why not post the exact script you have, the exact text file, the dialplan, etc so we can check for typo's. If the AGI is failing inside asterisk and working outside, 9x out of 10 it's the permissions. Also, I cannot emphasize enough the math is needed and works.
0
 

Author Comment

by:rdelrosario
ID: 22715769
I found out the problem....
Asterisk CLI output is very deceptive.   I know you mentioned to put the full file path name in the perl script, but I thought about putting that in the dial plan too.   That did the trick so my dialplan is now:

exten => 2222,n,AGI(/var/lib/asterisk/searchfile.pl,${searchphone})

just for kicks, I even spelled the path wrong or the file name wrong in the AGI call and the CLI output was always successful returning 0.  

So anyway, it looks to be working well with your help...  thanks.   I'll award the points, but I do have one question about the current search script.

I'll grant the points promptly, but I do have a followup question.  Do you have sample code or working code that will allow me to:  I'll grant another 500 points for the below:

1.  search a specific column in the file for a pattern entered by the Read command.
2.  Use the search found/matched in item 1) above to read a particular value in that record layout.  Specifically,  lets say we are looking for account # in column 1-7 of the file I've been working with and I want to playback a balance amount in column 75-85 of that record.

thanks
0
 
LVL 4

Accepted Solution

by:
palner earned 500 total points
ID: 22715829
have you thought instead about using mysql? Much better for that type of read and easy to integrate.
0
 

Author Comment

by:rdelrosario
ID: 22720599
I have some other proprietary programs that use flat file structures in place already which we've spent a lot of time on.  We could use mysql, but would rather stick to the native flat file for now.  With that said, I'll award the points now.  Can you give me the equivelent search samples for mysql to the above 7 digit AGI code we got working above along with searching specific columns from found records.  that would great to review.
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Implementing Avaya's One-X portal is pretty painless, until you want to deploy this to the Android and iPhone clients when these clients are outside of your network. The clients will also work within your local network. Here is our experience and so…
Almost all Internet protocol telephones have built-in switches at the back that allow you to connect your personal computer to one port and use the other port to connect your phone to to a Cisco switch.   Why we need to connect the PC to the pho…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now