Twillo - how to handle no input on <gather>
<p>I'm building a simple Twillo (programmable voice) application using Python flask and the <a href="https://www.twilio.com/docs/libraries/python" rel="nofollow">twillo-python helper library</a>.  There are several steps to the voice menu, but the first asks the caller to enter a pin number.</p>

<p>I am trying to working out what the best practice to deal with no caller input from a TwiML <code>&lt;Gather&gt;</code> verb in a DRY way.  I've made a function <code>process_no_input_response</code> which receives and returns a twllio <code>resp</code> object with appropriate <code>&lt;Say&gt;</code> messages depending on if the maximum number of allowed retries has been reached. Code example is below.</p>

<p>Is there a better way to handle these scenarios?  Keen for any advice or feedback on this code.</p>

<pre><code>def process_no_input_response(resp, endpoint, num_retries_allowed=3):
    """Handle cases where the caller does not respond to a `gather` command.
       Determines whether to output a 'please try again' message, or redirect 
       to the hand up process

    Inputs:
      resp -- A Twillo resp object
      endpoint -- the Flask endpoint
      num_retries_allowed -- Number of allowed tries before redirecting to 
        the hang up process

    Returns:
      Twillo resp object, with appropriate ('please try again' or redirect) syntax
    """

    # Add initial caller message
    resp.say("Sorry, I did not hear a response.")

    session['num_retries_allowed'] = num_retries_allowed

    # Increment number of attempts
    if endpoint in session:
        session[endpoint] += 1
    else:
        session[endpoint] = 1

    if session[endpoint] &gt;= num_retries_allowed:
        # Reached maximum number of retries, so redirect to a message before hanging up
        resp.redirect(url=url_for('bye'))
    else:
        # Allow user to try again
        resp.say("Please try again.")
        resp.redirect(url=url_for(endpoint))

    return resp

@app.route('/', methods=['GET', 'POST'])
def step_one():
    """Entry point to respond to incoming requests."""

    resp = twilio.twiml.Response()
    with resp.gather(numDigits=6, action="/post_step_one_logic", method="POST") as gather:
        gather.say("Hello. Welcome to my amazing telephone app! Please enter your pin.")

    return str(process_no_input_response(resp, request.endpoint))    

@app.route('/bye', methods=['GET', 'POST'])
def bye():
    """Hangup after a number of failed input attempts."""

    resp = twilio.twiml.Response()
    resp.say("You have reached the maximum number of retries allowed. 
       Please hang up and try calling again.")
    resp.hangup()

    return str(resp)
</code></pre>

<p>Twilio developer evangelist here.</p>

<p>That seems like a reasonable way to build this response. Redirecting round to play the <a href="https://www.twilio.com/docs/api/twiml/gather" rel="nofollow"><code>&lt;Gather&gt;</code></a> again until you reach a number of attempts is a great way of dealing with this situation (and one I can't think of a a better way to deal with right now). Indeed, it is effectively the solution suggested in the <a href="https://www.twilio.com/docs/api/twiml/gather#hints" rel="nofollow">Advanced use section of the documentation</a>.</p>

python flask twilio twiml