What is the reason fo this difference in Facebook messages webhook JSON scheme? - facebook

I'm reading the Facebook Send API and events docs, and I'm surprised to see some examples define the message at the top level of the JSON object hierarchy (here for "text message")
{
"sender":{
"id":"<PSID>"
},
"recipient":{
"id":"<PAGE_ID>"
},
"timestamp":1458692752478,
"message":{
"mid":"mid.1457764197618:41d102a3e1ae206a38",
"text":"hello, world!",
"quick_reply": {
"payload": "<DEVELOPER_DEFINED_PAYLOAD>"
}
}
}
While others examples have a different object structure:
{
"id": "682498302938465",
"time": 1518479195594,
"messaging": [
{
"sender": {
"id": "<PSID>"
},
"recipient": {
"id": "<PAGE_ID>"
},
"timestamp": 1518479195308,
"message": {
"mid": "mid.$cAAJdkrCd2ORnva8ErFhjGm0X_Q_c",
"attachments": [
{
"type": "<image|video|audio|file>",
"payload": {
"url": "<ATTACHMENT_URL>"
}
}
]
}
}
]
}
Here is seems like the object is the first example is instead contained in a messaging array. I can't find either what id corresponds to in this second example : there is no table detailing the fields on why the hierarchy is different here.
Finally, there is another example with a different structure:
{
"object": "page",
"entry": [
{
"id": "<PAGE_ID>",
"time": 1583173667623,
"messaging": [
{
"sender": {
"id": "<PSID>"
},
"recipient": {
"id": "<PAGE_ID>"
},
"timestamp": 1583173666767,
"message": {
"mid": "m_toDnmD...",
"text": "This is where I want to go: https:\/\/youtu.be\/bbo_fZAjIhg",
"attachments": [
{
"type": "fallback",
"payload": {
"url": "<ATTACHMENT_URL >",
"title": "TAHITI - Heaven on Earth"
}
}
]
}
}
]
}
]
}
Are these differences documented elsewhere? Why do they exist in the first place? Why is messaging an array? Can it contain multiple messages at once?

Related

Sending WhatsApp interactive message of list type fails when sent with image header

I am able to send interactive message with "button" type and 3 buttons with image header.
But sending interactive message with "list" type and same image header fails with error:
{
"meta": {
"api_status": "stable",
"version": "2.39.4"
},
"errors": [
{
"code": 1008,
"title": "Required parameter is missing",
"details": "Failed building interactive message. Invalid Header."
}
]
}
Is it possible that "list" interactive messages doesn't support "image" header without stating it in documentation?
Successful "button" interactive payload (image URL changed):
{
"to": "972000000000",
"type": "interactive",
"interactive": {
"body": {
"text": "Select a branch for the takeaway by writing the name/number"
},
"action": {
"buttons": [
{
"reply": {
"id": "MQ==",
"title": "1"
},
"type": "reply"
},
{
"reply": {
"id": "Mg==",
"title": "2"
},
"type": "reply"
}
]
},
"type": "button",
"header": {
"image": {
"link": "https://www.google.com/images/branding/googlelogo/2x/googlelogo_light_color_272x92dp.png"
},
"type": "image"
}
}
}
Successful "button" interactive message result:
Failed "list" interactive payload (image URL changed):
{
"to": "972000000000",
"type": "interactive",
"interactive": {
"body": {
"text": "Select a branch for the takeaway by writing the name/number"
},
"action": {
"button": "Options",
"sections": [
{
"rows": [
{
"id": "MQ==",
"title": "1"
},
{
"id": "Mg==",
"title": "2"
},
{
"id": "Mw==",
"title": "3"
},
{
"id": "NA==",
"title": "4"
},
{
"id": "NQ==",
"title": "5"
},
{
"id": "Ng==",
"title": "6"
},
{
"id": "Nw==",
"title": "7"
},
{
"id": "OA==",
"title": "8"
},
{
"id": "OQ==",
"title": "9"
},
{
"id": "MTA=",
"title": "10"
}
]
}
]
},
"type": "list",
"header": {
"image": {
"link": "https://www.google.com/images/branding/googlelogo/2x/googlelogo_light_color_272x92dp.png"
},
"type": "image"
}
}
}
Well, it does state it in the docs. I'm just blind:
Kinda weird though "image" header not supported for "list".

In Netsuite REST, how do I assign an item location to an item line in a sales order?

