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?
Related
import telebot
from telebot import types, TeleBot
from flask import Flask, request
class Exception_Handler:
def handle(self, e: Exception):
# Here you can write anything you want for every type of exceptions
if isinstance(e, ApiTelegramException):
if e.description == "Forbidden: bot was blocked by the user":
print("Attention please! The user {} has blocked the bot. I can't send anything to them".format(message.from_user.username))
secret = "RANDOM_NUMBER"
bot: TeleBot = telebot.TeleBot('TOKEN', threaded=False, exception_handler = Exception_Handler())
bot.set_webhook("http://NAME.pythonanywhere.com/{}".format(secret), max_connections=1)
app = Flask(__name__)
#app.route('/{}'.format(secret), methods=["POST"])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.get_data().decode('utf-8')
update = telebot.types.Update.de_json(json_string)
bot.process_new_updates([update])
return ''
else:
flask.abort(403)
what needs to be done to make it work?
I expected the webhook to work normally, maybe it's a certificate, if so, how to get it for the pythonanywhere service?
In your code you have this line:
bot.set_webhook("http://NAME.pythonanywhere.com/{}".format(secret), max_connections=1)
That's using a non-HTTPS URL for the webhook, as the error message says. Try using this instead:
bot.set_webhook("https://NAME.pythonanywhere.com/{}".format(secret), max_connections=1)
I'm attempting to create a Flask application in Python that communicates with a RESTful API that uses OAuth2.0, but I'm having trouble sending requests. I'm successfully getting an access token from the server, but when I try to make a GET or POST request, I always get a 404 as a response. I'm new to RESTful API's so I don't know what I could possibly be doing wrong here or what a 404 means in this context.
Here is the .py file where I attempt to send a GET and POST request to the API. TokenHandler is just a helper class I made that keeps track of token related info, and the print(response) lines always print "Response [404]".
from flask import Flask, render_template, request, redirect
from src.apitest import TokenHandler
import requests
from oauthlib.oauth2 import LegacyApplicationClient
from requests_oauthlib import OAuth2Session
import json
app = Flask(__name__)
token_handler = TokenHandler()
#app.route('/find_customer')
def find_customer():
return render_template('customer_find_page.html')
#app.route('/find_customer', methods=['POST'])
def find_customer_get():
customer_id = request.form['text0']
oauth = OAuth2Session(client=LegacyApplicationClient(client_id=token_handler.CLIENT_ID))
oauth.fetch_token(token_url=token_handler.TOKEN_ENDPOINT,
username=token_handler.USERNAME, password=token_handler.PASSWORD, client_id=token_handler.CLIENT_ID,
client_secret=token_handler.CLIENT_SECRET,
scope=token_handler.SCOPE)
response = oauth.get("https://sedonacloudtest.com/api/customers/"+customer_id)
print(response)
return redirect('/find_customer')
#app.route('/add_customer')
def add_customer():
return render_template('customer_add_page.html')
#app.route('/add_customer', methods=['POST'])
def add_customer_post():
customer_id = request.form['text0']
customer_name = request.form['text1']
data = {"customer_id": customer_id, "customer_name": customer_name}
oauth = OAuth2Session(client=LegacyApplicationClient(client_id=token_handler.CLIENT_ID))
oauth.fetch_token(token_url=token_handler.TOKEN_ENDPOINT,
username=token_handler.USERNAME, password=token_handler.PASSWORD, client_id=token_handler.CLIENT_ID,
client_secret=token_handler.CLIENT_SECRET,
scope=token_handler.SCOPE)
response = oauth.post("https://sedonacloudtest.com/api/customers", data=data)
print(response)
return redirect('/add_customer')
if __name__ == "__main__":
app.run()
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
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.
I am new to API, and get a tasks of creating POST API. I have created a code somehow.
I want to add data to the hello.txt through post API, So how will I do it?
Here is my code:
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
app.config["DEBUG"] = True
#app.route('/api/v1/resources/messages', methods = ['POST'])
def api_message():
if request.headers['Content-Type'] == 'text/plain':
return "Text Message: " + request.data
elif request.headers['Content-Type'] == 'application/octet-stream':
return "Binary message written!"
elif request.headers['Content-Type'] == 'application/json':
f = open('F:\Asif_Ahmed\Projects\api\hello.txt',"w")
f.write(request.data)
f.close()
return "JSON Message: " + json.dumps(request.json)
else:
return "415 Unsupported Media Type ;)"
app.run()
from flask import Flask, jsonify, render_template, request #import flask library
from flask_basicauth import BasicAuth # import flask library for create basic authentication if needed
from flask_cors import CORS # import flask library Cross-Origin Resource Sharing that is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin
app = Flask(__name__)
CORS(app) #set-up cors for my app
#if you want use basic authentication you need set-up username and password
app.config['BASIC_AUTH_USERNAME'] = 'admin'
app.config['BASIC_AUTH_PASSWORD'] = 'password'
basic_auth = BasicAuth(app)#set-up username and password for my app but in this case I'm not specifying yet in which API use them
#app.route('/api/v1/resources/add_messages', methods=['POST'])#create my POST api
#basic_auth.required# set-up basic authentication for this API, comment out if not needed
def update_credential ():
json_credential=request.get_json()#get the JSON sent via API
print (json_credential["message"])#get the node "message" of my JSON
###########
#code to write in your file, you need write the json_credential["message"]
###########
return ("ok")
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1024, threaded=True)#start my flask app with local_host IP and specific port, if you don't specify the port it will run in the default port
In this case the JSON Input should be:
{"message":"your text"}
Please let me know if something is not clear, I even try this code on my local and the JSON is passed without problems.....
So you need run your python script and see that the API is running, if you had no JSON to send and was just a simple API that give back information you should have used even Chrome but in this case that you need send some JSON data I would advice you to use Postman.
See screenshot example: