Send response to Dialogflow webhook - ruby-on-rails

I'm trying to implement Dialogflow bot. I've set all intents, the response defined for the intent and webhook receiver controller. It works well but based on Fulfillment docs after Dialogflow request to my webhook service I need to send response to Dialogflow. How to do that?
Here is my webhook service:
class Api::V1::WebhooksController < ActionController::API
include ActionController::HttpAuthentication::Basic::ControllerMethods
include ActionController::HttpAuthentication::Token::ControllerMethods
http_basic_authenticate_with name: Rails.application.credentials.webhook_auth_name, password: Rails.application.credentials.webhook_auth_password
def create
action_name = params[:webhook][:queryResult][:intent][:displayName]
case action_name
when 'get-calendar'
render json: 'Show calendar', status: :ok
when 'get-room'
render json: 'Show available rooms', status: :ok
end
end
end
Which gives me that message inside Raw interaction log :
{
"queryText": "Calendar",
"parameters": {},
"fulfillmentText": "<happy>This is your calendar</happy>",
"fulfillmentMessages": [
{
"text": {
"text": [
"<happy>This is your calendar</happy>"
]
},
"lang": "en"
}
],
"intent": {
"id": "1234",
"displayName": "get-calendar",
"priority": 500000,
"webhookState": "WEBHOOK_STATE_ENABLED",
"messages": [
{
"text": {
"text": [
"<happy>This is your calendar</happy>"
]
},
"lang": "en"
}
]
},
"intentDetectionConfidence": 1234,
"diagnosticInfo": {
"webhook_latency_ms": 1234
},
"languageCode": "en",
"slotfillingMetadata": {
"allRequiredParamsPresent": true
},
"id": "1234",
"sessionId": "1234",
"timestamp": "2020-09-25T14:38:31.92Z",
"source": "agent",
"webhookStatus": {
"webhookEnabledForAgent": true,
"webhookStatus": {
"code": 3,
"message": "Webhook call failed. Error: Failed to parse webhook JSON response: Expect message object but got: \"Show\"."
}
},
"agentEnvironmentId": {
"agentId": "1324",
"cloudProjectId": "test-project"
}
}
I don't think this part is what I expected:
"message": "Webhook call failed. Error: Failed to parse webhook JSON response: Expect message object but got: \"Show\"."

