How to get current callers number from Twilio IVR system? - python

I am trying to get the current call's 'To' and 'From' numbers in Twilio. I am using the Twilio IVR system example at https://www.twilio.com/docs/voice/tutorials/ivr-phone-tree-python-flask.
This is my current code:
rom twilio.twiml.voice_response import VoiceResponse
from ivr_phone_tree_python import app
from ivr_phone_tree_python.view_helpers import twiml
#app.route('/ivr/welcome', methods=['POST'])
def welcome():
response = VoiceResponse()
# TODO
# get current calls to and from numbers here
# query subaccounts and main account and find which account the caller is calling based on the To number
with response.gather(
num_digits=1, action=url_for('menu'), method="POST"
) as g:
g.say(message="Thanks for calling the E T Phone Home Service. " +
"Please press 1 for directions." +
"Press 2 for a list of planets to call.", loop=3)
return twiml(response)
#app.route('/ivr/menu', methods=['POST'])
def menu():
selected_option = request.form['Digits']
option_actions = {'1': _give_instructions,
'2': _list_planets}
if option_actions.has_key(selected_option):
response = VoiceResponse()
option_actions[selected_option](response)
return twiml(response)
return _redirect_welcome()
#app.route('/ivr/planets', methods=['POST'])
def planets():
selected_option = request.form['Digits']
option_actions = {'2': "+12024173378",
'3': "+12027336386",
"4": "+12027336637"}
if selected_option in option_actions:
response = VoiceResponse()
response.dial(option_actions[selected_option])
return twiml(response)
return _redirect_welcome()
# private methods
def _give_instructions(response):
response.say("To get to your extraction point, get on your bike and go " +
"down the street. Then Left down an alley. Avoid the police" +
" cars. Turn left into an unfinished housing development." +
"Fly over the roadblock. Go past the moon. Soon after " +
"you will see your mother ship.",
voice="alice", language="en-GB")
response.say("Thank you for calling the E T Phone Home Service - the " +
"adventurous alien's first choice in intergalactic travel")
response.hangup()
return response
def _list_planets(response):
with response.gather(
numDigits=1, action=url_for('planets'), method="POST"
) as g:
g.say("To call the planet Broh doe As O G, press 2. To call the " +
"planet DuhGo bah, press 3. To call an oober asteroid " +
"to your location, press 4. To go back to the main menu " +
" press the star key.",
voice="alice", language="en-GB", loop=3)
return response
def _redirect_welcome():
response = VoiceResponse()
response.say("Returning to the main menu", voice="alice", language="en-GB")
response.redirect(url_for('welcome'))
return twiml(response)
If I wanted to use this IVR structure for all my subaccounts when I update to a paid account, would ngrok https output and post it to all subaccounts on my Twilio dashboard? That is the reason I want to know who the To and From callers are in the IVR call, so that I can distinguish which subaccount they are calling (and use the callers number for other reasons).

To get the To and From number, you would do something as follows request.POST['From'] and request.POST['To'] this is how you would do it in Django, you'll need to modify for flask. ngrok is a way for you to host your localhost website on the web so Twilio can communicate with it. You need to update the ngrok url Twilio needs to watch for, either manually in Twilio dashboard or through Twilio api. Also look into a TwilioML App.

Related

How to process a response from the Twilio REST API

