So I decided to convert my dialplan to lua. I though I would share some of my experiences doing so.
The main issue I found was with how app.background worked.
If an extension was entered while background was playing it would not jump to the extension.
To make it do so I found I had to do the following where c is the context and e is the current exension
app.backGround(menu, "", "", c)
if (channel["EXTEN"]:get() ~= e) then return end
app.waitExten(3)
I also come up with the following for my ivr menus. As most of my menus follow the same structure with an optional intro and the a message that repeats, along with the # key going back to the previous menu
function create_ivr_menu_context(intro, menu, includes)
context = {}
if includes ~= nil then
context["include"] = includes;
end
if intro ~= nil then
context["s"] = function(c, e)
if ivr_trail == nil then
ivr_trail = {}
end
table.insert(ivr_trail, c)
ivr_repeated_cnt = 0
app.answer()
app.wait(1)
app.backGround(intro, "", "", c)
if (channel["EXTEN"]:get() ~= e) then return end
app.goto(c, "s-repeat", "1")
end
else
context["s"] = function(c, e)
if ivr_trail == nil then
ivr_trail = {}
end
table.insert(ivr_trail, c)
ivr_repeated_cnt = 0
app.answer()
app.wait(1)
app.goto(c, "s-repeat", "1")
end
end
context["s-repeat"] = function(c, e)
if ivr_repeated_cnt < 2 then
ivr_repeated_cnt = ivr_repeated_cnt + 1
else
app.playback("to/thank-you-for-calling")
app.hangup()
end
app.backGround(menu, "", "", c)
if (channel["EXTEN"]:get() ~= e) then return end
app.waitExten(3)
end
context["i"] = function(c, e)
app.playback("invalid")
app.goto(c, "s-repeat", "1")
end
context["t"] = function(c, e)
app.goto(c, "s-repeat", "1")
end
context["*"] = function(c, e)
app.goto(c, "s-repeat", "1")
end
context["#"] = function(c, e)
if ivr_trail ~= nil then
if (# ivr_trail > 1) then
p = table.remove(ivr_trail)
p = table.remove(ivr_trail)
app.goto(p, "s", "1")
return
end
end
app.goto(c, "s-repeat", "1")
end
context["0"] = function(c, e)
call_reception()
end
return context
end
Then to create an ivr menu I would do
require("asterisk")
require("headoffice")
extensions["ivr_french"] = create_ivr_menu_context(
"to/intro",
"to/buss-opp&to/if-you-know-ext",
{"headoffice"})
extensions["ivr_french"]["1"] = function(c, e)
app.dial("Local/1000@headoffice")
end
extensions["ivr_french"]["2"] = function(c, e)
app.dial("Local/1000@headoffice")
end
Using lua helps me feel better at home as I am used other programming languages. I have implemented db driven employee look up menus and more with great success. I like having it built right in, instead of using AGI.
The hardest part is you still have to think in extension/context terms instead of a more free flow manor.