AEL Example Snippets

This Page intends to provide some examples on how to use the Asterisk Extension Language (AEL) combined with the applications and functions to create powerful dialplans.

String Manipulation


Since Asterisks Expression Evaluator is very advanced, we can easily use it to mangle strings (asterisk/docs/README.variable).

Adding / Removing items from delimited Strings


Lets assume we want to have a String containing elements somehow delimted, we can easily produce some macros to add and remove elements from those strings:


macro ael-remove-from-string(string,item,delim) {
        Set(left=$[ "${${string}}" : "\(.*\)[${delim}]*${item}[${delim}]*.*" ]);
        Set(right=$[ "${${string}}" : ".*[${delim}]*${item}[${delim}]*\(.*\)" ]);
        Set(new=${left}${right});

        if ( "${right}" = "" ) {
                Set(new=$[ "${new}" : "\(.*\)[${delim}]$" ]);
        };

        Set(${string}=${new});
};


macro ael-add-to-string( string, add , delim ) {
        Set(${string}=${${string}}${delim}${add});
        Set(${string}=$[ "${${string}}" : "[${delim}]*\(.*\)" ]);
} ;



These macros should be used like:


Set(teststring=item1);
&ael-add-to-string(teststring,item2,&);
&ael-add-to-string(teststring,item3,&);
--> teststring=item1&item2&item3 now
&ael-remove-from-string(teststring,item2,&);
--> teststring=item1&item3 now
&ael-remove-from-string(teststring,item1,&);
--> teststring=item3 now


The Telemarketing Torture scripts in AEL format:

See Asterisk AEL Telemarketer Torture.


Loop and Conditional test — AEL2




macro exten-gen(name,pword)
{
if( ${DB_EXISTS(org/${GroupID}/${name}/secret)} = 0 )
goto other|nomatch|begin;
if( ${DB(org/${GroupID}/${name}/secret)}foo != ${pword}foo )
goto other|nomatch|begin;

}

context other {
nomatch => {
begin:
NoOp(Hello!);
switch(${DIALSTATUS}) // watch out for spaces between the ( )'s
{
case BUSY:
NoOp(wow);
case TORTURE:
NoOp(woow);
}
NoOp(woohoo);
}
}

context testloop {
includes {
other|16:00-23:59|m0n-fri|*|*; // new to AEL2
}

1 => {
for (x=0; ${x} < 3; x=${x} + 1) {
Verbose(x is ${x} !);
if( ${x} = 1 )
continue;
if( ${x} = 2 )
break;
}
ifTime(14:00-25:00|sat-sun|*|*) { // new to AEL2
BackGround(Hello);
} else
BackGround(Sorry);
NoOp(This is a totally useless NOOP);
}
2 => {
y=10;
while (${y} >= 0) {
Verbose(y is ${y} !);
if( ${y} = 1 )
continue;
if( ${y} = 2 )
break;
if( ${y} = 3 )
return; // new to AEL2
y=${y}-1;
}
}
regexten hint(nasty/Thingy) 3 => {
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;

y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
y=${y}-1;
}
}
}
4 => {
y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;
for (z=0; ${z} < 17; z=${z} + 1)
{
Verbose(z is ${z} !);
Verbose(z is ${z} !);
if( ${z} = 4 )
break;
if( ${z} = 5 )
continue;
if( ${z} = 6 )
return;
Verbose(z is ${z} !);
Verbose(z is ${z} !);
}

}
y=${y}-1;
}
}
5 => {
&exten-gen(axel,brain);
}
}



Using the Asterisk database for CallerID info — AEL2


This macro will use/set the callerid on an incoming call, based on what's in the database, and what's in the callerID info.
It will also store the incoming CID in the database, under 'cidname'.


