I only get one whatsapp answer via dialogflow instead of multiple replies - python

How do I get multiple 'text answers' in whatsApp? When I add more than one 'text response' in intents they work normally in the dialogFlow console.
But when I repeat the same question on whatsapp I get only one answer box instead of 3, for example, that I had created.
I am using twilio to communicate with the whatsapp API. I also use Horoku cloud services to host the application.
Everything works normal. But I received only one message box instead of multiple in whatsapp.
I think the problem is my python code 'app.py'.
app.py
#app.route("/") #just to test Heroku cloud services
def hello():
return "Hello, World!"
#app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Fetch the message
msg = request.form.get('Body')
phone_no = request.form.get('From')
reply = fetch_reply(msg, phone_no)
# Create reply
resp = MessagingResponse()
resp.message(reply)
enter code here
return str(resp)
utils.py
import dialogflow_v2 as dialogflow
dialogflow_session_client = dialogflow.SessionsClient()
PROJECT_ID = "weather-husgcf"
def detect_intent_from_text(text, session_id, language_code='pt-BR'):
session = dialogflow_session_client.session_path(PROJECT_ID, session_id)
text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response = dialogflow_session_client.detect_intent(session=session, query_input=query_input)
return response.query_result
def fetch_reply(query, session_id):
response = detect_intent_from_text(query, session_id)
return response.fulfillment_text
https://i.imgur.com/a/b2QSYUB "ScreenShots"

Twilio developer evangelist here.
In your fetch_reply method you call on the query_result's fulfillment_text property. According the QueryResult documentation fulfillmentText is deprecated/legacy:
The text to be pronounced to the user or shown on the screen. Note: This is a legacy field, fulfillmentMessages should be preferred.
The fullfillmentMessages property is defined as a list of Message objects. So to return all 3 of your messages your code should probably loop through the messages adding them to the response, something like this:
def fetch_reply(query, session_id):
response = detect_intent_from_text(query, session_id)
return response.fulfillment_messages
Then your route should look something like this:
#app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Fetch the message
msg = request.form.get('Body')
phone_no = request.form.get('From')
replies = fetch_reply(msg, phone_no)
# Create reply
resp = MessagingResponse()
for reply in replies:
resp.message(reply.text)
return str(resp)
I haven't tested this, just worked from the DialogFlow documentation. Let me know if it helps.

Old-ish question but here's the answer (Dialogflow v2).
Assuming you have some sort of sendMessage(mobile_num, text) function, you iterate over the fulfillment_messages like this:
for message in response.query_result.fulfillment_messages:
sendMessage(mobile_num, message.text.text[0])
From the webhook you get a json like this:
{
"queryText": string,
"languageCode": string,
"speechRecognitionConfidence": number,
"action": string,
"parameters": {
object
},
"allRequiredParamsPresent": boolean,
"cancelsSlotFilling": boolean,
"fulfillmentText": string,
"fulfillmentMessages": [
{
"text": {
"text": [
"Some text"
]
}
},
{
"text": {
"text": [
"Some more text"
]
}
},
],
"webhookSource": string,
"webhookPayload": {
object
},
"outputContexts": [
{
object (Context)
}
],
"intent": {
object (Intent)
},
"intentDetectionConfidence": number,
"diagnosticInfo": {
object
},
"sentimentAnalysisResult": {
object (SentimentAnalysisResult)
}
}
where fulfillmentMessages is an array you have to iterate over.
Hope this helps.

Related

APNS Notifications: Python HTTP/2 POST request returning 404 ({"reason":"BadPath"})

