我编写了一个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)
在此先感谢您提供的任何提示或建议。
PS:我知道有文档说明如何在python / flask环境之外执行此操作。但是,我还无法弄清楚如何在python / flask中实现这一目标。
答案 0 :(得分:2)
您应该为forward()函数的动词定义一个动作URL。然后,对该操作URL的请求(它将转回到您的Flask应用程序的URL)上的DialCallStatus将让您知道调用是否成功。如果调用未成功“完成”,则将路由到VM逻辑,否则。动词的默认超时为30秒,因此效果不错。
关键逻辑在下面的函数中,将逻辑移植到Python并不难。
因此,基本上对于上述功能,如果DialCallStatus完成,则要挂断电话,否则路由到VM / Twimlet。
答案 1 :(得分:0)
感谢艾伦的帮助,我解决了。下面的代码从我最初的示例中替换了forward
和answer_call
,并添加了一个新的call_result
方法。关于我的示例的所有其他内容保持不变。
现在,基于REST的应用将白名单批准的号码并阻止不需要的号码。任何批准的或未阻止的号码都将转发到目标电话号码。如果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')