Can someone tell me please: how to take callers, from enqueue to dial(forwarding). In one app, with automation this ???
i have something like that and it wont work:
<Say>hello</Say>
<Enqueue waitUrl="https://brass-dragonfly-1957.twil.io/assets/poczekalnia.xml">support</Enqueue>
<Dial url="/ivr/agent/screencall">
+000000000
<Queue>support</Queue>
</Dial>
<Redirect>/ivr/welcome/</Redirect>
</Response>
in python look like this:
twiml_response.say('hello')
twiml_response.enqueue('support', wait_url='https://brass-dragonfly-1957.twil.io/assets/poczekalnia.xml')
twiml_response.dial('+000000000', url=reverse('ivr:agents_screencall')).queue('support')
It looks like you are trying to perform actions for both your caller and an agent within the one TwiML response, and that will not work.
When you <Enqueue> a caller, no following TwiML will execute until you dequeue the caller with a <Leave>.
It looks like you want to dial an agent, allow them to screen the call and then connect them to the caller in the queue. To do this, you would start by creating a call to your agent using the REST API. With that call you would provide a URL that will be requested when that agent connects. In the response to that URL you should say the message to them, then <Dial> the <Queue>. Something like this:
import os
from twilio.rest import Client
account_sid = os.environ['TWILIO_ACCOUNT_SID']
auth_token = os.environ['TWILIO_AUTH_TOKEN']
client = Client(account_sid, auth_token)
def call(request):
twiml_response = VoiceResponse()
twiml_response.say('hello')
twiml_response.enqueue('support', wait_url='https://brass-dragonfly-1957.twil.io/assets/poczekalnia.xml')
call = client.calls.create(
url = '/agent'.
to = agent_phone_number,
from = your_twilio_number
)
return HttpResponse(twiml_response, content_type='text/xml')
Then, in response to the webhook to the /agent endpoint, you should return your response for screening, which might look like this:
def agent(request):
twiml_response = VoiceResponse()
gather = Gather(action='/agent_queue', method='POST', numDigits=1)
gather.say('You are receiving an incoming call, press 1 to accept')
twiml_response.append(gather)
return HttpResponse(twiml_response, content_type='text/xml')
And finally in /agent_queue you determine the result of screening the call and if the agent accepts, then you connect them to the queue.
def agent_queue(request):
twiml_response = VoiceResponse()
digits = request.POST.get("Digits", "")
if digits == "1":
dial = Dial()
dial.queue('support')
twiml_response.append(dial)
else:
twiml_response.hangup()
return HttpResponse(twiml_response, content_type='text/xml')
Related
I'm building a chatbot deployed via FB messenger. According to FB documentation, you have to send this post request to the messenger platform. I send a string representation of the payload using json.dumps. However, I never see the typing bubble and only get the actual response message from the bot. Here is the pertinent code from the Flask app.
#app.route('/', methods=['GET', 'POST'])
def receive_message():
global tag, latest_message
if request.method == 'GET':
# Before allowing people to message your bot Facebook has implemented a verify token
# that confirms all requests that your bot receives came from Facebook.
token_sent = request.args.get("hub.verify_token")
return verify_fb_token(token_sent)
# If the request was not GET, it must be POSTand we can just proceed with sending a message
# back to user
else:
# get whatever message a user sent the bot
output = request.get_json()
for event in output['entry']:
messaging = event['messaging']
for message in messaging:
if message.get('message'):
# Facebook Messenger ID for user so we know where to send response back to
recipient_id = message['sender']['id']
typing_payload = json.dumps({"recipient":{"id":recipient_id}, "sender_action":"typing_on"})
bot.send_raw(typing_payload)
time.sleep(3)
if message['message'].get('text'):
response_sent_text = send(message['message'].get('text'))
send_message(recipient_id, response_sent_text)
latest_message = response_sent_text
return "Message Processed"
You can use Pymessenger wrapper. Just import it, create an instance and pass your FB_TOKEN and wrap your actions. Remember when sending action, Facebook doc state that you must only pass the recipient_id and action and call the method separate from the response.
set action to "typing_on" in your method.
NB: Your method is incorrect because you are mixing sender_id and recipient_id
from pymessenger import Bot
bot = Bot(<FB_ACCESS_TOKEN>)
def send_typing_bubble(sender_id, recipient_id, action, response_sent_text):
bot.send_action(sender_id, action)
bot.send_text_message(sender_id, response_sent_text)
After your create the method you can just call send_typing_bubble() inside your webhook receive_message() method
if messaging_event.get('message'):
#your code here
send_typing_bubble(sender_id, recipient_id, action,
response_sent_text)
I'm trying to set my chatbot to display a typing bubble before sending the user the response so that it's more human like. I followed the documentation but am still getting instant responses from the bot with no typing bubble. As per the documentation I am using this sender action:
{"recipient":{"id":recipient_id}, "sender_action":"typing_on"}
And to put it in context, here is how I'm using it in the flask app:
#app.route('/', methods=['GET', 'POST'])
def receive_message():
global tag, latest_message
if request.method == 'GET':
# Before allowing people to message your bot Facebook has implemented a verify token
# that confirms all requests that your bot receives came from Facebook.
token_sent = request.args.get("hub.verify_token")
return verify_fb_token(token_sent)
# If the request was not GET, it must be POSTand we can just proceed with sending a message
# back to user
else:
# get whatever message a user sent the bot
output = request.get_json()
for event in output['entry']:
messaging = event['messaging']
for message in messaging:
if message.get('message'):
# Facebook Messenger ID for user so we know where to send response back to
recipient_id = message['sender']['id']
if message['message'].get('text'):
response_sent_text = send(message['message'].get('text'))
send_message(recipient_id, response_sent_text)
latest_message = response_sent_text
return "Message Processed"
def send_message(recipient_id, response):
# sends user the text message provided via input response parameter
typing_payload = {"recipient":{"id":recipient_id}, "sender_action":"typing_on"}
bot.send_raw(typing_payload)
print(bot.send_raw(typing_payload))
bot.send_text_message(recipient_id, response)
return "success"
Any ideas would be much appreciated!
You should pass a string representation of the payload (not a dictionary).
try doing something like this:
import json
...
def send_message(recipient_id, response):
# sends user the text message provided via input response parameter
typing_payload = json.dumps({"recipient":{"id":recipient_id}, "sender_action":"typing_on"})
bot.send_raw(typing_payload)
print(bot.send_raw(typing_payload))
bot.send_text_message(recipient_id, response)
return "success"
Also it's best practice to send these indicators upon receiving message (to show the typing indicator while processing), as opposed to directly before sending message.
I am putting together a POC for a client that wants to do phone based testing. In the POC, we simply want to let the user enter a phone# on a web page. We would then display a question and call their number. We would record their response to the question and play it back to them.
I can initiate the call, but can't figure out how to indicate that I want to record it. Ideally, I would like to say something and start recording after the beep.
I have all of 3 hours of experience with Twilio, so forgive my ignorance.
Here is my code so far:
import logging
# [START imports]
from flask import Flask, render_template, request
import twilio.twiml
from twilio.rest import TwilioRestClient
# [END imports]
app = Flask(__name__)
# [START form]
#app.route('/form')
def form():
return render_template('form.html')
# [END form]
# [START submitted]
#app.route('/submitted', methods=['POST'])
def submitted_form():
phone = request.form['phone']
account_sid = "AC60***********************"
auth_token = "27ea************************"
client = TwilioRestClient(account_sid, auth_token)
call = client.calls.create(to=phone, # Any phone number
from_="+160#######", # Must be a valid Twilio number
url="https://my-host/static/prompt.xml")
call.record(maxLength="30", action="/handle-recording")
return render_template(
'submitted_form.html',
phone=phone)
# [END render_template]
#app.route("/handle-recording", methods=['GET', 'POST'])
def handle_recording():
"""Play back the caller's recording."""
recording_url = request.values.get("RecordingUrl", None)
resp = twilio.twiml.Response()
resp.say("Thanks for your response... take a listen to what you responded.")
resp.play(recording_url)
resp.say("Goodbye.")
return str(resp)
#app.errorhandler(500)
def server_error(e):
# Log the error and stacktrace.
logging.exception('An error occurred during a request.')
return 'An internal error occurred.', 500
# [END app]
Twilio developer evangelist here.
When you create the call, you pass a URL to the call. That URL will be the one called when the user answers the phone. The response to that request should be the TwiML to instruct Twilio to say the message and record the response. Like so:
#app.route("/handle-call", methods=['GET', 'POST'])
def handle_call():
resp = twilio.twiml.Response()
resp.say("Please leave your message after the beep")
resp.record(action="/handle-recording", method="POST")
return str(resp)
Then you just need to update your call creation to point to that URL
call = client.calls.create(to=phone, # Any phone number
from_="+160#######", # Must be a valid Twilio number
url="https://my-host/handle-call")
Your /handle-recording path looks as though it will do what you want already.
Just a quick tip, as you're new to Twilio, when developing using webhooks I recommend using ngrok to tunnel to your dev machine and expose your application to Twilio. I wrote a blog post about how to use ngrok and some of the features I like too.
Let me know if this helps at all.
I want to call my Twilio number from my cellphone, Twilio recognizes my number, rejects the call and then calls me back. Here is the code:
#application.route("/test", methods=['GET', 'POST'])
def test():
whitelist = ['81808730xxxx', '44753810xxxx', '+44753810xxxx', '+44792834xxxx', '44792834xxxx']
call_from = request.values.get('From', 'None')
if call_from in whitelist:
# "<Response><Reject /></Response>"
resp = twilio.twiml.Response()
resp.reject()
time.sleep( 10 )
account_sid = "account_sid"
auth_token = "account_auth_token"
client = TwilioRestClient(account_sid, auth_token)
call = client.calls.create(to=call_from, from_="+1646480xxxx", url="https://zshizuka.herokuapp.com/gather")
print call.sid
else:
resp = twilio.twiml.Response()
call_to = "+44792834xxxx"
resp.dial(call_to)
#return json.dumps({'success':True}), 200
return str(resp)
This produces the dreaded response: "We are sorry a system error has occurred. Goodbye".
If, however, I dial the number and hangup after the first ring it works perfectly. So I am assuming that the problem is with the reject verb. As you can see I have tried with and without twiml.
I would like to get a busy signal, call rejected (so no cost to cell phone bill) and then callback.
Grateful for help.
I'd love to better understand your use case but I'm going to give this a go using the Twilio Python Helper Library.
As far as <Reject> TwiML goes, you can do something like this and be sure to specify a reason setting it to 'busy':
from flask import Flask
from flask import request
from twilio import twiml
account_sid = "YOU_ACCOUNT_SID"
auth_token = "YOUR_ACCOUNT_TOKEN"
client = TwilioRestClient(account_sid, auth_token)
app = Flask(__name__)
#app.route('/test', methods=["GET", "POST"])
def test():
whitelist = ['+14151XXXXXX', '+14152XXXXXX']
call_from = request.form['From']
if call_from in whitelist:
resp = twiml.Response()
resp.reject(reason="busy")
return str(resp)
else:
resp = twiml.Response()
call_to = "+14153XXXXXX"
resp.dial(call_to)
return str(resp)
if __name__ == "__main__":
app.run()
As there is no callback within <Reject> you will have a few options as to how you can proceed.
If you're using Python 3.3 or greater you might consider doing the whole process with asyncio.
With older versions of Python, then I would recommend you try completing the client call through a task queue as demonstrated in this post.
Please let me know if this helps at all.
I am trying to allow the current caller to leave a callback number after specifying so with the gather function.
I imagine I need to use
calls = client.calls.list(status="in-progress")
I'm not sure where to go from here. Is there even a way to get the sid of a current call so I can then get the phone number?
The calls.list() method returns a list of Call resources which you can iterate through or retrieve by index.
from twilio.rest import TwilioRestClient
ACCOUNT_SID = ACxxxxxxxxxx
AUTH_TOKEN = yyyyyyyyyyyyy
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
calls = client.calls.list(status='in-progress')
for call in calls:
print(call.sid)
first_call = calls[0]
The phone numbers related to the call in-progress are available via the to and from_ attributes. For your use case, I suspect the phone number you are looking for would be available here:
from twilio.rest import TwilioRestClient
ACCOUNT_SID = ACxxxxxxxxxx
AUTH_TOKEN = yyyyyyyyyyyyy
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
calls = client.calls.list(status='in-progress')
first_call = calls[0]
to_number = first_call.to
from_number = first_call.from_
In fact you can see all the attributes available for a call in the Call resource's __dict__ method.
from twilio.rest import TwilioRestClient
ACCOUNT_SID = ACxxxxxxxxxx
AUTH_TOKEN = yyyyyyyyyyyyy
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
calls = client.calls.list(status='in-progress')
first_call = calls[0]
print(first_call.__dict__)
Hope that helps!
The GATHER verb has an action parameter (https://www.twilio.com/docs/api/twiml/gather#attributes-action) where you can set an endpoint to receive the results of the caller's response. This call to your endpoint will contain Twilio's standard request parameters (https://www.twilio.com/docs/api/twiml/twilio_request#synchronous-request-parameters).
Your choice would be to save the caller's phone number found in the From parameter or issue another GATHER verb to prompt the caller to enter any callback number. Repeat the prior action parameter steps.
This is late, but I managed to grab the 'Caller' parameter from the request
Python Flask:
request.values.get("Caller", None)