Twilio SMS Python - Simple send a message - python

New to Twilio, have followed the SMS Python Quickstart guide successfully, and have combined two bits together, but now have some redundant code that I can't seem to get rid of without getting errors.
I have Python code that takes in coordinates from a text message, converts this into a Google Maps link, and sends that link to a different phone number.
However, currently it is also sending this reply to the original sender phone number, as that is what the original guide has you set up.
I only want it to send the message to the specified number, not reply to the original sender.
run.py:
# /usr/bin/env python
# Download the twilio-python library from twilio.com/docs/libraries/python
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
# Download the helper library from https://www.twilio.com/docs/python/install
from twilio.rest import Client
# Your Account Sid and Auth Token from twilio.com/console
account_sid = 'account_sid'
auth_token = 'auth_token'
client = Client(account_sid, auth_token)
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def sms_reply():
messages = client.messages.list()
print(messages[0].body)
coord = messages[0].body
lat,lon = coord.split(":")
mapURL = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon
message = client.messages.create(
body=mapURL,
from_='+442030954643',
to='+447445678954'
)
"""Respond to incoming messages with a friendly SMS."""
# Start our response
resp = MessagingResponse()
# Add a message
resp.message(mapURL)
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
Whenever I take out the lines I think are to do with the replying message to sender, it seems to break some of the other lines that I still need.
Any help much appreciated, thanks!

Twilio developer evangelist here.
You don't need to reply back to the incoming message and you can avoid this by returning an empty TwiML response.
As an extra win here, you don't have to call the API to get the body of the last message that was sent. That will be available in the POST request parameters to the endpoint. You can access those via request.form so the Body parameter will be available at request.form['Body'].
Try something like this:
# /usr/bin/env python
# Download the twilio-python library from twilio.com/docs/libraries/python
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse
# Download the helper library from https://www.twilio.com/docs/python/install
from twilio.rest import Client
# Your Account Sid and Auth Token from twilio.com/console
account_sid = 'account_sid'
auth_token = 'auth_token'
client = Client(account_sid, auth_token)
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def sms_reply():
coord = request.form['Body']
lat,lon = coord.split(":")
mapURL = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon
message = client.messages.create(
body=mapURL,
from_='+442030954643',
to='+447445678954'
)
# Start our empty response
resp = MessagingResponse()
return str(resp)
if __name__ == "__main__":
app.run(debug=True)

It's because your output in your sms_reply function is returning a TwiML that sends a message. I think it's normal to have some feedback from the service. If you don't want to reply with the mapURL you can just say somethink like "Thank you".
Otherwise, you can take a look to TwiML documentation to see what other actions you can do.

Related

Inserting Twillio message history into data structure or text file

I have extracted my message history from Twillio - it prints it to python's shell. However, I cannot find a reasonable way to place it into a data structure or a text file for further analysis of the messages. My account sid and account token are hidden just for this post. Nothing is written to my txt file either.
from twilio.rest import Client
account_sid = 'XXXX'
auth_token = 'XXXX'
client = Client(account_sid, auth_token)
from twilio.twiml.messaging_response import Message, MessagingResponse
from flask import Flask, request, redirect
app = Flask(__name__) #creating a flask app
#app.route("/sms", methods=['GET', 'POST']) #creating an sms route
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Start our TwiML response
resp = MessagingResponse()
# Add a message
resp.message("The Robots are coming! Head for the hills!")
return str(resp)
text = []
messages = client.messages.list()
for record in messages:
text.append(record.body.encode("utf-8"))
My message history:
Sent from your Twilio trial account - Your verification code is: 219042
Test
Twilio developer evangelist here.
As my teammate Phil mentioned above, you seem to be conflating responding to an incoming webhook with hitting the API and fetching message history.
These Twilio docs mention how to retrieve message history in Python.
The following code writes message history to a .txt file called "chathistory.txt".
from twilio.rest import Client
account_sid = 'XXXX'
auth_token = 'XXXX'
client = Client(account_sid, auth_token)
messages = client.messages.list(limit=20)
writetofile = open("chathistory.txt", 'w')
for record in messages:
print(record.body)
writetofile.write(record.body + '\n')
writetofile.close()
Let us know if this helps at all!

How do I send 2 custom conditional responses with Twilio in Python and Flask?