macro fillcidname()
{
if( "${CALLERID(num)}" = "" ) // nothing to work with, quit!!!
return;
cidn=${DB(cidname/${CALLERID(num)})};
if( "${CALLERID(name)}" != "" )
{
if( ("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "0" ) // if the entry isn't in the database,
// or if an entry exists, and it's "Privacy Manager", and the callerid isn't "privacy manager"
{ // In other words, let's put the callerid into the DB, but only if it's not already set, or just set to "privacy manager".
DB(cidname/${CALLERID(num)})=${CALLERID(name)}; // then set or override what's in the DB, if it's a dumb "Privacy Manager", or nothing.
}
}
// Now, we fill in the callerid info from the incoming entry, if it's stuff worth using
// Ignore fundamentally semi-anonymous information from local cell phones
// if the db has an entry for this number, and it's not a canned string from a cell phone company
if( "${cidn}" != "0" & ( "${CALLERID(name)}" = ""
| "${CALLERID(name)}" = "CODY,WY "
| "${CALLERID(name)}" = "WIRELESS CALLER"
| "${CALLERID(name)}" = "CELLULAR ONE"
| "${CALLERID(name)}" = "Privacy Manager"
| "${CALLERID(name)}" = "RIVERTON,WY "
| "${CALLERID(name)}" = "BILLINGS,MT "
| "${CALLERID(name)}" = "PROVO,UT "
| "${CALLERID(name)}" = "TOLL FREE " ) ) // put stuff in the above, that the phone company tends to put in your callerid,
// that you would rather override with DB info
{
Set(CALLERID(name)=${cidn}); // Override what the phone company provides with what's in the DB for this number.
}
}




Holiday Greeting message - AEL2


AEL2 offers different ways to say the same thing. So, a string of choices can be nested:


ifTime(*|*|20-25|dec)
{
Playback(greetings/christmas);
}
else
{
ifTime(*|*|31|dec)
{
Playback(greetings/newyear);
}
else
{
ifTime(*|*|1|jan)
{
Playback(greetings/newyear);
}
else
{
ifTime(*|*|14|feb)
{
Playback(greetings/valentines);
}
else
{
ifTime(*|*|17|mar)
{
Playback(greetings/stPat);
}
else
{
ifTime(*|*|31|oct) {Playback(greetings/halloween);}
else
{
ifTime(*|mon|15-21|jan) {Playback(greetings/mlkDay);}
else
{
ifTime(*|thu|22-28|nov) {Playback(greetings/thanksgiving);}
else
{
ifTime(*|mon|25-31|may) {Playback(greetings/memorial);}
else
{
ifTime(*|mon|1-7|sep) {Playback(greetings/labor);}
else
{
ifTime(*|mon|15-21|feb) {Playback(greetings/president);}
else
{
ifTime(*|sun|8-14|may) {Playback(greetings/mothers);}
else
{
ifTime(*|sun|15-21|jun) {Playback(greetings/fathers);}
else {Playback(greetings/hello); }; // None of the above? Just a plain hello will do
}
}
}
}
}
}
}
}
}
}
}
}



That looks pretty awful, doesn't it? This is equivalent:


ifTime(*|*|20-25|dec)
{
Playback(greetings/christmas);
}
else ifTime(*|*|31|dec)
{
Playback(greetings/newyear);
}
else ifTime(*|*|1|jan)
{
Playback(greetings/newyear);
}
else ifTime(*|*|14|feb)
{
Playback(greetings/valentines);
}
else ifTime(*|*|17|mar)
{
Playback(greetings/stPat);
}
else ifTime(*|*|31|oct)
{
Playback(greetings/halloween);
}
else ifTime(*|mon|15-21|jan)
{
Playback(greetings/mlkDay);
}
else ifTime(*|thu|22-28|nov)
{
Playback(greetings/thanksgiving);
}
else ifTime(*|mon|25-31|may)
{
Playback(greetings/memorial);
}
else ifTime(*|mon|1-7|sep)
{
Playback(greetings/labor);
}
else ifTime(*|mon|15-21|feb)
{
Playback(greetings/president);
}
else ifTime(*|sun|8-14|may)
{
Playback(greetings/mothers);
}
else ifTime(*|sun|15-21|jun)
{
Playback(greetings/fathers);
}
else
{
Playback(greetings/hello); // None of the above? Just a plain hello will do
}


Guessing Game


Here is a game, invented by Matt Gibson, see his web site for the referenced sounds: http://www.voipphreak.ca/archives/358-Asterisk-Howto-Numbers-Guessing-Game.html
Note that I did not have to use a single 'goto'!!!



macro guessgame()
{
while (1)
{
Playback(guessit/intro);
set(GUESS="");
GUESS=${EPOCH}%9;
Set(TIMEOUT(digit)=3);
Set(TIMEOUT(response)=5);
while (1)
{
Read(NUMBER,guessit/input_number,1);
Verbose(Got ${NUMBER} from Read);
if( "${NUMBER}" = "*" || "${NUMBER}" = "#" || "${NUMBER}" = "")
{
Playback(guessit/thatsnotanumber);
}
else if ("${NUMBER}" = "${GUESS}")
{
Playback(guessit/win);
break; // the only way out of this loop!
}
else if ("${NUMBER}" > "${GUESS}")
{
Playback(guessit/less);
}
else if ("${NUMBER}" < "${GUESS}")
{
Playback(guessit/more);
}
else /* what other stuff can the user enter than a number, #, nothing, or * ? */
{
Playback(guessit/thatsnotanumber);
}
}
/* You get here after a successful guess */
Wait(.5);
Read(AGAIN,guessit/playagain,1);
if ("${AGAIN}" != "1")
break;
}
Playback(guessit/goodbye);
return;

catch t
{
playback(guessit/goodbye);
return;
}
catch i
{
playblack(invalid);
}
}



This page accessed 52858 times since creation on Tue 20 of Dec, 2005 (17:40).
This Page intends to provide some examples on how to use the Asterisk Extension Language (AEL) combined with the applications and functions to create powerful dialplans.

String Manipulation


Since Asterisks Expression Evaluator is very advanced, we can easily use it to mangle strings (asterisk/docs/README.variable).

Adding / Removing items from delimited Strings


Lets assume we want to have a String containing elements somehow delimted, we can easily produce some macros to add and remove elements from those strings:


macro ael-remove-from-string(string,item,delim) {
        Set(left=$[ "${${string}}" : "\(.*\)[${delim}]*${item}[${delim}]*.*" ]);
        Set(right=$[ "${${string}}" : ".*[${delim}]*${item}[${delim}]*\(.*\)" ]);
        Set(new=${left}${right});

        if ( "${right}" = "" ) {
                Set(new=$[ "${new}" : "\(.*\)[${delim}]$" ]);
        };

        Set(${string}=${new});
};


macro ael-add-to-string( string, add , delim ) {
        Set(${string}=${${string}}${delim}${add});
        Set(${string}=$[ "${${string}}" : "[${delim}]*\(.*\)" ]);
} ;



These macros should be used like:


Set(teststring=item1);
&ael-add-to-string(teststring,item2,&);
&ael-add-to-string(teststring,item3,&);
--> teststring=item1&item2&item3 now
&ael-remove-from-string(teststring,item2,&);
--> teststring=item1&item3 now
&ael-remove-from-string(teststring,item1,&);
--> teststring=item3 now


The Telemarketing Torture scripts in AEL format:

See Asterisk AEL Telemarketer Torture.


Loop and Conditional test — AEL2




macro exten-gen(name,pword)
{
if( ${DB_EXISTS(org/${GroupID}/${name}/secret)} = 0 )
goto other|nomatch|begin;
if( ${DB(org/${GroupID}/${name}/secret)}foo != ${pword}foo )
goto other|nomatch|begin;

}

context other {
nomatch => {
begin:
NoOp(Hello!);
switch(${DIALSTATUS}) // watch out for spaces between the ( )'s
{
case BUSY:
NoOp(wow);
case TORTURE:
NoOp(woow);
}
NoOp(woohoo);
}
}

context testloop {
includes {
other|16:00-23:59|m0n-fri|*|*; // new to AEL2
}

1 => {
for (x=0; ${x} < 3; x=${x} + 1) {
Verbose(x is ${x} !);
if( ${x} = 1 )
continue;
if( ${x} = 2 )
break;
}
ifTime(14:00-25:00|sat-sun|*|*) { // new to AEL2
BackGround(Hello);
} else
BackGround(Sorry);
NoOp(This is a totally useless NOOP);
}
2 => {
y=10;
while (${y} >= 0) {
Verbose(y is ${y} !);
if( ${y} = 1 )
continue;
if( ${y} = 2 )
break;
if( ${y} = 3 )
return; // new to AEL2
y=${y}-1;
}
}
regexten hint(nasty/Thingy) 3 => {
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;

y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
y=${y}-1;
}
}
}
4 => {
y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;
for (z=0; ${z} < 17; z=${z} + 1)
{
Verbose(z is ${z} !);
Verbose(z is ${z} !);
if( ${z} = 4 )
break;
if( ${z} = 5 )
continue;
if( ${z} = 6 )
return;
Verbose(z is ${z} !);
Verbose(z is ${z} !);
}

}
y=${y}-1;
}
}
5 => {
&exten-gen(axel,brain);
}
}