I am developing a watchOS app and I want to send push notifications to my users. I have enabled "Push Notifications" in signing and capabilities and a file called "app_name WatchKit Extension" was generated containing one entitlement called APS environment whose value is set to "development".
I have also generated a .p8 file in the Apple Developer Website with the authentication key and that also gives me the key id.
I have created a Swift class called App Delegate that conforms to UNUserNotificationCenterDelegate. I have implemented the method applicationDidFinishLaunching from where I call WKExtension.shared().registerForRemoteNotifications(). Then I implemented the didRegisterForRemoteNotifications where I receive the device token and convert it into a string by executing these lines of code:
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
Then I send the token to the server. In the server I have a Python script that makes the post request to https://api.sandbox.push.apple.com:443 with the headers and notification payload. However, I always get a 404 error ({"reason":"BadPath"}).
I don't know what I am doing wrong. Am I configuring anything wrong? This is the Python script I am using:
import time
import httpx
import asyncio
import jwt
ALGORITHM = 'ES256'
APNS_AUTH_KEY = "path to .p8 file"
f = open(APNS_AUTH_KEY)
secret = f.read()
apns_token = jwt.encode(
{
'iss': 'cert_id',
'iat': time.time()
},
secret,
algorithm=ALGORITHM,
headers={
'alg':ALGORITHM,
'kid':'key_id'
}
)
dev_server = "https://api.sandbox.push.apple.com:443"
device_token = "9fe2814b6586bbb683b1a3efabdbe1ddd7c6918f51a3b83e90fce038dc058550"
headers = {
'method': 'POST',
'path': '/3/device/{0}'.format(device_token),
'autorization': 'bearer {0}'.format(apns_token),
'apns-push-type': 'myCategory',
'apns-expiration': '0',
'apns-priority': '10',
}
payload = {
"aps" : {
"alert" : {
"title" : "Hello Push",
"message": "This is a notification!"
},
"category": "myCategory"
}
}
async def test():
async with httpx.AsyncClient(http2=True) as client:
client = httpx.AsyncClient(http2=True)
r = await client.post(dev_server, headers=headers, data=payload)
print(r.text)
print(r)
asyncio.run(test())
Is there anything wrong with the way I am setting things up or performing the post request?
Thank you for your help!

How to do transition to another flow in dialogflow CX and get responce from the target flow

lets say i have 2 flows "Book appointment" and "User registration". I need to do transition from "Book appointment" Flow to "User registration" flow. I am able to do transition here but i am not getting the response from "User Registration" flow.
I have enabled the webhook in both flows.
How to get response from User registration as soon as this flow gets triggered.
let me know if there is any other possible way achieve this, but i need to do transition from backend only
Thanks in advance
import json
from flask import Flask
from flask import Response, request
import requests
app = Flask(__name__)
#app.route('/transition_userRegistration', methods=['GET', 'POST'])
def transition_userRegistration():
body = request.get_json(silent=True)
fulfillment = body['fulfillmentInfo']['tag']
print('fulfillment', fulfillment)
user_txt = body['text']
Page_ans =page_transition(user_txt)
return Page_ans
def page_transition(msg):
message= {"fulfillment_response": {
"messages": []
},
"target_flow": 'FlowID path',
}
if isinstance(msg, list):
for i in msg:
message["fulfillment_response"]["messages"].append({
"text": {
"text": [i]
}
})
else:
message["fulfillment_response"]["messages"].append({
"text": {
"text": [msg]
}
})
print('message from page', message)
return Response(json.dumps(message), 200, mimetype='application/json')
if __name__ == '__main__':
app.run(debug=True)

Make Slack API buttons "do something"

Edit: Since I asked this question I have created a ngrok URL to receive the Slack POST when the user his the button.
However, every time I press the button I get this: "POST / HTTP/1.1" 404 -
I am using a local Flask URL, code below:
from flask import Flask, request
app = Flask(__name__)
#app.route('/payload', methods=['POST'])
def incoming_slack_message():
req = request.get_json(Force=True)
info = request.form['channel_id']
print(req)
print(info)
print('did it work???')
return 'action successful'
#app.route('/slack/blocks', methods=['POST'])
def incoming_slack_options():
req = request.get_json(Force=True)
info = request.form['payload']
print(req)
print(info)
print('Did it work here??')
return 'ok'
if __name__ == '__main__':
app.run(port=3000, debug = True)
I have read that I need to include a callback_id in the block but whenever I do I get TypeError: 'NoneType' object is not subscriptable
This is the block I am using less the callback_id
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Once your machine is selected, click here."
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Change",
},
"value": "click_me_123",
"action_id": "button"
}
}
I am SURE something is wrong in my flask code as I know little to nothing about Flask. I don't think there's anything wrong with my Slack Block but I still feel there should be a callback_id. Thank you for your time.
Okay I got the button to generate a response! The Flask code is as follows
from flask import Flask, request, Response, jsonify
import requests
import json
app = Flask(__name__)
#app.route('/', methods=['POST'])
def resp():
data = request.json
button_info = request.form['payload']
webhook_url = 'webhook from slack'
slack_data = { 'text': "How can I help you?"}
response = requests.post(
webhook_url, data=json.dumps(slack_data),
headers={'Content-Type': 'application/json'}
)
return(jsonify(data), print(button_info))
if __name__ == '__main__':
app.run(port=3000, debug = True)
The button_info will print out all the data.
I'm sure I can get rid of some of these line/imports and it will still work but this will get the job done!
*** This code is in conjunction with a ngrok public URL for the local web server.
brew cask install ngrok followed by
ngrok http 3000 to match the 3000 port in my code
Thewebhook_url is from the slack API website.

