After performing a fresh install of Asterisk (1.6) on a new box (decommissioning an old one) I found that it had support for LUA in the dialplan.
Of course, I’ve never used LUA but I know it’s used in some games as the primary scripting engine – which means it must be fast and powerful right? :)
Well, over the course of experimenting with LUA I’ve found that using it to power an Asterisk Dialplan results in some interesting hacks.
Have a look through the code, some of it is incomplete, some of the call_* functions will be enhanced later, but the basics are there
configuration = {
area = 7;
country = 61;
}
function linenotinuse()
app.wait(1)
app.answer()
app.playback("tt-monkeys")
app.hangup()
end
function time()
app.datetime()
app.wait(1)
time()
end
-- Eventually some of the call_* functions will become more complicated.
function call_emergency(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_localrate(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_freecall(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_local(ctx, ext)
app.dial("SIP/nodephone/0" .. configuration.area .. ext, 600, 'TWK')
end
function call_std(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_mobile(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_international(ctx, ext)
app.dial("SIP/nodephone/" .. ext, 600, 'TWK')
end
function call_lan(ctx, ext)
app.chanisavail("SIP/" .. ext, "s")
status = channel["AVAILSTATUS"]:get()
app.noop("Status: " .. status)
if status == "4" or status == "5" or status == "20" then
app.playback("pbx-invalid")
return
end
app.dial("SIP/" .. ext)
end
-- For incomming calls from nodephone (possibly others)
function nodephoneincoming()
-- Make sure both the phones are available
app.chanisavail("SIP/9100&SIP/9101", "s")
status = channel["AVAILSTATUS"]:get()
-- If both phones appear to be available
if string.find(status, '2', 1, true) == nil and string.find(status, '3', 1, true) == nil and string.find(status, '6', 1, true) == nil then
app.dial("SIP/9100&SIP/9101", 60, 'twk')
dialstatus = channel["DIALSTATUS"]:get()
else
dialstatus = "BUSY"
end
-- If there was no answer or the line was busy or unavailable, take a message
if not dialstatus == "ANSWER" then
app.noop(dialstatus)
app.goto("takemessage", "s", 1)
end
end
-- Prompt up to 3 times to leave a message
function takemessage()
if count == nil then count = 0 elseif count < 2 then count = count + 1 else hangup() end
if count == 0 then
app.answer()
app.wait(2)
if dialstatus == "BUSY" then
message = "the-party-you-are-calling&is-curntly-busy"
elseif dialstatus == "CHANUNAVAIL" then
message = "cannot-complete-network-error"
else
message = "away-naughty-boy"
end
message = message .. "&"
else
message = ""
end
app.background(message .. "T-to-leave-msg&press-star", "", "", "takemessage")
if not(channel["EXTEN"]:get() == "*") then app.waitexten() end
end
function hangup()
app.playback("thank-you-for-calling")
app.playback("goodbye")
app.hangup()
end
function voicemail()
app.voicemail("9100@default")
end
function voicemailmain()
app.nocdr()
app.voicemailmain()
end
extensions = {
-- Context used for message taking - bit of a hack...
takemessage = {
s = takemessage;
t = takemessage;
i = takemessage;
["*"] = voicemail;
};
-- Context used to potentially incomming providers
incoming = {
nodephone = nodephoneincoming;
pennytel = linenotinuse;
};
-- Generally unused context - it's here for voicemail really
default = {
s = linenotinuse;
};
-- All dialplan for the internal lines
internal = {
-- It doesn't seem the lua code can directly include the parkedcalls context
["_970X"] = function()
app.goto("parkedcalls", exten, "1")
end;
["101"] = voicemailmain;
["102"] = time;
["000"] = call_emergency;
["_91XX"] = call_lan;
["_13ZXXX"] = call_localrate;
["_1300XXXXXX"] = call_localrate;
["_1800XXXXXX"] = call_freecall;
["_NXXXXXXX"] = call_local;
["_0[2378]XXXXXXXX"] = call_std;
["_04XXXXXXXX"] = call_mobile;
["_0011."] = call_international;
};
}