python sending sms with twilio - python

import os
from flask import Flask
from flask import request
from flask import url_for
from flask import render_template
from twilio.rest import TwilioRestClient
from twilio import twiml
Declare and configure application
app = Flask(__name__, static_url_path='/static')
ACCOUNT_SID = "AACxxxxx"
AUTH_TOKEN = "xxxxxx"
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
Configure this number to a toll-free Twilio number to accept incoming calls.
#app.route('/caller', methods=['GET', 'POST'])
def caller():
response = twiml.Response()
response.say("Thank you for calling" \
"Please hold.")
response.enqueue("Queue Demo", waitUrl='/wait')
return str(response)
Configure waiting room to notify user of current position in the queue and
play the sweet, soothing sounds of Twilio's coffeeshop collection.
#app.route('/wait', methods=['GET', 'POST'])
def wait():
response = twiml.Response()
twilio_client.sms.messages.create(
to="+44xxxxxxxxxx",
from_="+44xxxxxxxxxx",
body="Hey Jenny! Good luck on the bar exam!",
)
response.say("You are number %s in line." % request.form['QueuePosition'])
response.play("https://s3-us-west-2.amazonaws.com/" \
"twilio/music1.mp3")
response.redirect('/wait')
return str(response)
Connect to support queue - assign to Twilio number for agent to call.
#app.route('/agent', methods=['GET', 'POST'])
def agent():
response = twiml.Response()
with response.dial() as dial:
dial.queue("Queue Demo")
return str(response)
If PORT not specified by environment, assume development config.
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
if port == 5000:
app.debug = False
app.run(host='0.0.0.0', port=port)
Why does it not send the sms?

Ok I resolved it, so if you are using python on twilio, this is the code to have your phone system that answers the call, puts the caller on hold playing music and then sends you an sms then you can call the number to help the caller.
Here it is:
import os
from flask import Flask
from flask import request
from flask import url_for
from flask import render_template
from twilio.rest import TwilioRestClient
from twilio import twiml
Declare and configure application
app = Flask(__name__, static_url_path='/static')
Configure this number to accept incoming calls.
#app.route('/caller', methods=['GET', 'POST'])
def caller():
response = twiml.Response()
response.say("Thank you for calling " \
"Please hold.")
response.enqueue("Queue Demo", waitUrl='/wait')
return str(response)
Configure the waiting room to notify the user of their current position in the queue and play the holding music or marketing message.
#app.route('/wait', methods=['GET', 'POST'])
def wait():
response = twiml.Response()
response.say("You are number %s in line." % request.form['QueuePosition'])
response.play("https://s3-us-west-2.amazonaws.com/" \
"triptorigatwilio/eventpremrigaholdmusic1.mp3")
response.redirect('/wait')
Notify agent of call via SMS
client = TwilioRestClient("your account sid...AC...", "your account auth token...xxxx")
client.sms.messages.create(
to="put number to send sms here",
from_="put the twilio number to send sms from here",
body="A caller is in the queue. Call now to help them.",
)
return str(response)
Connect to support queue - assign to Twilio number for agent to call.
#app.route('/agent', methods=['GET', 'POST'])
def agent():
response = twiml.Response()
with response.dial() as dial:
dial.queue("Queue Demo")
return str(response)
If PORT not specified by environment, assume development config.
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
if port == 5000:
app.debug = True
app.run(host='0.0.0.0', port=port)
Don't forget to configure your active numbers in twilio. The number the caller calls should point to /caller and the number for the agent calls should point to /agent. Good luck...

Related

Python Flask background threading is not working: code is not being executed