I'm using Netsuite's Postman collection (which takes care of the Oauth1 stuff), and am POSTing to this endpoint:
{{proto}}://{{host}}/rest/platform/{{version}}/record/salesorder
... and the body is something like this:
{
"customForm": "999",
"entity": {
"id": "1111"
},
"department": {
"id": "2222"
},
"subsidiary": {
"id": "33"
},
"otherRefNum": "TEST-PO",
"location": {
"id": "444"
},
"item": {
"items": [
{
"item": { "id": "555555" },
"inventorylocation": { "id": "444" },
"price": { "id": "-1" },
"grossAmt": 999,
"quantity": 1
}
]
}
}
I'm trying to assign a location on the item level. The above request creates a sales order ok (without the line-level location assignment) if I remove the inventorylocation line, but with that in there, I get this error: Unknown reference or subrecord field inventorylocation in request body.
Netsuite's REST API documentation is here:
https://system.netsuite.com/help/helpcenter/en_US/APIs/REST_API_Browser/record/v1/2019.2/index.html#tag-salesorder
I have also tried substituting location and moving the fields around a bit, without success. (either the salesorder is created without a line-level location assignment, or I get an error similar to the above error.
Any ideas?
From the documentation you linked, it appears that the field id you need is inventorylocation rather than itemlocation.
salesorder-itemElement
...
giftCertRecipientName Recipient Name: string
id [Missing Label:id]: string
inventorydetail: salesorder-item-inventorydetail
inventorylocation: location
inventorysubsidiary: subsidiary
isClosed Closed: boolean
...
Based on the documentation for a salesOrder-itemElement, it looks like that key is correct.
Have you tried the "location": "{ID}" variation?
In LedgerSync it looks like the request for creating an invoice results in this body:
{
"entity": "309",
"location": "1",
"sublist": {
"items": [
{
"amount": 12345,
"description": "Test Line Item FLURYAOLJLFADYGR-1"
},
{
"amount": 12345,
"description": "Test Line Item FLURYAOLUFUTBYJD-2"
}
]
}
}
There also is a salesOrder-item-inventorydetail object that also contains a location. Perhaps you could use that one like so:
{
"customForm": "999",
"entity": {
"id": "1111"
},
"department": {
"id": "2222"
},
"subsidiary": {
"id": "33"
},
"otherRefNum": "TEST-PO",
"location": {
"id": "444"
},
"item": {
"items": [
{
"item": { "id": "555555" },
"inventorydetail": {
"location": "444"
},
"price": { "id": "-1" },
"grossAmt": 999,
"quantity": 1
}
]
}
}

Loopback 3 get relation from embedded model

I'm using loopback 3 to build a backend with mongoDB.
So i have 3 models: Object, Attachment and AwsS3.
Object has a relation Embeds2Many to Attachment.
Attachment has a relation Many2One to AwsS3.
Objects look like that in mongoDB
[
{
"fieldA": "valueA1",
"attachments": [
{
"id": 1,
"awsS3Id": "1234"
},
{
"id": 2,
"awsS3Id": "1235"
}
]
},
{
"fieldA": "valueA2",
"attachments": [
{
"id": 4,
"awsS3Id": "1236"
},
{
"id": 5,
"awsS3Id": "1237"
}
]
}
]
AwsS3 looks like that in mongoDB
[
{
"id": "1",
"url": "abc.com/1"
},
{
"id": "2",
"url": "abc.com/2"
}
]
The question is: how can i get Objects included Attachment and AwsS3.url over the RestAPI?
I have try with the include and scope filter. But it didn't work. It look like, that this function is not implemented in loopback3, right? Here is what i tried over the GET request:
{
"filter": {
"include": {
"relation": "Attachment",
"scope": {
"include": {
"relation": "awsS3",
}
}
}
}
}
With this request i only got the Objects with Attachments without anything from AwsS3.
UPDATE for the relation definitons
The relation from Object to Attachment:
"Attachment": {
"type": "embedsMany",
"model": "Attachment",
"property": "attachments",
"options": {
"validate": true,
"forceId": false
}
},
The relation from Attachment to AwsS3
in attachment.json
"relations": {
"awsS3": {
"type": "belongsTo",
"model": "AwsS3",
"foreignKey": ""
}
}
in AwsS3.json
"relations": {
"attachments": {
"type": "hasMany",
"model": "Attachment",
"foreignKey": ""
}
}
Try this filter:
{ "filter": { "include": ["awsS3", "attachments"]}}}}

Google Assistant flow with multiple actions_intent_OPTION handlers

