I have decided that none of the built in asterisk functions are
exactly what I want. Furthermore the form and the link_to_dtmf isn''t
exactly what I want either. I have written the following code which is
*exactly* what I want. If you want I can merge this to the codebase
as another option for users. It will require very minor tweaking to
merge.
Here is how you would call these functions.
pin_number = get_data_ex ( :timeout_value => 10000,
:valid_keys => "0123",
:escape_keys => "#" ,
:max_length => 4,
:max_tries => 3,
:sound_files => ["lang/eng/welcome",
"lang/eng/enter-pin-number" ],
:invalid_key_prompts =>
[''lang/eng/invalid-key''],
:no_key_pressed_prompts =>
[''lang/eng/no-key'',''lang/eng/try-again''],
:error_prompts =>
[''lang/eng/contact-cust-service'']
)
This will play all the sound_files and the user will be able to
interrupt them at any time. It collect up to max_length number of
digits (or less if the user presses any of the escape_keys). If the
user doesn''t type anything it will play the no_key_pressed_prompts, if
the user presses a non acceptable key it will play the
invalid_key_prompts. If the user runs out of retries then it will play
the error_prompts and return an empty string.
If the user hangs up at any time it will raise a UserHungupError
If any of the sound files are missing it will raise a SoundFileNotFoundError
What do you guys think?
--------Code------------------
def get_data_ex(params)
params[:timeout_value] ||= 10000 #set to zero for
params[:valid_keys] ||= "0123456789*"
params[:escape_keys] ||= "#"
params[:max_length] ||= 10 # as good as any I guess.
params[:max_tries] ||= 3
params[:sound_files] ||= Array.new()
params[:invalid_key_prompts] ||= Array.new()
params[:no_key_pressed_prompts] ||= Array.new()
params[:error_prompts] ||= Array.new()
key = ''''
input = ''''
retry_count = 0
#try to get a good key max_tries times
key = play_prompts_get_digit params[:sound_files], params[:timeout_value]
input = ''''
while retry_count < params[:max_tries] && input.size
<params[:max_length] do
if '''' == key
log_debug "no entry"
retry_count += 1
key = play_prompts_get_digit
params[:no_key_pressed_prompts], params[:timeout_value]
elsif params[:escape_keys].include? key
#escape keys are valid so it has to be tested first
log_debug "Escape key pressed"
break
elsif !(params[:valid_keys].include? key)
log_debug "Bad key entry"
retry_count += 1
key = play_prompts_get_digit params[:invalid_key_prompts],
params[:timeout_value]
else
input << key
#get next key
if input.size <= params[:max_length]
key = wait_for_digit params[:timeout_value]
end
end #if
log_info "KEY: #{key}"
log_info "INPUT: #{input}"
end #while
if retry_count == params[:max_tries]
#we tried and tried but to no avail
#zero timeout
log_debug "max retries"
play_prompts_get_digit params[:error_prompts], 0
input = ''''
end
return input
end #get_data_ex
def play_prompts_get_digit (prompts, timeout, digits =
''0123456789#*'' )
#turn it into an array in case it''s not...
if not prompts.is_a?(Array)
raise "Prompts is not an array"
end
#In this case we always want to terminate on any digit
sample_offset = -99
key = ''''
for prompt in prompts do
log_debug "playing #{prompt}"
msg = "STREAM FILE #{prompt} #{digits} #{sample_offset}"
send_to_asterisk(msg)
results = get_multivalue_result
# Parse the return values. This is from the asterisk documentation:
#
# failure: 200 result=-1 endpos=<sample offset>
# failure on open: 200 result=0 endpos=0
# success: 200 result=0 endpos=<offset>
# digit pressed: 200 result=<digit> endpos=<offset>
key_code = results["result"].to_i
final_offset = results["endpos"].to_i
if -1 == key_code
log_debug "User Hung Up"
raise UserHungUpError, "User hung up during streaming of file
#{prompt}"
elsif 0 == key_code && 0 == final_offset
log_debug "File not Found"
raise SoundFileNotFoundError, "Unable to stream file
#{prompt} perhaps file does exist"
elsif 0 == key_code
# user didn''t press a key keep going
else
log_debug "User pressed Key #{key_code.chr} Final Offset
#{final_offset}"
key = key_code.chr #, final_offset
end
#if a key was pressed we jump out of the loop
break if key.length > 0
end #for
log_debug "outside with #{key}"
key = wait_for_digit(timeout) unless key.length > 0
return key
end #play_prompts_get_digit
def wait_for_digit (timeout = 100000)
#Default one second
log_debug "wait for key"
send_to_asterisk("WAIT FOR DIGIT #{timeout}")
results = get_multivalue_result
log_debug results.to_yaml
key_code = results["result"].to_i
#Returns:
#failure: 200 result=-1
#timeout: 200 result=0
#success: 200 result=<digit>
#<digit> is the ascii code for the digit received.
if -1 == key_code
log_debug "User Hung Up"
raise UserHungUpError, "User hung up during streaming of file
#{filename}"
elsif 0 == key_code
log_debug "Timeout waiting for key press"
return ''''
else
return key_code.chr
end #if
end #wait for key