I am trying to essentially loop through the Flask app with Twilio so that when a user texts a Twilio number, Twilio will greet the user but will be awaiting a second response from the user. Basically:
user texts twilio number -> twilio app greets and prompts user for another response -> user enters 2nd response by texting twilio number again -> twilio acknowledges and transaction is marked done
I get the first half of the functionality I want with:
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
#app.route("/sms", methods=['GET','POST'])
def sms_logic():
# get the message the user sent our Twilio number
body = request.values.get('Body', None)
# start our TwiML response
resp1 = MessagingResponse()
resp1.message('Hi! Please enter your name')
return(str(resp1))
...but then how do I make it execute the 2nd part of the workflow?
Thanks for your help in advance!
Twilio developer evangelist here!
We recommend building conversations like this using sessions - you can check out a tutorial for that using Python and Flask here: https://www.twilio.com/docs/sms/tutorials/how-to-create-sms-conversations-python
So you could do something like:
from flask import Flask, request, session
from twilio.twiml.messaging_response import MessagingResponse
# The session object makes use of a secret key.
SECRET_KEY = 'a secret key'
app = Flask(__name__)
app.config.from_object(__name__)
#app.route("/sms", methods=['GET', 'POST'])
def sms_logic():
# Increment the counter
counter = session.get('counter', 0)
counter += 1
# Save the new counter value in the session
session['counter'] = counter
resp = MessagingResponse()
if counter == 1:
resp.message('Hi! Please enter your name')
else:
body = request.values.get('Body', 'Friend')
resp.message('Thanks {}!'.format(body))
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
For a bigger example check out this tutorial on building an Employee directory with Python and Flask: https://www.twilio.com/docs/sms/tutorials/employee-directory-python-flask

Groupme Bot Posting Twice

I made a GroupMe bot that is supposed to echo what a specific user says, but in ALL CAPS. I used this blog to set up the bot which runs on a python server using gunicorn and Flask which is then hosted with Heroku. I have generated the bot ID and the bot successfully echoes the user, but it does so twice. I used this short code to operate the bot:
import os
import json
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from flask import Flask, request
app = Flask(__name__)
bot_id_var = 'TEST_BOT_ID'
# The url that we want to POST to
POST_url = 'https://api.groupme.com/v3/bots/post'
#app.route('/', methods=['POST'])
def webhook():
json_data = request.get_json()
if json_data['name'] == 'Dylan Powers':
# Make the message all upper case
message = json_data['text'].upper()
send_message(message)
# Constructs the message that we would like to send
def send_message(message):
POST_data = {
# Get the bot ID from environment variables
'bot_id': os.getenv(bot_id_var),
'text': message
}
request = Request(POST_url, urlencode(POST_data).encode())
json = urlopen(request).read().decode()
TEST_BOT_ID refers to an environment variable that I created that holds the bot's ID. Does anybody know why this is posting twice to group chats?

Twilio/Python - 12200 Schema validation warning

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.

Twilio returns a 401 unauthorized when using the Python SDK on Heroku

If I run my message forwarding server locally with ngrok it works, but if I deploy it Heroku however, I get a 401 unauthorized error.
My server works as follows:
First, from my phone, messages go to Twilio.
Twilio sends my app a request at /.
The app forwards the SMS body to another number, using the python
SDK to create and send a message to that number.
Twilio does expect to forward numbers to my Heroku app, I've listed the callback urls on the number.
I've also checked all my environment variables in Heroku, they are correct and contain the right keys and such, and are named properly.
My app:
from flask import Flask, request, redirect
from twilio.rest import TwilioRestClient
import twilio.twiml
import os
# log to stderr
import logging
from logging import StreamHandler
app = Flask(__name__)
file_handler = StreamHandler()
app.logger.setLevel(logging.DEBUG) # set the desired logging level here
app.logger.addHandler(file_handler)
# if getting variables from config py file use:
# app.config.from_pyfile('path/to/config/config.py')
# if using variables from environment variables
print os.environ.keys()
client = TwilioRestClient(os.environ['ACCOUNT_SID'], os.environ['AUTH_TOKEN'])
shannon = os.environ['SHANNON']
nic = os.environ['NIC']
twilio_number_uk = os.environ['TWILIO_NUMBER_UK']
twilio_number_us = os.environ['TWILIO_NUMBER_US']
#app.route("/", methods=['GET', 'POST'])
def forwardMessages():
"""Forwards texts from Shannon (US) to Nic (UK) through Twilio API.
Useful for those without international texting"""
app.logger.debug("We're in the home request")
sender = request.values.get("From")
sms_body = request.values.get("Body")
if sender and sms_body:
if sender == shannon:
# if it's from Shannon
forward_number = nic
from_number = twilio_number_uk
#forward to NIC
else:
# if it's from not SHANNON
forward_number = shannon
from_number = twilio_number_us
# forward to Shannon
forward_message = client.sms.messages.create(to=forward_number, from_=from_number, body=sms_body)
resp = twilio.twiml.Response()
app.logger.debug("Response from Twilio: " + str(resp))
return str(resp)
else:
return "Got your request"
if __name__ == "__main__":
port = int(os.environ.get('PORT', 5000))
print "Magic happenin' on port %d" % port
app.run(host='0.0.0.0', port=port)
app.run(debug=True)
I've had lots of people look at this and no one can figure it out!
Please help!

Categories

Resources