Context:
I have a function in my views command where some varaibales is being send through a background task script after a HTTP post on form. This background script handles a lot of API calls and is converting this to JSON that is gonna be converted Because this can take a long time (because of the way the API Calls) go before the next html page is rendered I had decided to make this one a background task with threading. Eventually if possible I would like a que to be added later on.
The problem:
But the thing is even though I clearly set it to a daemon thread and everything. The code is not being executed. I the Python Console log does not even show the code being executed, so what I am doing wrong here.
Just look at Order 66 if you want the background task itself.
"""
Routes and views for the flask application.
"""
from datetime import datetime
from flask import render_template, jsonify
from FlaskWebPODTracer import app
import json
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import request, redirect, url_for, flash
# The main script that has to happen in the background.
import classified.background_script.backgroundtask as Order66
from threading import Thread
import random
import string
from celery import Celery
from flask_mail import Mail, Message
import requests
API_VERSION = "v1/"
Succes_message = "U ontvangt nog een mail wanneer de data klaar is. Bedankt om PODTracer te gebruiken."
Fail_message_1 = "Wijzig de parameters van uw aanvraag en probeer opnieuw."
Fail_message_2 = "Blijft dit voorkomen contacteer dan support."
Fail_message = Fail_message_1 + '\n' + Fail_message_2
#app.route('/handle_data/')
#app.route('/handle_data/', methods=['POST', 'GET'])
def handle_data():
#if request.method == 'GET':
# return render_template(
# "request-completed.html",
# title=
# "Aanvraag ingediend",
# objects = jsonobjects,
# year=datetime.now().year,
# message='Uw aanvraag is voltooid.'
# )
if request.method == 'POST':
email = request.form['inputEmail']
stringpart = request.form['city']
sper_year = int(request.form["Speryear"])
urlpart = request.form["api-url-input"]
url = "Classified" + API_VERSION + urlpart
print(url)
response = requests.get(url)
if response.status_code == 200:
jsonobjects = len(response.json())
task = Thread(group=None, target=None,name=Order66.main, args=(stringpart,url,sper_year,email), daemon=True)
task.start()
state = "succesvol."
message_body = Succes_message
else:
jsonobjects = 0;
state = "onsuccesvol."
message_body = Fail_message
return render_template(
"request-posted.html",
respstate = state,
body = message_body,
title=
"Aanvraag ingediend",
objects = jsonobjects,
year=datetime.now().year,
message='Uw aanvraag is ' + state
)
# TODO RUN THIS IN BACKGROUND
# app.route('/request-completed')
#app.route('/handle_data_fail')
def handle_data_fail():
jsonobjects = 0
state = "onsuccesvol."
message_body = Fail_message
return render_template(
"request-posted.html",
respstate = state,
body = message_body,
title=
"Aanvraag ingediend",
objects = jsonobjects,
year=datetime.now().year,
message='Uw aanvraag is ' + state
)
As discussed in comments, here's an oversimplified example of an event-driven system with RabbitMQ and Flask.
Dependencies you need:
(flask-rabbitmq) ➜ flask-rabbitmq pip freeze
click==8.0.3
Flask==2.0.2
itsdangerous==2.0.1
Jinja2==3.0.3
MarkupSafe==2.0.1
pika==1.2.0
Werkzeug==2.0.2
Try to create a RabbitMQ docker container with the command below:
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.9-management
your simple flask app would look like this:
from flask import Flask
from flask import request
import json
from RabbitMQPublisher import publish
app = Flask(__name__)
#app.route('/publish', methods=['POST'])
def index():
if request.method == 'POST':
publish(json.dumps(request.json))
return 'Done'
if __name__ == '__main__':
app.run()
your RabbitMQPublisher.py would be like this:
import pika
def publish(data: str):
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='0.0.0.0', port=5672))
channel = connection.channel()
channel.exchange_declare(exchange='test', exchange_type='fanout')
channel.queue_declare(queue='', exclusive=True)
channel.basic_publish(exchange='test', routing_key='', body='{"data": %s}'%(data))
connection.close()
and finally your script.py would be like this:
import pika
import json
from time import sleep
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='0.0.0.0', port=5672))
channel = connection.channel()
channel.exchange_declare(exchange='test', exchange_type='fanout')
result = channel.queue_declare(queue='', exclusive=True)
channel.queue_bind(exchange='test', queue='')
def callback(ch, method, properties, body):
body = json.loads(body.decode().replace("'", '"'))
print(body)
channel.basic_consume(
queue='', on_message_callback=callback, auto_ack=True)
channel.start_consuming()
inside the callback function in the code above, you can specify you're logic and when your logic finishes you can again use RabbitMQ to call a pattern on flask side or event do http call with requests. that would be your choice.

Dialogflow response from webhook using flask python integration platform digital human uneeq