I have webhooks configured through Dialogflow for a template chatbot UI starter project I'm making on Github. I have a bot integrated through Facebook Messenger and Google Assistant. All of Facebook works fine because the actions send back strings and it's easy to handle. But when Google Assistant tries to handle items of "#type": "type.googleapis.com/google.actions.v2.OptionValueSpec", actions_intent_OPTION is needed on the event in Dialogflow to handle the response. If I have just one in my app, it works fine, but when I add a second list item / carousel item of type OptionValueSpec, the flow chokes. I have details on the attached image. My guess is actions_intent_OPTION is needed to handle the list, but when I put that on multiple intents on the events section, the flow doesn't know how to handle it.
Comparison of Facebook Messenger (working) to Google Assistant (with bug)
Detailed full flow view of Google Assistant
Responses sent to Dialogflow that subsequently get sent to Google Actions...
Exact responses related to the UI pics above.
// working as expected
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "Hey there! This is a guided tour of common components between Facebook Messenger and Google Assistant."
}
},
{
"simpleResponse": {
"textToSpeech": "You can start coding the sample project at github.com/ianrichard."
}
}
],
"suggestions": [{
"title": "Show me demos!"
},
{
"title": "Show code & docs"
}
]
}
}
// working as expected
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "Animated GIFs are always fun to add to the mix!"
}
},
{
"basicCard": {
"image": {
"url": "https://somewebsite.com/colbert.gif",
"accessibilityText": "Stephen Colbert at the beginning of the show being happy."
}
}
}
],
"suggestions": [{
"title": "What about a card?"
}]
}
}
// working as expected
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "Absolutely!"
}
},
{
"simpleResponse": {
"textToSpeech": "Named for a winding stretch of Hill Country highway, Devil’s Backbone is a Belgian-style tripel. Featuring a beautiful pale-golden color, this ale’s spicy hops and Belgian yeast work together to create a distinctive flavor and aroma. Don’t let the light color fool you, this one has a dark side too. Traditional Belgian brewing techniques add strength without increasing heaviness."
}
},
{
"basicCard": {
"image": {
"url": "https://somewebsite.com/devils-backbone.jpg",
"accessibilityText": "Devil’s Backbone"
},
"title": "Devil’s Backbone",
"subtitle": "Belgian-Style Tripel",
"buttons": [{
"title": "Read More",
"openUrlAction": {
"url": "https://realalebrewing.com/beers/devils-backbone/"
}
}]
}
}
],
"suggestions": [{
"title": "How about a list?"
}]
}
}
// working as expected
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "Absolutely!"
}
},
{
"simpleResponse": {
"textToSpeech": "Who’s your favorite GOT character!?"
}
}
]
},
"systemIntent": {
"intent": "actions.intent.OPTION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
"listSelect": {
"items": [{
"optionInfo": {
"key": "tyrion"
},
"title": "Tyrion Lannister",
"description": "Peter Dinklage",
"image": {
"url": "https://somewebsite.com/got-tyrion.jpg",
"accessibilityText": "Tyrion Lannister"
}
},
{
"optionInfo": {
"key": "daene"
},
"title": "Daenerys Targaryen",
"description": "Emilia Clarke",
"image": {
"url": "https://somewebsite.com/got-daenerys.jpg",
"accessibilityText": "Daenerys Targaryen"
}
},
{
"optionInfo": {
"key": "jon"
},
"title": "Jon Snow",
"description": "Kit Harington",
"image": {
"url": "https://somewebsite.com/got-jon.jpg",
"accessibilityText": "Jon Snow"
}
}
]
}
}
}
}
// if two events with the same actions_intent_OPTION are defined, it goes straight to the end and the list option handler is never invoked
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "The end"
}
},
{
"simpleResponse": {
"textToSpeech": "Well, that’s the end of the demo. Hope you enjoyed!"
}
}
],
"suggestions": [{
"title": "Start over"
}]
}
}
// otherwise, it will show the last carousel
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "I drink and I know things!"
}
},
{
"simpleResponse": {
"textToSpeech": "What are you going to buy your wife from Tiffany?"
}
}
]
},
"systemIntent": {
"intent": "actions.intent.OPTION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
"carouselSelect": {
"items": [{
"optionInfo": {
"key": "sunglasses"
},
"title": "Aviator Sunglasses",
"description": "$360",
"image": {
"url": "https://somewebsite.com/tiffany-glasses.jpg",
"accessibilityText": "Aviator Sunglasses"
}
},
{
"optionInfo": {
"key": "ring"
},
"title": "Infinity Ring",
"description": "$200",
"image": {
"url": "https://somewebsite.com/tiffany-ring.jpg",
"accessibilityText": "Infinity Ring"
}
},
{
"optionInfo": {
"key": "earrings"
},
"title": "Soleste Earrings",
"description": "$5,600",
"image": {
"url": "https://somewebsite.com/tiffany-earrings.jpg",
"accessibilityText": "Soleste Earrings"
}
},
{
"optionInfo": {
"key": "pendant"
},
"title": "Infinity Pendant",
"description": "$250",
"image": {
"url": "https://somewebsite.com/tiffany-necklace.jpg",
"accessibilityText": "Infinity Pendant"
}
},
{
"optionInfo": {
"key": "watch"
},
"title": "East West Mini",
"description": "$7,500",
"image": {
"url": "https://somewebsite.com/tiffany-watch.jpg",
"accessibilityText": "East West Mini"
}
}
]
}
}
}
}
// but the carousel option handler isn't processed correctly :( - keeps repeating this same thing.
{
"richResponse": {
"items": [{
"simpleResponse": {
"textToSpeech": "What!? None of them?"
}
},
{
"simpleResponse": {
"textToSpeech": "What are you going to buy your wife from Tiffany?"
}
}
]
},
"systemIntent": {
"intent": "actions.intent.OPTION",
"data": {
"#type": "type.googleapis.com/google.actions.v2.OptionValueSpec",
"carouselSelect": {
"items": [{
"optionInfo": {
"key": "sunglasses"
},
"title": "Aviator Sunglasses",
"description": "$360",
"image": {
"url": "https://somewebsite.com/tiffany-glasses.jpg",
"accessibilityText": "Aviator Sunglasses"
}
},
{
"optionInfo": {
"key": "ring"
},
"title": "Infinity Ring",
"description": "$200",
"image": {
"url": "https://somewebsite.com/tiffany-ring.jpg",
"accessibilityText": "Infinity Ring"
}
},
{
"optionInfo": {
"key": "earrings"
},
"title": "Soleste Earrings",
"description": "$5,600",
"image": {
"url": "https://somewebsite.com/tiffany-earrings.jpg",
"accessibilityText": "Soleste Earrings"
}
},
{
"optionInfo": {
"key": "pendant"
},
"title": "Infinity Pendant",
"description": "$250",
"image": {
"url": "https://somewebsite.com/tiffany-necklace.jpg",
"accessibilityText": "Infinity Pendant"
}
},
{
"optionInfo": {
"key": "watch"
},
"title": "East West Mini",
"description": "$7,500",
"image": {
"url": "https://somewebsite.com/tiffany-watch.jpg",
"accessibilityText": "East West Mini"
}
}
]
}
}
}
}
Intent References
FINALLY works! Thanks #Prisoner!
In Dialogflow...
First list, define the output context
Second list, define the input context and output context
Question after the second list, define the input context
In your webhook...
(The missing piece of the puzzle that made it work)
Set the output context for the list options
{
"speech": "",
"displayText": "",
"data": { "google": { ... } },
"contextOut": [
{
"name": "carouselExample",
"lifespan": 0,
"parameters": null
}
]
}
Broadly speaking, the problem is that Dialogflow doesn't know where in the conversation you are when it gets the action_intent_OPTION event. For that event, it doesn't try to do Entity matching, but the issue of conversational context is a problem in general (what happens, for example, if you have two different option carousels which have overlapping answers?).
The solution is twofold:
When you send back the response that includes the option information, you should also set an outgoing Context. You can include other information in this Context, but in your case it sounds mostly like you just want to keep track of where you are in the conversation.
You can then differentiate the two Intents with the option event by specifying which context each should be triggered for. Dialogflow will match both the event and the context to determine the best Intent to use.