Custom HTTP Exceptions in Python

I want to make a python script to automate JIRA-similar ticket responses.
For this, I am using json and requests library. Since http requests can be quite unreliable sometimes, I wanted to my script to retry the HTTP request in case it fails. So far I have this:
def openNewTicket(queueID, subject, content):
post_url = "{}/ticket/".format(default_url)
#Filling body OBJ
myObj = { "ContentType": "text/plain",
"Subject" : subject,
"Content": content,
"Queue": queueID,
"CustomFields": { "33": "alarm", "26": "yes", "24": "technical incident" }
}
#Formatting obj to json
jsonBody = json.dumps(myObj)
print jsonBody
try:
response = requests.post(post_url, data=jsonBody, headers=authorization_header))
date = datetime.datetime.now()
writeLog("{} - Created ticket {}\n".format(date, response['id']))
rocketChat.sendChatMessage("modem", "Sucessfully created ticket {}".format(response['id']))
return 0
except Exception:
time.sleep(1)
return openNewTicket(queueID, subject, content)
The problem is: For some reason when I get 201 status code(created), it counts as an Exception and iterates again. Is there a way I can tell python that 201 status code is not an Exception?

Create python proactive messaging with microsoft bot framework

What are the steps to create a push notification/proactive messaging bot using Python with microsoft bot framework? Since there's no official documentation yet, I don't really know where to start.
I have imported the following:
from botbuilder.schema import Activity, ActivityTypes, ConversationReference
How can it be used and what's a very simple example?
I worked a sample demo which based on state management sample for you .
Pls follow the setps to make it work :
1.Adding code below into app.py :
#APP.route("/api/notify", methods=["POST"])
def notify():
if request.headers["Content-Type"] == "application/json":
body = request.json
else:
return Response(status=415)
activity = Activity().deserialize(body)
auth_header = (
request.headers["Authorization"] if "Authorization" in request.headers else ""
)
async def aux_func(turn_context):
await BOT.on_turn(turn_context)
try:
task = LOOP.create_task(
ADAPTER.process_activity(activity, auth_header, aux_func)
)
LOOP.run_until_complete(task)
return Response(status=201)
except Exception as exception:
raise exception
2.Modify function on_message_activity in state_management_bot.py as code below
async def on_message_activity(self, turn_context: TurnContext):
# Get the state properties from the turn context.
if(turn_context.activity.channel_id != 'notify'):
await turn_context.send_activity("You asid:" + turn_context.activity.text);
else:
await turn_context.send_activity("You get a notify : "+ turn_context.activity.text);
Run this sample locally on Azure bot emulator, click the message from bot and note the conversation id and serviceUrl :
Use postman or restclient to do a post call to trigger the notify endpoint with json content :
{
"text": "this is a notify sent from outside ",
"textFormat": "plain",
"type": "message",
"channelId": "notify",
"from": {
"id": "backend",
"name": "xxxxx",
"role": "xxxxxx"
},
"conversation": {
"id": "<conversation id>"
},
"recipient": {
"id": "",
"name": "bot",
"role": "bot"
},
"serviceUrl": "<service URL>"
}
Result :

Categories

Resources