I am trying to send a response to Dialogflow Es using webhook written in python-flask.
Integration platform :
digital human --> Uneeq
I tried with the fulfillment library (dialogflow_fulfillment) but it was not working so I tried it without a library like :
if req.get('queryResult').get('action') == 'appointment':
print("ïntent triggered")
return {"fulfillmentText": 'BUDDY!'}
It worked!
Now the issue is before integrating this chatbot to digital human I wrote the whole code using the fulfillment library. Now I need to change the whole code for this purpose.
As I am unable to extract entities using context-based intents (session-vars) like :
case = agent.context.get('session-vars').get('parameters').get('case')
name = agent.context.get('session-vars').get('parameters').get('name')['name']
email = agent.context.get('session-vars').get('parameters').get('email')
phone = agent.context.get('session-vars').get('parameters').get('phone')
So my question is how to accomplish this task successfully?
If I try to use the fulfillment library then how to send a response to Dialogflow so that digital human will understand it since "agent.add" doesn't work.
Or, If I try to do it without a library then how to extract entities(from the session-vars) like (case, name, email, phone).
I need to save all these parameters(entities) in firebase, These output context (only session-vars parameters not other contexts):
This is the response I am getting correctly without library:
Unable to proceed at any cost!
looking forward to your response.
Thanks in advance!
Complete code (with the library):
from dialogflow_fulfillment import WebhookClient
from flask import Flask, request, Response
import json
app = Flask(__name__)
def handler(agent: WebhookClient) :
"""Handle the webhook request.."""
req = request.get_json(force=True)
a= req.get('queryResult').get('action')
if req.get('queryResult').get('action') == 'appointment':
name = agent.context.get('session-vars').get('parameters').get('name')['name']
email = agent.context.get('session-vars').get('parameters').get('email')
phone = agent.context.get('session-vars').get('parameters').get('phone')
print("ïntent triggered")
agent.add('BUDDY!')
#app.route('/webhook', methods=['GET', 'POST'])
def webhook():
req = request.get_json(force=True)
agent = WebhookClient(req)
agent.handle_request(handler)
return agent.response
if __name__ == '__main__':
app.run(debug=True)
Complete code (without library):
import urllib
import json
import os
from flask import Flask
from flask import request
from flask import make_response
# Flask app should start in global layout
app = Flask(__name__)
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
res = makeWebhookResult(req)
res = json.dumps(res, indent=4)
r = make_response(res)
#print(res)
r.headers['Content-Type'] = 'application/json'
return r
def makeWebhookResult(req):
intent_name = req.get('queryResult').get('intent').get('displayName')
print(intent_name)
action_name = req['queryResult']['action']
if req.get('queryResult').get('action') == 'input.welcome':
print("intent trigered")
return {"fulfillmentText": 'Hi there'}
if action_name == 'test':
cont = req.get('queryResult').get('outputContexts')[0]['name']
print(type(cont))
x = cont.split("/")
print(x[6])
if x[6] == 'session-vars' :
para = req['queryResult']['outputContexts']
print(para)
print("test intent trigered")
return {"fulfillmentText": 'Bye there'}
if __name__ == '__main__':
app.run(debug=True)

403 IAM permission 'dialogflow.sessions.detectIntent' error in flask

I am trying to use Dialogflow in my Flask app but I am getting 403 IAM permission 'dialogflow.sessions.detectIntent' I have checked twice my role is project owner in cloud console. I am following this tutorial.
This is my app.py
from flask import Flask
from flask import request, jsonify
import os
import dialogflow
from google.api_core.exceptions import InvalidArgument
import requests
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = 'service_key.json'
DIALOGFLOW_PROJECT_ID = 'whatsappbotagent-gmsl'
DIALOGFLOW_LANGUAGE_CODE = 'en'
SESSION_ID = 'me'
app = Flask(__name__)
app.config["DEBUG"] = True
#app.route('/')
def root():
return "Hello World"
#app.route('/api/getMessage', methods = ['POST'])
def home():
message = request.form.get('Body')
mobnu = request.form.get('From')
session_client = dialogflow.SessionsClient()
session = session_client.session_path(DIALOGFLOW_PROJECT_ID, SESSION_ID)
text_input = dialogflow.types.TextInput(text = message, language_code = DIALOGFLOW_LANGUAGE_CODE)
query_input = dialogflow.types.QueryInput(text = text_input)
try:
response = session_client.detect_intent(session = session, query_input = query_input)
except InvalidArgument:
raise
print("Query text: ", response.query_result.query_text)
# sendMessage()
return response.query_result.fullfilment_text
if __name__ == '__main__':
app.run()
OK, so after a lot of searching and trial and error I found the issue.
Actually while creating a service account the user gets a service email and that email will have access to use the project but I was not adding that email in project permission emails. Adding that email in IAM & Admin > IAM > +ADD will make it work.
Maybe there was a better solution but this is what works for me and hopefully solves others problem if have similar issue like this.

Flask Socketio not updating data