I am developing a program to help treat depression. I do not have a deep understanding of Twilio. I would like to collect the responses to this message:
Sent from your Twilio trial account - What are the positive results or outcomes you have achieved lately?
What are the strengths and resources you have available to you to get even more results and were likely the reason you got the results in the first question.
What are your current priorities? What do you and your team need to be focused on right now?
What are the benefits to all involved-you
your team and all other stakeholders who will be impacted by achieving your priority focus.
How can we (you and/or your team) move close? What action steps are needed?
What am I going to do today?
What am I doing tomorrow ?
What did I do yesterday?
and process them 1-9. The responses will be enumerated by 1-9.
I've contacted Twilio support and I read these docs https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python.
Here is what I tried:
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client
import logging
import csv
import psycopg2
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
# Set environtment variables
DATABASE = os.environ["DATABASE"]
PASSWORD = os.environ["PASSWORD"]
PORT = os.environ["PORT"]
USER = os.environ["USER"]
HOST = os.environ["HOST"]
# initialization TODO: move into env vars
MY_PHONE_NUMBER = os.environ["MY_PHONE_NUMBER"]
TWILIO_PHONE_NUMBER = os.environ["TWILIO_PHONE_NUMBER"]
TWILIO_ACCOUNT_SID = os.environ["TWILIO_ACCOUNT_SID"]
TWILIO_AUTH_TOKEN = os.environ["TWILIO_AUTH_TOKEN"]
# Configure Twillio
# Set environment variables for your credentials
# Read more at http://twil.io/secure
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
logging.debug(f"Connected to Twilio using MY_PHONE_NUMBER:{MY_PHONE_NUMBER},TWILIO_PHONE_NUMBER{TWILIO_PHONE_NUMBER}")
# Establish db connection
# use psycopg to connect to the db and create a table
conn = psycopg2.connect(
database=DATABASE, user=USER, password=PASSWORD, host=HOST, port=PORT)
conn.autocommit = True
cursor = conn.cursor()
# Step 1: Set up frequency, i.e. times to send messages
# Step 2: Load questions
questionsFile = open('questions.csv')
questions = csv.reader(questionsFile)
logging.debug(f"message:{questions}")
message = "\n".join([question for row in questions for question in row])
logging.debug(f"message: {message}")
# Step 3: Send questions
# message = client.messages.create(
# body=message,
# from_=TWILIO_PHONE_NUMBER,
# to=MY_PHONE_NUMBER
# )
# Step 4: Collect response
#app.route("/sms", methods=['GET', 'POST'])
def incoming_sms():
"""Send a dynamic reply to an incoming text message"""
# Get the message the user sent our Twilio number
body = request.values.get('Body', None)
# Start our TwiML response
resp = MessagingResponse()
# Determine the right reply for this message
if body == 'hello':
resp.message("Hi!")
elif body == 'bye':
resp.message("Goodbye")
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
# Step 5: Create a database table as the sheet name and Save responses in db
logging.debug(f'Step 2 creating table response')
# TODO: create 10 columns for saving responses (each response contains 10 answers)
sql = f'CREATE TABLE IF NOT EXISTS public.responses'
logging.debug(f'CREATE TABLE IF NOT EXISTS public.responses')
# cursor.execute(sql)
# conn.commit()
# Next steps:
# 1. Process positive and negative sentiment from responses
# 2. Calculuate total positive sentiment
# 3. Calculate total negative sentiment
# 4. Plot positive sentiment vs. negative sentiment
The documentation doesn't provide a clear path for completing step 4.
[shows response from text message.]
[messages url]
Expected
processed responses from the questions.
Actual:
Sent from your Twilio trial account - What are the positive results or outcomes you have achieved lately?
What are the strengths and resources you have available to you to get even more results and were likely the reason you got the results in the first question.
What are your current priorities? What do you and your team need to be focused on right now?
What are the benefits to all involved-you
your team and all other stakeholders who will be impacted by achieving your priority focus.
How can we (you and/or your team) move close? What action steps are needed?
What am I going to do today?
What am I doing tomorrow ?
What did I do yesterday?
I added a Twilio flow to test the connection to Twilio. This could go in two directions just python or using a Twilio flow. The flow does not work even after adding the correct number.
messages screenshot
this comes from the demo video which does not match the current UI: https://www.youtube.com/watch?v=VRxirse1UfQ.
There's a second code sample on the page you linked. This explains how you can parse the body of incoming message to read the payload with request.values.get('Body', None):
#app.route("/sms", methods=['GET', 'POST'])
def incoming_sms():
"""Send a dynamic reply to an incoming text message"""
# Get the message the user sent our Twilio number
body = request.values.get('Body', None)
# Start our TwiML response
resp = MessagingResponse()
# Determine the right reply for this message
if body == 'hello':
resp.message("Hi!")
elif body == 'bye':
resp.message("Goodbye")
return str(resp)
However, it makes sense to ask the questions after each other and this means you would need to handle many different endpoint and it can get complicated really fast.
But there's also a visual editor that allows you to define this within a few minutes in your browser: Build a Chatbot with Twilio Studio

