代码之家  ›  专栏  ›  技术社区  ›  HippoMan

twilio/python/flask:向前呼叫,如果没有及时应答,则重定向到语音邮件

  •  0
  • HippoMan  · 技术社区  · 7 年前

    我已经编写了一个flask应用程序(使用python3),我已经在twilio注册了这个应用程序,以响应twilio提供的电话号码的来电。我可以让它路由到语音邮件,挂断,忽略呼叫,并转发到另一个电话号码,我在这里呼叫 target

    但有一项功能我还没有弄清楚如何在这个框架内实现 twilio python / flask 应用程序。如果传入号码没有被我的应用程序逻辑拒绝,我希望呼叫被转发到目标号码。但是,如果在30秒内没有人接这个号码,我希望电话能转到我通过的语音信箱 twimlets . 我不知道如何在这里实现这个条件转发/语音邮件逻辑。

    这必须发生在 answer_call 以下代码底部附近的方法:

    import re
    
    from flask import Flask, Response, redirect, request, send_file
    from twilio.twiml.voice_response import VoiceResponse
    
    app = Flask(__name__)
    
    ngrokurl = 'http://XXXXXXXX.ngrok.io'
    vmbase   = 'http://twimlets.com/voicemail?Email=USER@DOMAIN.COM&Transcribe=False'
    vmpath   = '/path/to/voicemessage.mp3'
    vmurl    = os.path.join(ngrokurl, 'vm')
    fwd      = '+1-111-111-11111'
    
    def num(n):
        return re.compile(n)
    
    whitelist = [
        num(r'^[+]11100000000$'),
        num(r'^[+]11111100000$'),
        num(r'^[+]11111111100$'),
    ]
    
    ignorelist = [
        num(r'^[+]2000'),
    ]
    
    hanguplist = [
        num(r'^[+]3000'),
    ]
    
    def number_in(n, numlist):
        if not n or not numlist:
            return False
        for item in numlist:
            if item.search(n):
                return True
        return False
    
    def voicemail():
        return redirect(
            '{}&Message={}'.format(vmbase, vmurl),
            302
        )
    
    def ignore():
        resp = VoiceResponse()
        resp.play(vmurl, loop=1)
        return Response(str(resp), 200, mimetype='application/xml')
    
    def hangup():
        resp = VoiceResponse()
        resp.hangup()
        return Response(str(resp), 200, mimetype='application/xml')
    
    def forward():
        resp = VoiceResponse()
        resp.dial(fwd)
        return Response(str(resp), 200, mimetype='application/xml')
    
    @app.route('/answer', methods=['GET', 'POST'])
    def answer_call():
        '''
        Main flask route for answering phone calls.
        '''
        number = request.args.get('From', None)
        if not number:
            return hangup()
        if number_in(number, whitelist):
            # Whitelisted numbers are directly forwarded.
            #
            # However, what I want to do here is forward to
            # the target number, but then to redirect
            # to voicemail if the call isn't answered
            # after, say, 30 seconds. Don't know how ... ???
            #
            return forward()
    ##        return voicemail()
        elif number_in(number, ignorelist):
            return ignore()
        elif number_in(number, hanguplist):
            return hangup()
        else:
            #
            # Same question here: how do I forward
            # to the target but then redirect
            # to voicemail if the call isn't answered?
            #
            return forward()
    ##        return voicemail()
    
    @app.route('/vm', methods=['GET', 'POST'])
    def vm():
        '''
        URL for the voicemail recording used within the
        twimlets voicemail call. See `vmurl`, above.
        '''
        return send_file(vmpath, 'audio/mpeg')
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    提前感谢你们的指点和建议。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Alan    7 年前

    应该为forward()函数的谓词定义一个动作URL。然后,请求到该操作URL的DialCallStatus(它将引导回Flask应用程序的URL)将告诉您调用是否成功。如果调用未成功“完成”,则将路由到VM逻辑,否则。一个动词的默认超时时间是30秒,所以你在那里很好。

    关键逻辑在下面的函数中,将逻辑移植到Python应该没有那么困难。

    在函数中创建语音邮件操作 https://www.twilio.com/docs/wireless/tutorials/communications-guides/implement-voicemail#create-voicemail-action-in-functions

    因此,基本上对于上述函数,如果DialCallStatus完成,您希望挂断呼叫,否则将路由到VM/Twimlet。

        2
  •  0
  •   HippoMan    7 年前

    forward answer_call 从我最初的例子,它添加了一个新的 call_result

    现在,REST-ful应用程序将列出已批准的号码并阻止不需要的号码。任何已批准或未阻止的号码都将转发到目标电话号码。如果20秒后无人接听,应用程序会将呼叫路由到我的手机 twimlet

    显然,这个示例应用程序包含硬编码的过滤器,这些过滤器只包含伪数据。在现实生活中,每次有调用传入时,我都会从数据存储中加载这些。这样,我就可以从REST-ful应用程序外部修改这些过滤器,而不必重新编译甚至重新启动该应用程序。

    到目前为止,我的初始编码工作得很好。

    def forward():
        resp = VoiceResponse()
        resp.dial(
            fwd,
            action=url_for('call_result'),
            method='GET',
            timeout=20
        )
        return Response(str(resp), 200, mimetype='application/xml')
    
    @app.route('/answer', methods=['GET', 'POST'])
    def answer_call():
        number = request.args.get('From', None)
        if not number:
            return hangup()
        elif number_in(number, whitelist):
            return forward()
        elif number_in(number, ignorelist):
            return ignore()
        elif number_in(number, hanguplist):
            return hangup()
        else:
            return forward()
    
    @app.route('/call', methods=['GET', 'POST'])
    def call_result():
        status = request.args.get('DialCallStatus', None)
        if not status or status != 'completed':
            return voicemail()
        else:
            return Response(str(resp), 200, mimetype='application/xml')
    
    推荐文章