From 2f8e950d34efc0e567286772a3907a3b99f15c86 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Wed, 3 Feb 2016 16:53:22 +0300 Subject: [PATCH 1/7] Fix. Can not pick any options after IVR play `streamfile.lua` Rewrite ivr functions to easy read code. --- resources/install/scripts/ivr_menu.lua | 287 ++++++++++++------------- 1 file changed, 139 insertions(+), 148 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index e1154c8d61..b2c2be7aee 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -40,6 +40,7 @@ --include functions require "resources.functions.format_ringback" + require "resources.functions.split" --get the variables domain_name = session:getVariable("domain_name"); @@ -79,10 +80,8 @@ end end - --set default variable(s) tries = 0; - option_found = "false"; --define the trim function require "resources.functions.trim" @@ -142,12 +141,9 @@ --get the sounds dir, language, dialect and voice sounds_dir = session:getVariable("sounds_dir"); - default_language = session:getVariable("default_language"); - default_dialect = session:getVariable("default_dialect"); - default_voice = session:getVariable("default_voice"); - if (not default_language) then default_language = 'en'; end - if (not default_dialect) then default_dialect = 'us'; end - if (not default_voice) then default_voice = 'callie'; end + default_language = session:getVariable("default_language") or 'en'; + default_dialect = session:getVariable("default_dialect") or 'us'; + default_voice = session:getVariable("default_voice") or 'callie'; --make the path relative if (string.sub(ivr_menu_greet_long,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then @@ -164,16 +160,10 @@ end --parse file names - greet_long_file_name = ivr_menu_greet_long:match("([^/]+)$"); - greet_short_file_name = ivr_menu_greet_short:match("([^/]+)$"); - invalid_sound_file_name = ivr_menu_invalid_sound:match("([^/]+)$"); - exit_sound_file_name = ivr_menu_exit_sound:match("([^/]+)$"); - ---prevent nil concatenation errors - if (greet_long_file_name == nil) then greet_long_file_name = ""; end - if (greet_short_file_name == nil) then greet_short_file_name = ""; end - if (invalid_sound_file_name == nil) then invalid_sound_file_name = ""; end - if (exit_sound_file_name == nil) then exit_sound_file_name = ""; end + greet_long_file_name = ivr_menu_greet_long:match("([^/]+)$") or ""; + greet_short_file_name = ivr_menu_greet_short:match("([^/]+)$") or ""; + invalid_sound_file_name = ivr_menu_invalid_sound:match("([^/]+)$") or ""; + exit_sound_file_name = ivr_menu_exit_sound:match("([^/]+)$") or ""; --get the recordings from the database ivr_menu_greet_long_is_base64 = false; @@ -295,7 +285,7 @@ end end --greet short - if (string.len(ivr_menu_greet_short) > 1) then + if #ivr_menu_greet_short > 1 then if (not file_exists(ivr_menu_greet_short)) then if (file_exists(recordings_dir.."/"..domain_name.."/"..greet_short_file_name)) then ivr_menu_greet_short = recordings_dir.."/"..domain_name.."/"..greet_short_file_name; @@ -325,44 +315,49 @@ --define the ivr menu function menu() - --increment the tries - tries = tries + 1; - min_digits = 1; - session:setVariable("slept", "false"); - if (tries == 1) then - if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] greet long: " .. ivr_menu_greet_long .. "\n"); + -- increment the tries + tries = tries + 1; + -- set the minimum dtmf lengts + local min_digits = 1; + + -- set sound file and number of attempts + local sound, sound_type, attempts + + if tries == 1 then + sound, sound_type, attempts = ivr_menu_greet_long or "", "long", 1 + else + sound, sound_type, attempts = ivr_menu_greet_short or "", "short", tonumber(ivr_menu_max_timeouts) or 3 end - --check if phrase - pos = string.find(ivr_menu_greet_long, ":", 0, true); - if (pos ~= nil and string.sub(ivr_menu_greet_long, 0, pos-1) == 'phrase') then - freeswitch.consoleLog("notice", "[ivr_menu] phrase detected\n"); - dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, 1, ivr_menu_timeout, ivr_menu_confirm_key, ivr_menu_greet_long, "", ".*"); + + if (debug["tries"]) then + freeswitch.consoleLog("notice", "[ivr_menu] greet " .. sound_type .. ": " .. sound .. "\n"); + end + + -- read dtmf + local dtmf_digits + if attempts > 0 then + dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, attempts, ivr_menu_timeout, ivr_menu_confirm_key, sound, "", ".*"); + -- need pause before stream file session:setVariable("slept", "false"); - else - dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, 1, ivr_menu_timeout, ivr_menu_confirm_key, ivr_menu_greet_long, "", ".*"); end - else - if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] greet long: " .. ivr_menu_greet_short .. "\n"); + + -- proceed dtmf + if dtmf_digits and #dtmf_digits > 0 then + if (debug["tries"]) then + freeswitch.consoleLog("notice", "[ivr_menu] dtmf_digits: " .. dtmf_digits .. "\n"); + end + return menu_options(session, dtmf_digits); end - dtmf_digits = session:playAndGetDigits(min_digits, ivr_menu_digit_len, ivr_menu_max_timeouts, ivr_menu_timeout, ivr_menu_confirm_key, ivr_menu_greet_short, "", ".*"); - end - if (dtmf_digits ~= nil and string.len(dtmf_digits) > 0) then - if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] dtmf_digits: " .. dtmf_digits .. "\n"); + + -- check number of failures + if tries < tonumber(ivr_menu_max_failures) then + --log the dtmf digits + if (debug["tries"]) then + freeswitch.consoleLog("notice", "[ivr_menu] tries: " .. tries .. "\n"); + end + --run the menu again + return menu(); end - menu_options(session, dtmf_digits); - else - if (tries < tonumber(ivr_menu_max_failures)) then - --log the dtmf digits - if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] tries: " .. tries .. "\n"); - end - --run the menu again - menu(); - end - end end function menu_options(session, digits) @@ -377,113 +372,109 @@ if (debug["sql"]) then freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); end - status = dbh:query(sql, function(row) + + local action, script, data + dbh:query(sql, function(row) + -- clear vars + action, script, data = nil + --check for matching options - if (tonumber(row.ivr_menu_option_digits) ~= nil) then + if tonumber(row.ivr_menu_option_digits) then row.ivr_menu_option_digits = "^"..row.ivr_menu_option_digits.."$"; end - if (api:execute("regex", "m:~"..digits.."~"..row.ivr_menu_option_digits) == "true") then - if (row.ivr_menu_option_action == "menu-exec-app") then - --get the action and data - pos = string.find(row.ivr_menu_option_param, " ", 0, true); - if pos then - action = string.sub(row.ivr_menu_option_param, 0, pos-1); - data = string.sub(row.ivr_menu_option_param, pos+1); - else - action, data = row.ivr_menu_option_param, "" - end - --check if the option uses a regex - regex = string.find(row.ivr_menu_option_digits, "(", 0, true); - if (regex) then - --get the regex result - result = trim(api:execute("regex", "m:~"..digits.."~"..row.ivr_menu_option_digits.."~$1")); - if (debug["regex"]) then - freeswitch.consoleLog("notice", "[ivr_menu] regex m:~"..digits.."~"..row.ivr_menu_option_digits.."~$1\n"); - freeswitch.consoleLog("notice", "[ivr_menu] result: "..result.."\n"); - end - - --replace the $1 and the domain name - data = data:gsub("$1", result); - data = data:gsub("${domain_name}", domain_name); - end --if regex - end --if menu-exex-app - if (row.ivr_menu_option_action == "phrase") then - action = 'phrase'; - data = row.ivr_menu_option_param; - end - if (action == "lua") then - pos = string.find(data, " ", 0, true); - if pos then - script = string.sub(data, 0, pos-1); - else - script = data - end - end - end --if regex match - - --execute - if (action) then - if (string.len(action) > 0) then - --option found - option_found = "true"; - - --send to the log - if (debug["action"]) then - freeswitch.consoleLog("notice", "[ivr_menu] action: " .. action .. " data: ".. data .. "\n"); - end - --run the action - if (action == 'phrase' or (script ~= nil and script == 'streamfile.lua')) then - session:execute(action, data); - menu(); - else - if (ivr_menu_exit_sound ~= nil) then - session:streamFile(ivr_menu_exit_sound); - end - session:execute(action, data); - end - end + if api:execute("regex", "m:~"..digits.."~"..row.ivr_menu_option_digits) ~= "true" then + return end - --clear the variables - action = ""; - data = ""; + if row.ivr_menu_option_action == "menu-exec-app" then + --get the action and data + action, data = split_first(row.ivr_menu_option_param, ' ', true) + data = data or "" + + --check if the option uses a regex + local regex = string.find(row.ivr_menu_option_digits, "(", 0, true); + if regex then + --get the regex result + regex = "m:~"..digits.."~"..row.ivr_menu_option_digits.."~$1" + local result = trim(api:execute("regex", regex)); + if (debug["regex"]) then + freeswitch.consoleLog("notice", "[ivr_menu] regex "..regex.."\n"); + freeswitch.consoleLog("notice", "[ivr_menu] result: "..result.."\n"); + end + + --replace the $1 and the domain name + data = data:gsub("$1", result); + data = data:gsub("${domain_name}", domain_name); + end --if regex + end --if menu-exex-app + + if row.ivr_menu_option_action == "phrase" then + action = 'phrase'; + data = row.ivr_menu_option_param; + end + + if action == "lua" then + script = split_first(data, " ", true) + end + + -- break loop + if action and #action > 0 then + return 1 + end + + -- we have unsupported IVR action + freeswitch.consoleLog("warning", "[ivr_menu] invalid action in ivr: " .. row.ivr_menu_option_action .. "\n"); end); --end results - --direct dial - if (ivr_menu_direct_dial == "true") then - if (string.len(digits) < 6 and option_found == "false") then - --replace the $1 and the domain name - digits = digits:gsub("*", ""); - --check to see if the user extension exists - cmd = "user_exists id ".. digits .." "..domain_name; - result = api:executeString(cmd); - freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..cmd.." "..result.."\n"); - if (result == "true") then - --log the action - freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..digits.." XML "..context.."\n"); - --run the action - session:execute("transfer", digits.." XML "..context); - else - --run the menu again - menu(); - end - end + --execute + if action and #action > 0 then + -- send to the log + if (debug["action"]) then + freeswitch.consoleLog("notice", "[ivr_menu] action: " .. action .. " data: ".. data .. "\n"); + end + + -- run the action (with return to menu) + if action == 'phrase' or script == 'streamfile.lua' then + session:execute(action, data); + return menu(); + end + + -- run the action (without return to menu) + if ivr_menu_exit_sound and #ivr_menu_exit_sound > 0 then + session:streamFile(ivr_menu_exit_sound); + end + return session:execute(action, data); end - --execute - if (action) then - if (string.len(action) == 0) then - session:streamFile(ivr_menu_invalid_sound); - menu(); - end - else - if (action ~= 'phrase' and (script == nil or script ~= 'streamfile.lua')) then - session:streamFile(ivr_menu_invalid_sound); - end - menu(); + --direct dial + if ivr_menu_direct_dial == "true" and #digits > 0 and #digits < 6 then + -- remove *# + digits = digits:gsub("[*#]", ""); + + -- check to see if the user extension exists + local cmd = "user_exists id ".. digits .." "..domain_name; + local result = api:executeString(cmd); + freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..cmd.." "..result.."\n"); + if result == "true" then + --log the action + freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..digits.." XML "..context.."\n"); + --run the action + return session:execute("transfer", digits.." XML "..context); + end + + --run the menu again (without play ivr_menu_invalid_sound) + return menu(); end - + + --invalid input try again + if (debug["action"]) then + freeswitch.consoleLog("notice", "[ivr_menu] unrecgnized action \n"); + end + if ivr_menu_invalid_sound and #ivr_menu_invalid_sound then + session:streamFile(ivr_menu_invalid_sound); + end + return menu(); end --end function --answer the session From 2fe1337494e0242b45674ae3308c4ff092382b35 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 4 Feb 2016 13:20:30 +0300 Subject: [PATCH 2/7] Simplify code --- resources/install/scripts/ivr_menu.lua | 204 +++++++++---------------- 1 file changed, 69 insertions(+), 135 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 146abee182..f06f10df76 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -80,9 +80,6 @@ end end ---set default variable(s) - tries = 0; - --define the trim function require "resources.functions.trim" @@ -146,18 +143,11 @@ default_voice = session:getVariable("default_voice") or 'callie'; --make the path relative - if (string.sub(ivr_menu_greet_long,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then - ivr_menu_greet_long = string.sub(ivr_menu_greet_long,72); - end - if (string.sub(ivr_menu_greet_short,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then - ivr_menu_greet_short = string.sub(ivr_menu_greet_short,72); - end - if (string.sub(ivr_menu_invalid_sound,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then - ivr_menu_invalid_sound = string.sub(ivr_menu_invalid_sound,72); - end - if (string.sub(ivr_menu_exit_sound,0,71) == "$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/") then - ivr_menu_exit_sound = string.sub(ivr_menu_exit_sound,72); - end + local strip_pattern = "^$${sounds_dir}/${default_language}/${default_dialect}/${default_voice}/" + ivr_menu_greet_long = string.gsub(ivr_menu_greet_long, strip_pattern, "") + ivr_menu_greet_short = string.gsub(ivr_menu_greet_short, strip_pattern, "") + ivr_menu_invalid_sound = string.gsub(ivr_menu_invalid_sound, strip_pattern, "") + ivr_menu_exit_sound = string.gsub(ivr_menu_exit_sound, strip_pattern, "") --parse file names greet_long_file_name = ivr_menu_greet_long:match("([^/]+)$") or ""; @@ -171,105 +161,65 @@ ivr_menu_invalid_sound_is_base64 = false; ivr_menu_exit_sound_is_base64 = false; if (storage_type == "base64") then + + --add functions + require "resources.functions.base64"; + require "resources.functions.mkdir"; + + --make sure the recordings directory exists + mkdir(recordings_dir.."/"..domain_name); + + --define function to load file from db + local function load_file(recordings_dir, domain_name, file_name) + local full_path = recordings_dir.."/"..domain_name .. "/" .. file_name + if file_exists(full_path) then + return full_path + end + + local sql = [[SELECT * FROM v_recordings WHERE domain_uuid = ']]..domain_uuid.. + [['AND recording_filename = ']]..file_name..[[' ]]; + + if (debug["sql"]) then + freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); + end + + local is_base64 + dbh:query(sql, function(row) + if #row.recording_base64 > 32 then + local file, err = io.open(full_path, "w"); + if not file then + freeswitch.consoleLog("err", "[ivr_menu] can not create file: "..full_path.."; Error - " .. tostring(err) .. "\n"); + end + file:write(base64.decode(row.recording_base64)); + file:close(); + is_base64 = true; + end + end); + + -- return path in any case + return full_path, is_base64 + end + --greet long - if (string.len(ivr_menu_greet_long) > 1) then - if (not file_exists(recordings_dir.."/"..domain_name.."/"..greet_long_file_name)) then - sql = [[SELECT * FROM v_recordings - WHERE domain_uuid = ']]..domain_uuid..[[' - AND recording_filename = ']]..greet_long_file_name..[[' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); - end - status = dbh:query(sql, function(row) - --add functions - require "resources.functions.base64"; - --make sure the recordings directory exists - require "resources.functions.mkdir"; - mkdir(recordings_dir.."/"..domain_name); - --add the path to filename - ivr_menu_greet_long = recordings_dir.."/"..domain_name.."/"..greet_long_file_name; - ivr_menu_greet_long_is_base64 = true; - --save the recording to the file system - if (string.len(row["recording_base64"]) > 32) then - local file = io.open(ivr_menu_greet_long, "w"); - file:write(base64.decode(row["recording_base64"])); - file:close(); - end - end); - end + if #ivr_menu_greet_long > 1 then + ivr_menu_greet_long, ivr_menu_greet_long_is_base64 = load_file(recordings_dir, domain_name, greet_long_file_name) end + --greet short - if (string.len(ivr_menu_greet_short) > 1) then - if (not file_exists(recordings_dir.."/"..domain_name.."/"..greet_short_file_name)) then - sql = [[SELECT * FROM v_recordings - WHERE domain_uuid = ']]..domain_uuid..[[' - AND recording_filename = ']]..greet_short_file_name..[[' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); - end - status = dbh:query(sql, function(row) - --add functions - require "resources.functions.base64"; - --add the path to filename - ivr_menu_greet_short = recordings_dir.."/"..domain_name.."/"..greet_short_file_name; - ivr_menu_greet_short_is_base64 = true; - --save the recording to the file system - if (string.len(row["recording_base64"]) > 32) then - local file = io.open(ivr_menu_greet_short, "w"); - file:write(base64.decode(row["recording_base64"])); - file:close(); - end - end); - end + if #ivr_menu_greet_short > 1 then + ivr_menu_greet_short, ivr_menu_greet_short_is_base64 = load_file(recordings_dir, domain_name, greet_short_file_name) end + --invalid sound - if (string.len(ivr_menu_invalid_sound) > 1) then - if (not file_exists(recordings_dir.."/"..domain_name.."/"..invalid_sound_file_name)) then - sql = [[SELECT * FROM v_recordings - WHERE domain_uuid = ']]..domain_uuid..[[' - AND recording_filename = ']]..invalid_sound_file_name..[[' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); - end - status = dbh:query(sql, function(row) - --add functions - require "resources.functions.base64"; - --add the path to filename - ivr_menu_invalid_sound = recordings_dir.."/"..domain_name.."/"..invalid_sound_file_name; - ivr_menu_invalid_sound_is_base64 = true; - --save the recording to the file system - if (string.len(row["recording_base64"]) > 32) then - local file = io.open(ivr_menu_invalid_sound, "w"); - file:write(base64.decode(row["recording_base64"])); - file:close(); - end - end); - end + if #ivr_menu_invalid_sound > 1 then + ivr_menu_invalid_sound, ivr_menu_invalid_sound_is_base64 = load_file(recordings_dir, domain_name, invalid_sound_file_name) end + --exit sound - if (string.len(ivr_menu_exit_sound) > 1) then - if (not file_exists(recordings_dir.."/"..domain_name.."/"..exit_sound_file_name)) then - sql = [[SELECT * FROM v_recordings - WHERE domain_uuid = ']]..domain_uuid..[[' - AND recording_filename = ']]..exit_sound_file_name..[[' ]]; - if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); - end - status = dbh:query(sql, function(row) - --add functions - require "resources.functions.base64"; - --add the path to filename - ivr_menu_exit_sound = recordings_dir.."/"..domain_name.."/"..exit_sound_file_name; - ivr_menu_exit_sound_is_base64 = true; - --save the recording to the file system - if (string.len(row["recording_base64"]) > 32) then - local file = io.open(ivr_menu_exit_sound, "w"); - file:write(base64.decode(row["recording_base64"])); - file:close(); - end - end); - end + if #ivr_menu_exit_sound > 1 then + ivr_menu_exit_sound, ivr_menu_exit_sound_is_base64 = load_file(recordings_dir, domain_name, exit_sound_file_name) end + elseif (storage_type == "http_cache") then --add the path to file name ivr_menu_greet_long = storage_path.."/"..ivr_menu_greet_long; @@ -279,44 +229,28 @@ end --adjust file paths + local function adjust_file_path(full_path, file_name) + return file_exists(full_path) + or file_exists(recordings_dir.."/"..domain_name.."/"..file_name) + or file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..file_name) + or full_path + end --greet long - if (not file_exists(ivr_menu_greet_long)) then - if (file_exists(recordings_dir.."/"..domain_name.."/"..greet_long_file_name)) then - ivr_menu_greet_long = recordings_dir.."/"..domain_name.."/"..greet_long_file_name; - elseif (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..greet_long_file_name)) then - ivr_menu_greet_long = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..greet_long_file_name; - end - end + ivr_menu_greet_long = adjust_file_path(ivr_menu_greet_long, greet_long_file_name) --greet short if #ivr_menu_greet_short > 1 then - if (not file_exists(ivr_menu_greet_short)) then - if (file_exists(recordings_dir.."/"..domain_name.."/"..greet_short_file_name)) then - ivr_menu_greet_short = recordings_dir.."/"..domain_name.."/"..greet_short_file_name; - elseif (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..greet_short_file_name)) then - ivr_menu_greet_short = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..greet_short_file_name; - end - end + ivr_menu_greet_short = adjust_file_path(ivr_menu_greet_short, greet_short_file_name) else - ivr_menu_greet_short = ivr_menu_greet_long; + ivr_menu_greet_short = ivr_menu_greet_long end --invalid sound - if (not file_exists(ivr_menu_invalid_sound)) then - if (file_exists(recordings_dir.."/"..domain_name.."/"..invalid_sound_file_name)) then - ivr_menu_invalid_sound = recordings_dir.."/"..domain_name.."/"..invalid_sound_file_name; - elseif (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..invalid_sound_file_name)) then - ivr_menu_invalid_sound = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..invalid_sound_file_name; - end - end + ivr_menu_invalid_sound = adjust_file_path(ivr_menu_invalid_sound, invalid_sound_file_name) --exit sound - if (not file_exists(ivr_menu_exit_sound)) then - if (file_exists(recordings_dir.."/"..domain_name.."/"..exit_sound_file_name)) then - ivr_menu_exit_sound = recordings_dir.."/"..domain_name.."/"..exit_sound_file_name; - elseif (file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..exit_sound_file_name)) then - ivr_menu_exit_sound = sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..exit_sound_file_name; - end - end + ivr_menu_exit_sound = adjust_file_path(ivr_menu_exit_sound, exit_sound_file_name) --define the ivr menu + local menu_options, menu + local tries = 0; function menu() -- increment the tries tries = tries + 1; From 1f9fbc6b7b9afa7be311ac3d4270ea5daabc3a65 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 4 Feb 2016 16:05:35 +0300 Subject: [PATCH 3/7] Use logger class. --- resources/install/scripts/ivr_menu.lua | 64 ++++++++++++++------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index f06f10df76..90af66d61c 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -38,6 +38,9 @@ require "resources.functions.database_handle"; dbh = database_handle('system'); +--get logger + local log = require "resources.functions.log".ivr_menu + --include functions require "resources.functions.format_ringback" require "resources.functions.split" @@ -50,6 +53,8 @@ caller_id_number = session:getVariable("caller_id_number"); domain_uuid = session:getVariable("domain_uuid"); + local recordings_dir = recordings_dir .. "/" .. domain_name + --settings require "resources.functions.settings"; settings = settings(domain_uuid); @@ -94,9 +99,9 @@ WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' AND ivr_menu_enabled = 'true' ]]; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); + log.notice("SQL: " .. sql); end - status = dbh:query(sql, function(row) + dbh:query(sql, function(row) domain_uuid = row["domain_uuid"]; ivr_menu_name = row["ivr_menu_name"]; --ivr_menu_extension = row["ivr_menu_extension"]; @@ -123,12 +128,10 @@ end); --set the caller id name - if (caller_id_name) then - if (string.len(ivr_menu_cid_prefix) > 0) then - caller_id_name = ivr_menu_cid_prefix .. "#" .. caller_id_name; - session:setVariable("caller_id_name", caller_id_name); - session:setVariable("effective_caller_id_name", caller_id_name); - end + if caller_id_name and #caller_id_name >0 then + caller_id_name = ivr_menu_cid_prefix .. "#" .. caller_id_name; + session:setVariable("caller_id_name", caller_id_name); + session:setVariable("effective_caller_id_name", caller_id_name); end --set ringback @@ -167,11 +170,11 @@ require "resources.functions.mkdir"; --make sure the recordings directory exists - mkdir(recordings_dir.."/"..domain_name); + mkdir(recordings_dir); --define function to load file from db - local function load_file(recordings_dir, domain_name, file_name) - local full_path = recordings_dir.."/"..domain_name .. "/" .. file_name + local function load_file(file_name) + local full_path = recordings_dir .. "/" .. file_name if file_exists(full_path) then return full_path end @@ -180,7 +183,7 @@ [['AND recording_filename = ']]..file_name..[[' ]]; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: "..sql.."\n"); + log.notice("SQL: "..sql); end local is_base64 @@ -188,7 +191,8 @@ if #row.recording_base64 > 32 then local file, err = io.open(full_path, "w"); if not file then - freeswitch.consoleLog("err", "[ivr_menu] can not create file: "..full_path.."; Error - " .. tostring(err) .. "\n"); + log.err("can not create file: "..full_path.."; Error - " .. tostring(err)); + return end file:write(base64.decode(row.recording_base64)); file:close(); @@ -202,22 +206,22 @@ --greet long if #ivr_menu_greet_long > 1 then - ivr_menu_greet_long, ivr_menu_greet_long_is_base64 = load_file(recordings_dir, domain_name, greet_long_file_name) + ivr_menu_greet_long, ivr_menu_greet_long_is_base64 = load_file(greet_long_file_name) end --greet short if #ivr_menu_greet_short > 1 then - ivr_menu_greet_short, ivr_menu_greet_short_is_base64 = load_file(recordings_dir, domain_name, greet_short_file_name) + ivr_menu_greet_short, ivr_menu_greet_short_is_base64 = load_file(greet_short_file_name) end --invalid sound if #ivr_menu_invalid_sound > 1 then - ivr_menu_invalid_sound, ivr_menu_invalid_sound_is_base64 = load_file(recordings_dir, domain_name, invalid_sound_file_name) + ivr_menu_invalid_sound, ivr_menu_invalid_sound_is_base64 = load_file(invalid_sound_file_name) end --exit sound if #ivr_menu_exit_sound > 1 then - ivr_menu_exit_sound, ivr_menu_exit_sound_is_base64 = load_file(recordings_dir, domain_name, exit_sound_file_name) + ivr_menu_exit_sound, ivr_menu_exit_sound_is_base64 = load_file(exit_sound_file_name) end elseif (storage_type == "http_cache") then @@ -231,7 +235,7 @@ --adjust file paths local function adjust_file_path(full_path, file_name) return file_exists(full_path) - or file_exists(recordings_dir.."/"..domain_name.."/"..file_name) + or file_exists(recordings_dir.."/"..file_name) or file_exists(sounds_dir.."/"..default_language.."/"..default_dialect.."/"..default_voice.."/"..file_name) or full_path end @@ -267,7 +271,7 @@ end if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] greet " .. sound_type .. ": " .. sound .. "\n"); + log.notice("greet " .. sound_type .. ": " .. sound); end -- read dtmf @@ -281,7 +285,7 @@ -- proceed dtmf if dtmf_digits and #dtmf_digits > 0 then if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] dtmf_digits: " .. dtmf_digits .. "\n"); + log.notice("dtmf_digits: " .. dtmf_digits); end return menu_options(session, dtmf_digits); end @@ -290,7 +294,7 @@ if tries < tonumber(ivr_menu_max_failures) then --log the dtmf digits if (debug["tries"]) then - freeswitch.consoleLog("notice", "[ivr_menu] tries: " .. tries .. "\n"); + log.notice("tries: " .. tries); end --run the menu again return menu(); @@ -301,13 +305,13 @@ --log the dtmf digits if (debug["dtmf"]) then - freeswitch.consoleLog("notice", "[ivr_menu] dtmf: " .. digits .. "\n"); + log.notice("dtmf: " .. digits); end --get the ivr menu options sql = [[SELECT * FROM v_ivr_menu_options WHERE ivr_menu_uuid = ']] .. ivr_menu_uuid ..[[' ORDER BY ivr_menu_option_order asc ]]; if (debug["sql"]) then - freeswitch.consoleLog("notice", "[ivr_menu] SQL: " .. sql .. "\n"); + log.notice("SQL: " .. sql); end local action, script, data @@ -336,8 +340,8 @@ regex = "m:~"..digits.."~"..row.ivr_menu_option_digits.."~$1" local result = trim(api:execute("regex", regex)); if (debug["regex"]) then - freeswitch.consoleLog("notice", "[ivr_menu] regex "..regex.."\n"); - freeswitch.consoleLog("notice", "[ivr_menu] result: "..result.."\n"); + log.notice("regex "..regex); + log.notice("result: "..result); end --replace the $1 and the domain name @@ -361,14 +365,14 @@ end -- we have unsupported IVR action - freeswitch.consoleLog("warning", "[ivr_menu] invalid action in ivr: " .. row.ivr_menu_option_action .. "\n"); + log.warning("invalid action in ivr: " .. row.ivr_menu_option_action); end); --end results --execute if action and #action > 0 then -- send to the log if (debug["action"]) then - freeswitch.consoleLog("notice", "[ivr_menu] action: " .. action .. " data: ".. data .. "\n"); + log.notice("action: " .. action .. " data: ".. data); end -- run the action (with return to menu) @@ -392,10 +396,10 @@ -- check to see if the user extension exists local cmd = "user_exists id ".. digits .." "..domain_name; local result = api:executeString(cmd); - freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..cmd.." "..result.."\n"); + log.notice("[direct dial] "..cmd.." "..result); if result == "true" then --log the action - freeswitch.consoleLog("NOTICE", "[ivr_menu][direct dial] "..digits.." XML "..context.."\n"); + log.notice("[direct dial] "..digits.." XML "..context); --run the action return session:execute("transfer", digits.." XML "..context); end @@ -406,7 +410,7 @@ --invalid input try again if (debug["action"]) then - freeswitch.consoleLog("notice", "[ivr_menu] unrecgnized action \n"); + log.notice("unrecgnized action"); end if ivr_menu_invalid_sound and #ivr_menu_invalid_sound then session:streamFile(ivr_menu_invalid_sound); From a9e4f5a3e69d17890a85d4e6e8e54af5bbd7c432 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 4 Feb 2016 19:05:24 +0300 Subject: [PATCH 4/7] Fix. Allow multiple actions in IVR --- resources/install/scripts/ivr_menu.lua | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 90af66d61c..3f98d6d379 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -314,7 +314,7 @@ log.notice("SQL: " .. sql); end - local action, script, data + local actions, script, data = {} dbh:query(sql, function(row) -- clear vars action, script, data = nil @@ -361,7 +361,8 @@ -- break loop if action and #action > 0 then - return 1 + actions[#actions + 1] = {action, script, data} + return end -- we have unsupported IVR action @@ -369,7 +370,9 @@ end); --end results --execute - if action and #action > 0 then + if #actions > 0 then + for _, t in ipairs(actions) do + local action, script, data = t[1],t[2],t[3] -- send to the log if (debug["action"]) then log.notice("action: " .. action .. " data: ".. data); @@ -378,14 +381,15 @@ -- run the action (with return to menu) if action == 'phrase' or script == 'streamfile.lua' then session:execute(action, data); - return menu(); + else + if ivr_menu_exit_sound and #ivr_menu_exit_sound > 0 then + session:streamFile(ivr_menu_exit_sound); + end + -- run the action (without return to menu) + return session:execute(action, data); end - - -- run the action (without return to menu) - if ivr_menu_exit_sound and #ivr_menu_exit_sound > 0 then - session:streamFile(ivr_menu_exit_sound); - end - return session:execute(action, data); + end + return menu(); end --direct dial From 9f818dfbbf6c28ec59d6e544eabfcabbce6d07b1 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 4 Feb 2016 19:42:42 +0300 Subject: [PATCH 5/7] Fix. Infinity loop. IVR ignores `max_failures`. --- resources/install/scripts/ivr_menu.lua | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 3f98d6d379..6349b719a7 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -256,8 +256,19 @@ local menu_options, menu local tries = 0; function menu() + -- check number of failures + if (tries > 0) and (tries >= tonumber(ivr_menu_max_failures)) then + return + end + -- increment the tries tries = tries + 1; + + --log the dtmf digits + if (debug["tries"]) then + log.notice("tries: " .. tries); + end + -- set the minimum dtmf lengts local min_digits = 1; @@ -290,15 +301,7 @@ return menu_options(session, dtmf_digits); end - -- check number of failures - if tries < tonumber(ivr_menu_max_failures) then - --log the dtmf digits - if (debug["tries"]) then - log.notice("tries: " .. tries); - end - --run the menu again - return menu(); - end + return menu(); end function menu_options(session, digits) From b3764e21f97d011aa2bd1860507eeb9aca8278ed Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Thu, 4 Feb 2016 20:00:12 +0300 Subject: [PATCH 6/7] Update log. --- resources/install/scripts/ivr_menu.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 6349b719a7..37d407e9c3 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -266,7 +266,7 @@ --log the dtmf digits if (debug["tries"]) then - log.notice("tries: " .. tries); + log.noticef("tries: %d/%d", tries, tonumber(ivr_menu_max_failures) or '-1'); end -- set the minimum dtmf lengts From b616736a29f756a00820aa27b576bb9b30ef643c Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Fri, 5 Feb 2016 10:20:09 +0300 Subject: [PATCH 7/7] Fix. Declare vars in correct scope. --- resources/install/scripts/ivr_menu.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/install/scripts/ivr_menu.lua b/resources/install/scripts/ivr_menu.lua index 37d407e9c3..09c83397fc 100644 --- a/resources/install/scripts/ivr_menu.lua +++ b/resources/install/scripts/ivr_menu.lua @@ -317,10 +317,10 @@ log.notice("SQL: " .. sql); end - local actions, script, data = {} + local actions = {} dbh:query(sql, function(row) - -- clear vars - action, script, data = nil + -- declare vars + local action, script, data --check for matching options if tonumber(row.ivr_menu_option_digits) then