I'm learning python and as a project I'm trying to create a program that will recieve an SMS message, process it, and then depending on what is in that message, send back information.
I am using Twilio in python with Flask and ngrok to do all the SMS stuff, but I am still not sure how to actually receive an SMS as data that I can read and process, as there is no documentation that I can find on it. It would be great if someone could help me with this.
I already know how to receive and send SMS with Twilio, I just need to know how to get the precise message that was sent to my Twilio number.
I believe you already know how to configure Twilio to hit your endpoint when a message comes in. If you configure at Twilio for a POST request, then the data passed to you from Twilio will be in request.form.
If you take a look at Twilio's example here:
(https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python)
indeed the example makes no use of the data that is coming in.
The modified code below shows some data that is available from the request (and you can write your code depending on what you'd like to do with it).
the number from where the message was sent request.form['From'],
your Twilio number request.form['To']
and the body of the message request.form['Body']
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
#app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Use this data in your application logic
from_number = request.form['From']
to_number = request.form['To']
body = request.form['Body']
# Start our TwiML response
resp = MessagingResponse()
# Add a message
resp.message("The Robots are coming! Head for the hills!")
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
Some other parameters are also available in the request:
MessageSid
SmsSid
AccountSid
MessagingServiceSid
From
To
Body
NumMedia
Docs: (https://www.twilio.com/docs/sms/twiml#request-parameters)
Also you can find more examples if you google for "twilio blog python flask"
Related
I'm trying to write functional tests for a twilio application using flask and python. For the very first step, I will send a text that will trigger the twilip app to reply. I want to test this and make sure the app is replying with the right text.
I'm new to python and I'm not sure how to add assertions or integrate pytest within this. I'm expecting my messages in a certain order as well. What else can I use besides the else if statements. At the end of the last reply, I want to print something to the console that will tell me my test passed. Can I integrate a testing with this? Thanks in advance
app = Flask(__name__)
def send_sms():
account_sid = os.environ['TWILIO_ACCOUNT_SID']
auth_token = os.environ['TWILIO_AUTH_TOKEN']
client = Client(account_sid, auth_token)
message = client.messages \
.create(
body='I am interested in joining',
from_='+15017122661',
to='+15558675310'
)
#app.route("/sms", methods=['GET', 'POST'])
def incoming_sms():
body = request.values.get('Body', None)
resp = MessagingResponse()
if 'Please enter your name' in body:
# I want to write assertions for the messages in the body
resp.message("John Doe")
elif 'Please enter your age' in body:
resp.message("20")
elif 'Please enter your city' in body:
resp.message("Los Angeles")
elif 'Please enter your state' in body:
resp.message("California")
return str(resp)
if __name__ == "__main__":
send_sms()
app.run()
I would not recommend actually sending SMS messages, or even making API requests, as part of your tests. You should not need to test external dependencies, just test your own responses.
In this case, you seem to be testing your responses to incoming Twilio messages. You can use pytest and Flask to achieve this. You can use Flask's built in test_client for this, by making POST requests to your endpoints with the data you want to test with and then make assertions against the response.
The Flask documentation on testing is fairly comprehensive on how to go about this. I'd read through there and see how far you get. If you get particularly stuck, then I'd recommend asking a new question here and sharing the code and tests you've tried to write.
So, i have this code:
import os
from twilio.rest import Client
xml=f'''
<Response>
<Say language="ru-RU">Здравствуйте, пожалуйста введите код для подтверждения.</Say>
</Response>'''
account_sid = ('AC274461ad47988c753424a3c8735dbcc1')
auth_token =('8ac88e8d5bce419ae3b5cbac4fc255f9')
client = Client(account_sid, auth_token)
call = client.calls.create( twiml=xml,
to='+375336412273',
from_='+12318247004',
)
print(call.sid)
I want to put in xml, that way, so i could put result of (what user typed in) in variable.
I want to do it only with python and twilio.rest, on twilio site i only found how to do it with flask, url and twiml.
Twilio developer evangelist here.
In order to be able to run interactive phone calls, there needs to be a way for your application to give instructions to Twilio, receive responses and then give further instructions. The instructions are the TwiML that you send to Twilio, but the way that Twilio communicates things back to you, like the result of what a user typed during a <Gather>, is via webhooks. Webhooks are HTTP requests from Twilio that include data about the call, like user input, in the body of the request.
To use that data and provide Twilio with further TwiML instructions your application needs to be able to receive HTTP requests and respond with an HTTP response containing the TwiML.
There are example in the Twilio documentation using Flask because Flask is a good way to receive and respond to HTTP requests in Python. You could build an application without a framework like Flask, but you would still need to be able to receive an incoming HTTP request and respond to it.
I have this function that runs fine on its own but when I try to call to it in another program it doesnt work, I want to use it to check if a message has been received and then respond if one has.
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
from flask import Flask
app = Flask(__name__)
#app.route("/sms", methods =['POST'])
def sms_reply():
number = request.form['From']
m_b = request.form['Body']
response_message='unknown response, type KEW for a list of known words'
resp = MessagingResponse()
print(m_b)
if m_b=='hello' or m_b== 'Hello':
response_message='Hi,how are you?'
elif m_b=='KEW' or m_b== 'kew' or m_b== 'Kew':
response_message='hello, ..... yeh thats only one i have set up so far im still testing it'
resp.message(response_message)
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
the program its being called in
def bot():
timer=time.time()
sold_out=True
print('Bot is starting')
print('Loading item page')
still_running_check=0
while sold_out==True: #while item is sold out reload the page and print sold out to the console
driver.get(item_url)
#time.sleep(1)
sold_out=check_exists_by_xpath("/html/body/div[3]/main/div[2]/div[3]/div[2]/div/div/div[6]/div[1]/div/div/div/button")
still_running_check+=1
sms_reply()
#if still_running_check%100==0:
#sms('Bot is still running and is on attempt '+str(still_running_check)+'\n '+str(round((time.time()-timer)/60,2))+' minute(s) have passed')
if sold_out==False:
break
else:
print ("Sold out")
cart_button = driver.find_element_by_class_name("fulfillment-add-to-cart-button") #once sold out is no longer true add to cart button is clicked
cart_button.click()
time.sleep(1)
driver.get("https://www.bestbuy.com/checkout/r/fast-track") #navigates to checkout page
time.sleep(1)
code= driver.find_element_by_xpath('//*[#id="credit-card-cvv"]') #csv input location
code.send_keys(security_code) #inputs previously given csv code
time.sleep(2)
#confirm_button= driver.find_element_by_class_name("button--place-order-fast-track")
#confirm_button.click()
print('Order submission screenshot saved as "OrderSubmission.png" in repository location') #order completion code
driver.get_screenshot_as_file('OrderSubmission.png')
sms('Bot Program executed succesfully for '+title.text)
end=input(title.text+' program executed succesfuly hit enter to exit browser or type retry to start bot again:') #if program ran all the way through will print program ran succesfully
if end=='retry':
bot()
this returns the error "Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem."
I looked in the flask documentation and saw this
"This should typically only happen when testing code that expects an active request. One option is to use the test client to simulate a full request. Or you can use test_request_context() in a with block, and everything that runs in the block will have access to request, populated with your test data."
but I don't really understand what its saying and how to implement that into my code
Twilio developer evangelist here.
Your first function, sms_reply, looks as though it is set up to receive an incoming webhook from Twilio when an SMS message is sent to your Twilio phone number. The function receives an incoming HTTP request, checks the body of the message, constructs a reply and returns it as the response to the request.
The problem is that you are then trying to call that function, which is expecting to respond to an HTTP request, inside your second bit of code, which does not seem to have an HTTP request related to it at all.
You might find that you want to use the Twilio REST API if you want to list messages that you have received or send a message. I'm not sure exactly what your code is trying to do, so I can't be more specific than that.
I have a small script that sends text messages with Twilio using Python.
This is my code:
import os
from twilio.rest import Client
account_sid = os.environ.get('TWILIO_ACCOUNT_SID')
auth_token = os.environ.get('TWILIO_AUTH_TOKEN')
client = Client(account_sid, auth_token)
cell_number = os.environ.get('CELL_PHONE_NUMBER')
text_message = input("Enter a message to send: ")
send_message = client.messages.create(from_=os.environ.get('TWILIO_PHONE_NUMBER'),
to=cell_number,
body=text_message
print(send_message)
And this is the response I get back:
<Twilio.Api.V2010.MessageInstance account_sid=MY_ACCOUNT_SID sid=SMc5e8f335198144b4b3c7f401af511f11>
I was wondering what the best way was to validate that the message was actually sent in code.
I thought of doing something like this:
if send_message:
print("Message sent.")
else:
print("Message not sent.")
And I was just wondering if there was a better way to do that.
I understand that this is a relatively old question and you might have figured out a way to achieve the desired behavior, but just wanted to post my thoughts so that it may help other learners like me in the future.
So basically, twilio provides developers with a functionality of webhooks using which the status of messages can be tracked. You will have to provide an extra parameter while creating the message wherein you will have to pass the callback url pointing to a server which will be logging the status of the sent messages.
When your python script sends a SMS by doing a POST request to twilio server, twilio will send the status of the message to the callback URL as a parameter by making a post or a get request.
This document describes how to achieve the above behavior with the help of example code snippets. In case you used another method to track the status of the messages, let us know so that it will help the community.
Right now I have a program that receives an SMS message, posts the body of the message, and then forwards the SMS to another number. However I'm receiving an error from Twilio about the "Scheme validation." The code functions exactly as it should, but I'd like to fix the error.
Initially I had the following code:
import RUAlertsTwilioWEBSERVER
import twilio.twiml
import time
import praw
from flask import Flask, request, redirect
from twilio.rest import TwilioRestClient
from passwords import *
from twilio import twiml
def login():
r = praw.Reddit(app_ua)
r.set_oauth_app_info(app_id, app_secret, app_uri)
r.refresh_access_information(app_refresh)
return r
r=RUAlertsTwilioWEBSERVER.login()
client = TwilioRestClient(account_sid, auth_token)
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def AlertService():
TheMessage=request.form.get("Body")
if (TheMessage != None):
print(TheMessage)
client.messages.create(to=ePhone,from_=tPhone,body=str(TheMessage))
r.submit(*submit to reddit code*)
return str(TheMessage)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")
The Twilio debugger gives me
Content is not allowed in prolog.
Warning - 12200
Schema validation warning
The provided XML does not conform to the Twilio Markup XML schema.
I tried to get the XML needed for the post by changing my code to the following (Only the relevant part)
#app.route("/", methods=['GET', 'POST'])
def AlertService():
TheMessage=request.form.get("Body")
if (TheMessage != None):
print(TheMessage)
resp = twiml.Response()
XML = resp.say(TheMessage)
client.messages.create(to=ePhone,from_=tPhone,body=XML)
r.submit(*submit to reddit code*)
return str(resp)
return str(TheMessage)
This code didn't work so I changed body=XML to body=str(XML). However now it just sends the XML as the body and I receive the error:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'Say'. One of '{Sms, Message, Redirect}' is expected.
Warning - 12200
Schema validation warning
The provided XML does not conform to the Twilio Markup XML schema.
How can I fix this?
Twilio evangelist here.
<Say> is not a valid TwiML verb to include in response to a request made to a Message Request URL. Its only valid for Voice Requests.
If you want to send a message back to the person who sent the text message to Twilio use the <Message> verb.
resp = twilio.twiml.Response()
resp.message(message)
Also, it looks like you are sending the TwiML as the message of the new outbound SMS message. I think you can replace that with just the Body param.
client.messages.create(to=ePhone,from_=tPhone,body=TheMessage)
Hope that helps.