I am working with Flask Socketio. My code right now console logs every time a user opens a page. However when I open the page in a new tab/window the console of the original user in not updated. Below is the code, have a look at it
let socket = io.connect("http://127.0.0.1:5000/")
socket.on("connect",() => {
socket.emit("my custom event",{text:"I have joined"})
})
socket.on("my response",function(msg) {
console.log(msg)
})
And here is the python code for flask
from flask import Flask, render_template, request
import requests
from flask_socketio import SocketIO, emit, send
app = Flask(__name__)
app.config["SECRET_KEY"] = "hope"
socketio = SocketIO(app)
#app.route('/')
def hello_world():
return render_template("index.html")
#app.route('/1')
def random_route():
return render_template("index2.html")
#socketio.on('message')
def message(data):
print(data)
#socketio.on('my custom event')
def handle_custom_event(data):
emit("my response", data)
if __name__ == "__main__":
socketio.run(app, debug=True)
The default for the emit function is to address the event only to the sender. If you want to address all your connected clients, you have to indicate so with the broadcast option:
#socketio.on('my custom event')
def handle_custom_event(data):
emit("my response", data, broadcast=True)

400 Bad Request while POSTing json to Flask on openshift

I have read all related SO questions on this but I still keep encountering this error(400 - Bad Request) when posting json to my Flask app running on RedHat's openshift cloud platform.
This is my code:
flaskapp.py
import os
from datetime import datetime
from flask import Flask, request, flash, url_for, redirect, \
render_template, abort, send_from_directory
app = Flask(__name__)
app.config.from_pyfile('flaskapp.cfg')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/<path:resource>')
def serveStaticResource(resource):
return send_from_directory('static/', resource)
#app.route("/test")
def test():
return "<strong>It's Alive!</strong>"
#app.route('/mine', methods=['POST'])
def mine():
content = request.get_json(force=True)
print content
return "Success!\n"
if __name__ == '__main__':
app.run(debug=True)
This is how my app.py looks like
#!/usr/bin/env python
# This file may be used instead of Apache mod_wsgi to run your python
# web application in a different framework. A few examples are
# provided (cherrypi, gevent), but this file may be altered to run
# whatever framework is desired - or a completely customized service.
#
import imp
import os
import sys
try:
virtenv = os.path.join(os.environ.get('OPENSHIFT_PYTHON_DIR','.'), 'virtenv')
python_version = "python"+str(sys.version_info[0])+"."+str(sys.version_info[1])
os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib', python_version, 'site-packages')
virtualenv = os.path.join(virtenv, 'bin','activate_this.py')
if(sys.version_info[0] < 3):
execfile(virtualenv, dict(__file__=virtualenv))
else:
exec(open(virtualenv).read(), dict(__file__=virtualenv))
except IOError:
pass
#
# IMPORTANT: Put any additional includes below this line. If placed above this
# line, it's possible required libraries won't be in your searchable path
#
#
# main():
#
if __name__ == '__main__':
application = imp.load_source('app', 'flaskapp.py')
port = application.app.config['PORT']
ip = application.app.config['IP']
app_name = application.app.config['APP_NAME']
host_name = application.app.config['HOST_NAME']
fwtype="wsgiref"
for fw in ("gevent", "cherrypy", "flask"):
try:
imp.find_module(fw)
fwtype = fw
except ImportError:
pass
print('Starting WSGIServer type %s on %s:%d ... ' % (fwtype, ip, port))
if fwtype == "gevent":
from gevent.pywsgi import WSGIServer
WSGIServer((ip, port), application.app).serve_forever()
elif fwtype == "cherrypy":
from cherrypy import wsgiserver
server = wsgiserver.CherryPyWSGIServer(
(ip, port), application.app, server_name=host_name)
server.start()
elif fwtype == "flask":
from flask import Flask
server = Flask(__name__)
server.wsgi_app = application.app
server.run(host=ip, port=port)
else:
from wsgiref.simple_server import make_server
make_server(ip, port, application.app).serve_forever()
And this how am posting the data:
curl -X POST -H "application/json" -d '{"key":"val"}'
https://python-bonga.rhcloud.com/mine
N/B: This works fine on localhost
I found that a POST using curl without specifying the Content-Type defaults to sending Content-Type application/x-www-form-urlencoded
http://curl.haxx.se/docs/httpscripting.html#POST
And if the (different) mimetype exists in Flask, then the json data becomes unavailable; hence request.get_json(force=True) fails.
I therefore changed my code to look for form-data first before anything else
if request.form:
content = [item for item in request.form]
print "Content:", ''.join(content)
else:
content = request.get_json(force=True)
print "Content:", content

Categories

Resources