DialogFlow calls your WebHook when processing an Intent, you need to ensure your code send back a JSON object which DialogFlow understands and can process. It looks like you are sending back just a text message (Show Calendar), or at least a JSON starting with `Show..'
You are using DialogFlow API v1 (this is deprecated, better move to V2) so your JSON should look like this. Normally there are SDK (Java, NodeJS, I guess Ruby too?) which provides the model and objects to work with, so you don't need to create the JSON manually but just use the API.

Related

Hasura query action exception

Got a small problem (I guess). I created c# rest web API on docker swarm environment. Rest API is working properly - tested via the postman. Then I tried to compose Hasura service on the same docker swarm environment. The console is working properly also. The problem is with query action.
Code:
Action definition:
type Query {
getWeatherForecast : [WeatherForecastResonse]
}
New types definition:
type WeatherForecastResonse {
date : String
temperatureC : Int
temperature : Int
summary : String
}
Handler:
http://{api ip}:{api port}/WeatherForecast
While trying to execute query:
query MyQuery {
getWeatherForecast {
temperature
summary
date
temperatureC
}
}
All I got from response is error with json:
{
"errors": [
{
"extensions": {
"internal": {
"error": "invalid json: Error in $: not enough input",
"response": {
"status": 405,
"body": "",
"headers": [
{
"value": "Mon, 14 Jun 2021 13:54:00 GMT",
"name": "Date"
},
{
"value": "Kestrel",
"name": "Server"
},
{
"value": "0",
"name": "Content-Length"
},
{
"value": "GET",
"name": "Allow"
}
]
},
"request": {
"body": {
"session_variables": {
"x-hasura-role": "admin"
},
"input": {},
"action": {
"name": "getWeatherForecast"
}
},
"url": "http://{api ip}:{api port}/WeatherForecast",
"headers": []
}
},
"path": "$",
"code": "unexpected"
},
"message": "not a valid json response from webhook"
}
]
}
I got desired response by using postman white calling: http://{api ip}:{api port}/WeatherForecast (GET method)
Where should I improve, to finally get desired result from rest api?
P.S. hasura version: v2.0.0-alpha.4 (tried also with v1.3.3)
UPDATE:
Released a new version of web API. Inside WeatherForecastController included a new method with POST attribute. Query remained the same, but now graphql query returns what I want.
So the question is: Is it possible to call/access web api methods with GET attribute with Hasura action query?
From the version v2.1.0 and above we can do this using the REST Connectors.Hasura Actions RESTConnectors Methods
Go to the Actions tab on the console and create or modify an action. Scroll down to Configure REST Connectors.
In the Configure REST Connectors section, click on Add Request Options Transform
Along with this you can do a lot of other configurations.
No, currently it's not possible, Hasura always makes POST requests to the action handler:
When the action is executed i.e. when the query or the mutation is called, Hasura makes a POST request to the handler with the action arguments and the session variables.
Source: https://hasura.io/docs/latest/graphql/core/actions/action-handlers.html#http-handler

graph-api: Adaptive card with mention doesn't render date properly

It seams that msteams object doesn't allow to render date, when card pushed through graph api in private msteams channel.
Example is like this:
POST https://graph.microsoft.com/v1.0/teams/{team_id}/channels/{channel_id}/messages
{
"body": {
"contentType": "html",
"content": "<attachment id=\"1\"/>"
},
"attachments":[
{
"contentType":"application/vnd.microsoft.card.adaptive",
"id":"1",
"content":"{\"type\":\"AdaptiveCard\",\"body\":[{\"text\":\"<at>Lev</at> hello {{ DATE(2021-04-28T00:00:00Z, SHORT) }}\",\"wrap\":true,\"type\":\"TextBlock\"}],\"version\":\"1.3\",\"msteams\":{\"entities\":[{\"type\":\"mention\",\"text\":\"<at>Lev</at>\",\"mentioned\":{\"id\":\"29:131...Rg\",\"name\":\"Lev\"}}]}}"
}
]
}
Example in teams
Is there some workaround?
msteams object is not allowed through Graph API. Only Bots have access to the msteams object. This is by design.
The at mention object when you send from bot, the user will get notify in teams activity and the card will display as shown in below image
and the at mention in adaptive card using graph api post request, the user will not get notify in teams activity and the card will display as shown in below image
Please check the below request body
{
"body": {
"contentType": "html",
"content": "<attachment id=\"1\"/>"
},
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"id": "1",
"content": "{ \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\", \"type\": \"AdaptiveCard\", \"version\": \"1.0\", \"body\": [ { \"type\": \"TextBlock\", \"text\": \"Your package will arrive on {{DATE(2017-02-14T06:00:00Z, SHORT)}} at {{TIME(2017-02-14T06:00:00Z)}}\", \"wrap\": true } ]}"
}
]
}

Azure Logic App: Read telemetry data as dynamic content from IoT hub message

I'm routing telemetry messages via IoT Events and event Grid to Logic Apps using a webhook. The logic app lets you input a sample JSON message and then use dynamic content to add information to an email alert I'm sending(O365: Send an Email V2)
I can include System Properties like "iothub-connection-device-id" But when I try to pick temeletry data I get the following error:
InvalidTemplate. Unable to process template language expressions in action 'Send_an_email_(V2)' inputs at line '1' and column '1680': 'The template language expression 'items('For_each')?['data']?['body']?['windingTemp1']' cannot be evaluated because property 'windingTemp1' cannot be selected. Property selection is not supported on values of type 'String'. Please see https://aka.ms/logicexpressions for usage details.'.
When I look at the raw output of the webhook connector it shows the following message but the telemetry points are cleary not there. I'd expect to see them in the "body" property but instead there is just the string: "eyJ3aW5kaW5nVGVtcDEiOjg2LjYzOTYxNzk4MjYxODMzLCJ3aW5kaW5nVGVtcDIiOjc4LjQ1MDc4NTgwMjQyMTUyLCJ3aW5kaW5nVGVtcDMiOjg1LjUzMDYxMDY5OTQ1MzY1LCJMb2FkQSI6MjAyOS44NDgyMTg4ODYxMTEsIkxvYWRCIjoyMDQwLjgxMDk4OTg0MDMzMzgsIkxvYWRWIjoyMDA0LjYxMTkzMjMyNTQ2MTgsIk9pbFRlbXAiOjk5LjA2MjMyNjU2MTY4ODU4fQ=="
Looking for help to determine what could be causing this and how to get the telemetry data passed through correctly so that I can inculde it dynamically in the email alert.
Thanks!
{
"headers": {
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip,deflate",
"Host": "prod-24.northeurope.logic.azure.com",
"aeg-subscription-name": "TEMPALERT",
"aeg-delivery-count": "1",
"aeg-data-version": "",
"aeg-metadata-version": "1",
"aeg-event-type": "Notification",
"Content-Length": "1017",
"Content-Type": "application/json; charset=utf-8"
},
"body": [
{
"id": "c767fb91-3806-324c-ec3c-XXXXXXXXXX",
"topic": "/SUBSCRIPTIONS/XXXXXXXXXXXX",
"subject": "devices/Device-001",
"eventType": "Microsoft.Devices.DeviceTelemetry",
"data": {
"properties": {
"TempAlarm": "true"
},
"systemProperties": {
"iothub-connection-device-id": "Device-001",
"iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"iothub-connection-auth-generation-id": "637264713410XXXX",
"iothub-enqueuedtime": "2020-06-01T23:05:58.3130000Z",
"iothub-message-source": "Telemetry"
},
"body": "eyJ3aW5kaW5nVGVtcDEiOjg2LjYzOTYxNzk4MjYxODMzLCJ3aW5kaW5nVGVtcDIiOjc4LjQ1MDc4NTgwMjQyMTUyLCJ3aW5kaW5nVGVtcDMiOjg1LjUzMDYxMDY5OTQ1MzY1LCJMb2FkQSI6MjAyOS44NDgyMTg4ODYxMTEsIkxvYWRCIjoyMDQwLjgxMDk4OTg0MDMzMzgsIkxvYWRWIjoyMDA0LjYxMTkzMjMyNTQ2MTgsIk9pbFRlbXAiOjk5LjA2MjMyNjU2MTY4ODU4fQ=="
},
"dataVersion": "",
"metadataVersion": "1",
"eventTime": "2020-06-01T23:05:58.313Z"
}
]
}
Here is the sample input I am using with the trigger:
[{
"id": "9af86784-8d40-fe2g-8b2a-bab65e106785",
"topic": "/SUBSCRIPTIONS/<subscription ID>/RESOURCEGROUPS/<resource group name>/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/<hub name>",
"subject": "devices/LogicAppTestDevice",
"eventType": "Microsoft.Devices.DeviceTelemetry",
"eventTime": "2019-01-07T20:58:30.48Z",
"data": {
"body": {
"windingTemp1": 95.62818310718433
},
"properties": {
"Status": "Active"
},
"systemProperties": {
"iothub-content-type": "application/json",
"iothub-content-encoding": "utf-8",
"iothub-connection-device-id": "d1",
"iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"iothub-connection-auth-generation-id": "123455432199234570",
"iothub-enqueuedtime": "2019-01-07T20:58:30.48Z",
"iothub-message-source": "Telemetry"
}
},
"dataVersion": "",
"metadataVersion": "1"
}]
Summary comment to answer to help others who have same problem.
The body you provided is Base64 encoded, you can decode it with Convert.FromBase64String(String) Method.
byte[] newBytes = Convert.FromBase64String(body);
For more details, you could refer to this issue.
Update:
Add the following code in my application will solve the problem.
message.ContentEncoding = "utf-8";
message.ContentType = "application/json";

How to delete message replies using Slack API?

I'm getting an error when I try to use Slack API to remove the replies saying the channel doesn't exists.
To validate it, I'm calling the:
https://slack.com/api/channels.history?token={token}&channel={channel}&count=1&inclusive=true&latest={ts}&oldest={ts}
Then I get the message back.
The message I'm getting back is this one:
{
"ok": true,
"latest": "1540555927.024300",
"oldest": "1540555927.024300",
"messages": [
{
"text": "This message was deleted.",
"edited": {
"user": "UD6SLKGEP",
"ts": "1540555928.000000"
},
"type": "message",
"subtype": "tombstone",
"user": "USLACKBOT",
"hidden": true,
"thread_ts": "1540555927.024300",
"reply_count": 1,
"replies": [
{
"user": "UD6SLKGEP",
"ts": "1540555928.024401"
}
],
"subscribed": false,
"unread_count": 1,
"ts": "1540555927.024300"
}
],
"has_more": false,
"is_limited": true
}
As you can see, there is this "This message was deleted." that seems to be generated automatically and keep showing up because I still have replies associated to it.
If I call the same endpoint passing the reply ts (1540555928.024401), for the same channel I get this:
{
"ok": true,
"latest": "1540555928.024401",
"oldest": "1540555928.024401",
"messages": [
{
"type": "message",
"user": "UD6SLKGEP",
"text": "45d7bc14a6fa03 23456789 abcdefghijklmnop",
"bot_id": "BD6AJUY8G",
"thread_ts": "1540555927.024300",
"ts": "1540555928.024401"
}
],
"has_more": false,
"is_limited": true
}
Which means that there is a message there, which is a reply from another message.
The problem starts when I try to remove this reply message.
I call this endpoint:
https://slack.com/api/chat.delete?token={token}
Passing the channel and the reply ts as the payload:
{
"channel": "CD65XB2D7",
"message_ts": "1540555928.024401"
}
Now instead of having the message removed, I get this response:
{
"ok": false,
"error": "channel_not_found",
"warning": "missing_charset",
"response_metadata": {
"warnings": [
"missing_charset"
]
}
}
But the channel exists and I'm using it to remove other messages as well. That happens when I try to remove the reply from a message only.
Is there something special about removing reply messages?
I just found out the problem here:
https://api.slack.com/changelog/2017-10-keeping-up-with-the-jsons#methods
For some reason on my side it's working for messages, but not for replies. I had to move the token to the "Authorization" on header with the Bearer as suggested on this link.

Unknown name \"model\" at 'config': Cannot find field

I'm trying to use Google Cloud speech (v1beta1) to analyse phone calls. I can't find the "model" parameter in the C# client library, so I'm constructing my own json message and sending it. This works:
{
"audio": {
"content": "UklGRiavCAA+P8QAAgA....."
},
"config": {
"languageCode": "nl-NL"
}
}
But when I add the phone_call model like this:
{
"audio": {
"content": "UklGRiavCAA+P8QAAgA....."
},
"config": {
"languageCode": "nl-NL",
"model": "phone_call"
}
}
I get an error:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"model\" at 'config': Cannot find field.",
"errors": [
{
"message": "Invalid JSON payload received. Unknown name \"model\" at 'config': Cannot find field.",
"domain": "global",
"reason": "badRequest"
}
],
"status": "INVALID_ARGUMENT"
}
}
Why? Accoding to the documentation I believe my request is valid?
Edit: to answer my own question: turns out I was using a wrong url. The correct url is: https://speech.googleapis.com/v1p1beta1/speech:recognize.
I'm sorry to be the bearer of bad news, but it looks like the phone call model is only supported for en-US, and your language is nl-NL:
https://cloud.google.com/speech-to-text/docs/basics
Scroll down to "Selecting Models". "Command and Search" and "Default" are both listed as available for all languages, but "video" and "phone call" are listed as "en-US only".

Resources