Using the Asterisk database for CallerID info — AEL2


This macro will use/set the callerid on an incoming call, based on what's in the database, and what's in the callerID info.
It will also store the incoming CID in the database, under 'cidname'.


macro fillcidname()
{
if( "${CALLERID(num)}" = "" ) // nothing to work with, quit!!!
return;
cidn=${DB(cidname/${CALLERID(num)})};
if( "${CALLERID(name)}" != "" )
{
if( ("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "0" ) // if the entry isn't in the database,
// or if an entry exists, and it's "Privacy Manager", and the callerid isn't "privacy manager"
{ // In other words, let's put the callerid into the DB, but only if it's not already set, or just set to "privacy manager".
DB(cidname/${CALLERID(num)})=${CALLERID(name)}; // then set or override what's in the DB, if it's a dumb "Privacy Manager", or nothing.
}
}
// Now, we fill in the callerid info from the incoming entry, if it's stuff worth using
// Ignore fundamentally semi-anonymous information from local cell phones
// if the db has an entry for this number, and it's not a canned string from a cell phone company
if( "${cidn}" != "0" & ( "${CALLERID(name)}" = ""
| "${CALLERID(name)}" = "CODY,WY "
| "${CALLERID(name)}" = "WIRELESS CALLER"
| "${CALLERID(name)}" = "CELLULAR ONE"
| "${CALLERID(name)}" = "Privacy Manager"
| "${CALLERID(name)}" = "RIVERTON,WY "
| "${CALLERID(name)}" = "BILLINGS,MT "
| "${CALLERID(name)}" = "PROVO,UT "
| "${CALLERID(name)}" = "TOLL FREE " ) ) // put stuff in the above, that the phone company tends to put in your callerid,
// that you would rather override with DB info
{
Set(CALLERID(name)=${cidn}); // Override what the phone company provides with what's in the DB for this number.
}
}




Holiday Greeting message - AEL2


AEL2 offers different ways to say the same thing. So, a string of choices can be nested:


ifTime(*|*|20-25|dec)
{
Playback(greetings/christmas);
}
else
{
ifTime(*|*|31|dec)
{
Playback(greetings/newyear);
}
else
{
ifTime(*|*|1|jan)
{
Playback(greetings/newyear);
}
else
{
ifTime(*|*|14|feb)
{
Playback(greetings/valentines);
}
else
{
ifTime(*|*|17|mar)
{
Playback(greetings/stPat);
}
else
{
ifTime(*|*|31|oct) {Playback(greetings/halloween);}
else
{
ifTime(*|mon|15-21|jan) {Playback(greetings/mlkDay);}
else
{
ifTime(*|thu|22-28|nov) {Playback(greetings/thanksgiving);}
else
{
ifTime(*|mon|25-31|may) {Playback(greetings/memorial);}
else
{
ifTime(*|mon|1-7|sep) {Playback(greetings/labor);}
else
{
ifTime(*|mon|15-21|feb) {Playback(greetings/president);}
else
{
ifTime(*|sun|8-14|may) {Playback(greetings/mothers);}
else
{
ifTime(*|sun|15-21|jun) {Playback(greetings/fathers);}
else {Playback(greetings/hello); }; // None of the above? Just a plain hello will do
}
}
}
}
}
}
}
}
}
}
}
}



That looks pretty awful, doesn't it? This is equivalent:


ifTime(*|*|20-25|dec)
{
Playback(greetings/christmas);
}
else ifTime(*|*|31|dec)
{
Playback(greetings/newyear);
}
else ifTime(*|*|1|jan)
{
Playback(greetings/newyear);
}
else ifTime(*|*|14|feb)
{
Playback(greetings/valentines);
}
else ifTime(*|*|17|mar)
{
Playback(greetings/stPat);
}
else ifTime(*|*|31|oct)
{
Playback(greetings/halloween);
}
else ifTime(*|mon|15-21|jan)
{
Playback(greetings/mlkDay);
}
else ifTime(*|thu|22-28|nov)
{
Playback(greetings/thanksgiving);
}
else ifTime(*|mon|25-31|may)
{
Playback(greetings/memorial);
}
else ifTime(*|mon|1-7|sep)
{
Playback(greetings/labor);
}
else ifTime(*|mon|15-21|feb)
{
Playback(greetings/president);
}
else ifTime(*|sun|8-14|may)
{
Playback(greetings/mothers);
}
else ifTime(*|sun|15-21|jun)
{
Playback(greetings/fathers);
}
else
{
Playback(greetings/hello); // None of the above? Just a plain hello will do
}


Guessing Game


Here is a game, invented by Matt Gibson, see his web site for the referenced sounds: http://www.voipphreak.ca/archives/358-Asterisk-Howto-Numbers-Guessing-Game.html
Note that I did not have to use a single 'goto'!!!



macro guessgame()
{
while (1)
{
Playback(guessit/intro);
set(GUESS="");
GUESS=${EPOCH}%9;
Set(TIMEOUT(digit)=3);
Set(TIMEOUT(response)=5);
while (1)
{
Read(NUMBER,guessit/input_number,1);
Verbose(Got ${NUMBER} from Read);
if( "${NUMBER}" = "*" || "${NUMBER}" = "#" || "${NUMBER}" = "")
{
Playback(guessit/thatsnotanumber);
}
else if ("${NUMBER}" = "${GUESS}")
{
Playback(guessit/win);
break; // the only way out of this loop!
}
else if ("${NUMBER}" > "${GUESS}")
{
Playback(guessit/less);
}
else if ("${NUMBER}" < "${GUESS}")
{
Playback(guessit/more);
}
else /* what other stuff can the user enter than a number, #, nothing, or * ? */
{
Playback(guessit/thatsnotanumber);
}
}
/* You get here after a successful guess */
Wait(.5);
Read(AGAIN,guessit/playagain,1);
if ("${AGAIN}" != "1")
break;
}
Playback(guessit/goodbye);
return;

catch t
{
playback(guessit/goodbye);
return;
}
catch i
{
playblack(invalid);
}
}



This page accessed 52858 times since creation on Tue 20 of Dec, 2005 (17:40).
Created by: crich, Last modification: Mon 23 of Apr, 2012 (23:50 UTC) by admin
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+