Creating Slackbot with Google Sheets integration using python and git

My name is Ken. I am trying to create a Slack Bot first one message every Monday at 9:00 am and asks for a input (goal number of sales for the week). Then responds with user input in new message saying (great your weekly sales goal is (#). Then it takes this number and adds it to Google sheets. Then asks user to enter daily goal for the day. And responds with (daily goal set as). Then at 9:00 pm asks user to input the number of deals written and keeps track of all data in Google sheets and provides graphs. I have been thinking maybe MySQL would work for that too.
Here is some of the code I have so far:
starterbot.py
import os
import time
from slackclient import slackclient
# starterbot's ID as an environment variable
BOT_ID = os.environ.get("BOT_ID")
# contasts
AT_BOT = "<#" + BOT_ID + ">"
EXAMPLE_COMMAND = "do"
#instantiate Slack & Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
def handle_command (command, channel)
"""
Receives commnds directed at the bot and determines if they
are valid commands. if so, then acts on the commands. if not,
returns back what it needs for clarification.
"""
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
"* command with numbers, delimited by spaces."
if command.startswitch(EXAMPLE_COMMAND):
response = "Sure ... wire some more c ie then I can do
that!"
slack_client.api_call("chat.postMessage", channel=channel,
text=response, as_user=True)
def parse_slack_output(slack_messages):
"""
The Slack Real Time Messaging API is an event firehose.
this parsing function returns None unless a message is
directed at the Bot, based on its ID.
"""
if slack_messages and len(slack_messages) > 0;
for message in slack_messages:
if message and 'text' in message and AT_BOT in message['text']:
command = message['text'].split(AT_BOT)[1].strip().lower()
channel = message['channel']
# return text after the # mention, white space removed
return command, channel
return None, None
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print("starterbot connected and running!")
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")
bot_id_py
import os
from slackclient import SlackClient
import pdb
BOT_NAME = 'pilot4u'
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
if __name__ == "__main__":
api_call = slack_client.api_call("users.list")
if api_call.get('members'):
pdb.set_trace()
# Retrieve all users so we can find our bot
users = api_call.get('members')
for user in users:
if 'name' in user and user.get('name') == BOT_NAME:
print("Bot ID for '" + user ['name'] + "'is " +
user.get('id'))
else:
print("could not find bot user with the name " + BOT_NAME)

Python - Check if url exists fails

I'm trying to create a python function that will connect to a URL and check if a list of directory's exists on that website. So the input consists of a target and the directory's. My ultimate goal is to write some sort of DirBuster like program.
This is my function untill now:
def checkDir(checkDir_target):
breakurl = urlparse(target)
conn = httplib.HTTPConnection(breakurl.netloc)
conn.request('HEAD', checkDir_target)
response = conn.getresponse()
print response.status
complete = target + x
if (response.status < 400):
print(" [X] " + complete)
global total_resp
total_resp += 1
found.append(complete)
else:
print(" [ ] " + complete)
The only problem I'm having right now is that dynamic created pages like wordpress pages also return HTTP Status 200 codes. So even when I'm testing on a non-existing url the website will still return a HTTP 200 OK.
Example: testing on www.wordpressexamplesite.com/DIRECTORYTHATDOESNTEXISTS/ gives a HTTP 200 code as well as website URL's that DOES exist.
This means that the whole check in the checkDir function is not doing it's work like I want it to.
Can one of you guys give me some ideas on how to resolve this?
Unfortunately for you, when the server returns a "200 OK", then that means the URL does, in fact, exist and has the contents returned. Those contents might be a page that says "This doesn't exist". To identify that you would need to work on some artificial intelligence that can render and read the content that was returned and comprehend it like a human would.
I consider it bad web site design (and even worse for AJAX APIs) to always return "200 OK" and embed the "real" status in the payload, but that is how some people code it.
Try use requests lib:
import requests
def checkDir(checkDir_target):
breakurl = urlparse(target)
response = requests.get(breakurl.netloc, headers=checkDir_target)
complete = target + x
if response.status < 400:
print(" [X] " + complete)
global total_resp
total_resp += 1
found.append(complete)
else:
print(" [ ] " + complete)
I think this can works for you.

Getting request.form to act like raw_input in a text adventure game (twilio)

----------------------- EDIT -----------------------
I still am not sure how to get the request.form['Body'] working properly. I am likely not using this request properly, but I'm not sure how else to use it. One suggestion was make a listener, but am not sure where to start on that.
So I guess now its:
1) where am I totally buggering up?
2) Any suggestions on how to make a listener?
Here's a skeleton of my set up:
from flask import Flask, request, redirect
import twilio.twiml
from twilio.rest import TwilioRestClient
from sys import exit
twil_number = "XXXXXXXXX"
sid = "XXXXXXXXXXXXXXXXXXXX"
token = "XXXXXXXXXXXXXXXXX"
tos = "XXXXXXXXXX"
client = TwilioRestClient(sid,token)
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
##### get the SMS ####
def smsGet():
try:
action = request.form['Body']
except RuntimeError:
action = raw_input("> ")
return action.lower()
### Snd the SMS ####
def smsSend(bods):
client.sms.messages.create(to=tos, from_=twil_number, body= bods)
class TestClass(object):
def doStuff(self):
smsSend("Intro Text")
## I don't know why this is buggering up. ###
go = smsGet()
if go == "yes":
smsSend("yes")
exit(1)
else:
pass
exit(1)
a = TestClass()
a.doStuff()
#### running the app ###
if __name__ == "__main__":
app.run(debug=True)
----------------------- older -----------------------
I'm making a text adventure game in twilio/python. There's no database or anything, Its just a python based text adventure that I run locally out of a shell.
All the sending SMS things are fine, but how do I get something like this:
request.form['Body'].lower()
to work like this:
raw_input("> ").lower()
So far most things I've tried just have Flask throwing this error:
RuntimeError('working outside of request context')
So for context. A lot of my scenes are set up like this:
class Hallway(Scene):
def enter(self):
hall = "You pause in the Hallway. You could: Go to the bedroom. Go to the kitchen to see if there's food. Check on your human in the office."
send_sms(hall)
#action = raw_input("> ").lower()
#would like this to work like raw _input()
action = request.form['Body'].lower()
if action == "kitchen":
return 'kitchen'
elif action == "bedroom":
return 'bedroom'
elif action == "office":
return 'office'
else:
nope = "But I don't want to hang in the hallway..."
send_sms(nope)
return 'hallway'
And send_sms() is just this:
def send_sms(bods):
client.sms.messages.create(body=bods,to=tos,from_=froms)
Any suggestions on where I'm totally mucking up?
Thanks! :)
So, if I understand what you're trying to do correctly, you probably want something like this (note that I haven't run this, so it may have some small bugs, but the idea should be sound):
listener.py
from flask import Flask, request
from twilio.rest import TwilioRestClient
import twilio.twiml
import game
account_sid = "ACXXXXXXXXXXXXXXXXX"
auth_token = "YYYYYYYYYYYYYYYYYY"
twilio_client = TwilioRestClient(account_sid, auth_token)
app = Flask(__name__)
games = {}
#app.route("/", methods=['GET', 'POST'])
def accept_response():
from_number = request.values.get('From')
body = request.values.get('Body')
try:
games[from_number].queue.put(body)
except KeyError:
games[from_number] = game.Game(twilio_client, from_number, "your number goes here")
games[from_number].start()
return str(twilio.twiml.Response())
if __name__ == "__main__":
app.run(debug=True)
game.py
import queue
from threading import Thread
class Game(Thread)
def __init__(self, twilio, to_number, from_number):
Thread.__init__(self, name=to_number)
self.twilio = twilio
self.from_number = from_number
self.to_number = to_number
self.queue = queue.Queue()
def run(self):
# Game logic goes here, e.g.:
action = self.send_sms("You're being chased by a thing!", wait_for_response=True)
if action == "stop":
self.send_sms("That was silly. The thing eats you, you die.")
elif action == "run":
self.send_sms("You're too slow! The thing eats you, you die.")
else:
self.send_sms("I don't know what you're trying to do, but the thing eats you, you die.")
def send_sms(self, body, wait_for_response=False):
self.twilio.messages.create(body=body, to=self.to_number, from_=self.from_number)
if wait_for_response:
response = self.queue.get()
return response
So, you run the listener, and with the correct configuration on the Twilio side it just sits there and listens for SMSs. When it receives one it checks to see if a game is already running for the user. If so, it sends the body of the SMS to the game, to be used as input. Otherwise, it kicks off a new game for that user.
Each Game instance is running in it's own thread, and you can use the send_sms method of a Game instance just like raw_input, that is, the user for that game will receive the string argument as an SMS, and their reply will be the return value.
I don't know what the rest of your game logic looks like, but to integrate this with something like the Scene class in your question, you would probably want to have Scene's consructor take a Game as an argument and assign it to an attribute. So, then, in enter() you could write something like action = this.game.send_sms('foo').
It appears you can get the current thread object using threading.current_thread() (which in this case is the Game instance), so there's no need to pass it around. You can either call threading.current_thread().send_sms from anywhere, or wire it up in the constructor of your scenes.
If you want to run that code from either inside Flask or from the command line, you'll need to write a function which will get the action, either from the request or using raw_input. It could look something like this:
from flask import request
def get_action():
try:
action = request.form['Body']
except RuntimeError:
action = raw_input("> ")
return action.lower()