How to get the facebook fan page private messages through fql or graph

I have tried Page Messages
with the all the required permission i.e read_mailbox, read_page_mailboxes, etc (all the extended permission)
at length I get tried as
https://graph.facebook.com/456330641095467/conversations?access_token=BAAGgcfpJgfUBAHdKaE6KxMWo4rU6VU7psX7Ip4cLbG1yIvX80fkkTXm3ZApdYHmcISmqfnns1gPYZAHXWD2cXX7nMBcj4AK31uptfqJUjNAGXan1ftOK4Tw3sY1WsZD
but i get response as
{
"error": {
"message": "(#210) Subject must be a page.",
"type": "OAuthException",
"code": 210
}
}
I am unable to find out the issue. Please help.
Just use the access_token of page and you are done
yours output would be like this
{
"data": [
{
"id": "t_id.615971188431960",
"snippet": "ok fine reply on test 5:15",
"updated_time": "2013-04-16T12:15:12+0000",
"message_count": 8,
"tags": {
"data": [
{
"name": "inbox"
},
{
"name": "read"
},
{
"name": "seen"
},
{
"name": "sent"
},
{
"name": "source:web"
}
]
},
"participants": {
"data": [
{
"name": "Pragati Singh",
"email": "100000441901858\u0040facebook.com",
"id": "100000441901858"
},
{
"name": "Devdemo",
"email": "456330641095467\u0040facebook.com",
"id": "456330641095467"
}
]
},
"senders": {
"data": [
{
"name": "Devdemo",
"email": "456330641095467\u0040facebook.com",
"id": "456330641095467"
},
{
"name": "Pragati Singh",
"email": "100000441901858\u0040facebook.com",
"id": "100000441901858"
}
]
},