-- Dynamic Auto Attendant -- (C)opyright 2008, R. Marc Lewis -- IRC: gottafixthat -- Contributed to the FreeSWITCH project and licenced under the Mozilla Public License v1.1 -- Set our default actions and options context = session:getVariable("context") minDigits = 1 maxDigits = 1 -- How many times will we let them run through the extension prefix dialer? -- This is for security. We don't want someone tying up the channel without -- making them suffer at least a little bit. maxPrefixRuns = 3 curPrefixRun = 1 --digitPat = "(\*|#|\\d)\+" digitPat = "*" aaExtLen = session:getVariable("aa_ExtLen") if (aaExtLen == nil) then aaExtLen = 3 end aaDomain = session:getVariable("aa_domain") if (aaDomain == nil) then aaDomain = session:getVariable("domain") end aaAnnouncement = session:getVariable("aa_announcement") if (aaAnnouncement == nil) then aaAnnouncement = "" end aaTimeout = session:getVariable("aa_timeout") if (aaTimeout == nil) then aaTimeout = "30" end aaTimeoutAnnounce = session:getVariable("aa_timeoutannounce") if (aaTimeoutAnnounce == nil) then aaTimeoutAnnounce = "" end aaTimeoutAction = session:getVariable("aa_timeoutaction") if (aaTimeoutAction == nil) then aaTimeoutAction = "hangup" end aaTimeoutTarget = session:getVariable("aa_timeouttarget") if (aaTimeoutTarget == nil) then aaTimeoutTarget = "" end aaInvOptAnnounce = session:getVariable("aa_invoptannounce") if (aaInvOptAnnounce == nil) then aaInvOptAnnounce = "" end aaInvOptAction = session:getVariable("aa_invoptaction") if (aaInvOptAction == nil) then aaInvOptAction = "hangup" end aaInvOptTarget = session:getVariable("aa_invopttarget") if (aaInvOptTarget == nil) then aaInvOptTarget = "" end keyList = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "*", "#" } dtmfActs = { } curIDX = 1 for i,v in ipairs(keyList) do --dtmfActs[i] = { dtmf=v, action="invalid", playback=aaInvOptAnnounce, target=aaInvOptTarget } -- Load the digit actions from the variables dtmfVal = v if (dtmfVal == "#") then dtmfVal = "pound" end if (dtmfVal == "*") then dtmfVal = "star" end tmpAct = session:getVariable("aaDigitAct" .. dtmfVal) if (tmpAct ~= nil) then dtmf = v action = tmpAct playback = session:getVariable("aaDigitPlay" .. dtmfVal) if (playback == nil) then playback = "" end target = session:getVariable("aaDigitTgt" .. dtmfVal) if (target == nil) then target = "" end if (tmpAct == "prefix") then target = v end dtmfActs[curIDX] = { dtmf=dtmf, action=action, playback=playback, target=target } curIDX = curIDX + 1 end --freeswitch.consoleLog("warning", "Index: ".. i .." Value: ".. v .."\n") end for i,v in ipairs(dtmfActs) do --keyActs[v] = { action="invalid", playback="invalid.wav" } freeswitch.consoleLog("warning", "Index: ".. i .." DTMF: ".. v["dtmf"] .." Action: ".. v["action"] .." Target: ".. v["target"] .."\n") end -- extPrefixDial - Takes the first digit that we received and then gets -- (aaExtLen - 1) more digits, then attempts to transfer -- the call to that extension. function extPrefixDial(firstDigit) digLen = aaExtLen - 1 if (session:ready() == true) then extSuffix = session:getDigits(digLen, "", aaTimeout * 1000) if (session:ready() == true) then if (#extSuffix == digLen) then session:setVariable("prefix_dial_target", firstDigit .. extSuffix); session:execute("execute_extension", firstDigit .. extSuffix .. " XML " .. context) if (curPrefixRun == maxPrefixRuns) then session:hangup() end curPrefixRun = curPrefixRun + 1 end end end end -- processAction - Given a recording and an action, this function -- will handle processing the options for that action. function processAction(sndFile, action, target) if (session:ready() == true) then if (#sndFile) then session:streamFile(sndFile) end if (session:ready() == true) then if (action == "hangup") then session:hangup() elseif (action == "autoattendant") then -- FIXME: This needs to be a transfer to a special target in the -- dialplan that will create a new auto attendant. session:execute("transfer", "aa-".. target .. " XML " .. context) --session:hangup() elseif (action == "repeat") then -- Repeat is automatic. elseif (action == "prefix") then extPrefixDial(target) elseif (action == "exten") then session:execute("transfer", target .. " XML " .. context) elseif (action == "voicemail") then session:execute("voicemail", "default ".. aaDomain .." ".. target) session:hangup() elseif (action == "dialbyname") then session:streamFile("/opt/freeswitch/sounds/en/us/jjl/directory/8000/dir-unavailable.wav") session:sleep(1000) else -- Unknown Action. Log it and continue. freeswitch.consoleLog("warning", "Unknown auto attendant action '".. action .."'\n") end end end end -- Main Auto Attendant Loop. Continue looping as long as the seesion is valid -- or if they bomb out more than three times in a row. curPass = 1 while (session:ready() == true) do -- min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex actionTaken = false --digits = session:playAndGetDigits(minDigits, maxDigits, 3, aaTimeout * 1000, " ", aaAnnouncement, aaInvOptAnnounce, digitPat); digits = session:read(minDigits, maxDigits, aaAnnouncement, aaTimeout * 1000, "") --freeswitch.consoleLog("warning", "Got dtmf: ".. digits .."\n"); if (#digits < minDigits) then -- We got no digits, they timed out. if (session:ready() == true) then actionTaken = true freeswitch.consoleLog("warning", "Not enough digits.\n") processAction(aaTimeoutAnnounce, aaTimeoutAction, aaTimeoutTarget) curPass = curPass + 1 if (curPass > 3) then freeswitch.consoleLog("warning", "Exiting auto attendant. Timed out 3 times.") session:hangup() end end else -- Reset the current pass count curPass = 1 end if (session:ready() == true) then if (actionTaken == false) then for i,v in ipairs(dtmfActs) do freeswitch.consoleLog("warning", "Checking " ..digits.. " against "..v["dtmf"].."\n") if (digits == v["dtmf"]) then freeswitch.consoleLog("warning", "Found match for digit ".. digits .."\n"); actionTaken = true processAction(v["playback"], v["action"], v["target"]) end end end end -- If we get here and no action has been taken, do the invalid option actions if (session:ready() == true) then if (actionTaken == false) then freeswitch.consoleLog("warning", "Invalid option hit.\n") processAction(aaInvOptAnnounce, aaInvOptAction, aaInvOptTarget) end end end