Experiance with Asterisk and LUA

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.