How do I return the Instagram Realtime subscription challenge?

I'm trying to subscribe to a tag. It appears that the callback URL is being called correctly with a hub.challenge and hub.mode, and I figured out how to access the challenge using self.request.get('hub.challenge'). I thought I was just supposed to echo the challenge, but that doesn't appear to work since I receive the following errors in the GAE logs:
InstagramAPIError: (400) APISubscriptionError-Challenge verification failed. Sent "647bf6dbed31465093ee970577ce1b72", received "
647bf6dbed31465093ee970577ce1b72
".
Here is the full handler:
class InstagramHandler(BaseHandler):
def get(self):
def process_tag_update(update):
update = update
mode = self.request.get('hub.mode')
challenge = self.request.get('hub.challenge')
verify_token = self.request.get('hub.verify_token')
if challenge:
template_values = {'challenge':challenge}
path = os.path.join(os.path.dirname(__file__), '../templates/instagram.html')
html = template.render(path, template_values)
self.response.out.write(html)
else:
reactor = subscriptions.SubscriptionsReactor()
reactor.register_callback(subscriptions.SubscriptionType.TAG, process_tag_update)
x_hub_signature = self.request.headers.get('X-Hub-Signature')
raw_response = self.request.data
try:
reactor.process('INSTAGRAM_SECRET', raw_response, x_hub_signature)
except subscriptions.SubscriptionVerifyError:
logging.error('Instagram signature mismatch')
So returning it as a string worked. I should have payed closer attention to the error message, but it took a helpful person on the Python IRC to point out the extra line breaks in the message. Once I put the template files on one line, it seemed to work. I can now confirm that my app is authorized via Instagram's list subscription URL.

Categories

Resources