Passing arbitrary fields in a CUSTOM notification - google-glass

Is it possible to specify a payload in arbitrary fields in a menu item? Right now, I’m passing them as the id for the menu (which works but feels hacky) but I notice that if I set them as fields of the menu item, I never receive them in the POST:
MenuItem menuItem = new MenuItem()
// ... bunch skipped
.setId("5141...")
.set("eventId", "eventIdGoesHere")
;
Here is what I receive in the callback URL: I see the id in the payload field but I don’t see any "eventId" in the body of the POST:
body: {
"collection": "timeline",
"itemId": "a11d33c2-32d8-49c7-989e-2b69814e260f",
"operation": "UPDATE",
"userToken": "ya29.1....",
"userActions": [
{
"type": "CUSTOM",
"payload": "5141..."
}
]
}

You found the best practice - the ID of the menu item is returned as the payload of the user action when it is sent to you. The ID is opaque, so you are free to set it to whatever values you wish to decode however you want to.
Since the timeline itemId is also sent to you, you may also wish to set the sourceItemId or other (defined) attributes on the original timeline item to values that may contain information that will be useful to you. You can then do a timeline.get on the item to fetch this additional information.

Related

AWS Kendra PreHook Lambdas for Data Enrichment

I am working on a POC using Kendra and Salesforce. The connector allows me to connect to my Salesforce Org and index knowledge articles. I have been able to set this up and it is currently working as expected.
There are a few custom fields and data points I want to bring over to help enrich the data even more. One of these is an additional answer / body that will contain key information for the searching.
This field in my data source is rich text containing HTML and is often larger than 2048 characters, a limit that seems to be imposed in a String data field within Kendra.
I came across two hooks that are built in for Pre and Post data enrichment. My thought here is that I can use the pre hook to strip HTML tags and truncate the field before it gets stored in the index.
Hook Reference: https://docs.aws.amazon.com/kendra/latest/dg/API_CustomDocumentEnrichmentConfiguration.html
Current Setup:
I have added a new field to the index called sf_answer_preview. I then mapped this field in the data source to the rich text field in the Salesforce org.
If I run this as is, it will index about 200 of the 1,000 articles and give an error that the remaining articles exceed the 2048 character limit in that field, hence why I am trying to set up the enrichment.
I set up the above enrichment on my data source. I specified a lambda to use in the pre-extraction, as well as no additional filtering, so run this on every article. I am not 100% certain what the S3 bucket is for since I am using a data source, but it appears to be needed so I have added that as well.
For my lambda, I create the following:
exports.handler = async (event) => {
// Debug
console.log(JSON.stringify(event))
// Vars
const s3Bucket = event.s3Bucket;
const s3ObjectKey = event.s3ObjectKey;
const meta = event.metadata;
// Answer
const answer = meta.attributes.find(o => o.name === 'sf_answer_preview');
// Remove HTML Tags
const removeTags = (str) => {
if ((str===null) || (str===''))
return false;
else
str = str.toString();
return str.replace( /(<([^>]+)>)/ig, '');
}
// Truncate
const truncate = (input) => input.length > 2000 ? `${input.substring(0, 2000)}...` : input;
let result = truncate(removeTags(answer.value.stringValue));
// Response
const response = {
"version" : "v0",
"s3ObjectKey": s3ObjectKey,
"metadataUpdates": [
{"name":"sf_answer_preview", "value":{"stringValue":result}}
]
}
// Debug
console.log(response)
// Response
return response
};
Based on the contract for the lambda described here, it appears pretty straight forward. I access the event, find the field in the data called sf_answer_preview (the rich text field from Salesforce) and I strip and truncate the value to 2,000 characters.
For the response, I am telling it to update that field to the new formatted answer so that it complies with the field limits.
When I log the data in the lambda, the pre-extraction event details are as follows:
{
"s3Bucket": "kendrasfdev",
"s3ObjectKey": "pre-extraction/********/22736e62-c65e-4334-af60-8c925ef62034/https://*********.my.salesforce.com/ka1d0000000wkgVAAQ",
"metadata": {
"attributes": [
{
"name": "_document_title",
"value": {
"stringValue": "What majors are under the Exploratory track of Health and Life Sciences?"
}
},
{
"name": "sf_answer_preview",
"value": {
"stringValue": "A complete list of majors affiliated with the Exploratory Health and Life Sciences track is available online. This track allows you to explore a variety of majors related to the health and life science professions. For more information, please visit the Exploratory program description. "
}
},
{
"name": "_data_source_sync_job_execution_id",
"value": {
"stringValue": "0fbfb959-7206-4151-a2b7-fce761a46241"
}
},
]
}
}
The Problem:
When this runs, I am still getting the same field limit error that the content exceeds the character limit. When I run the lambda on the raw data, it strips and truncates it as expected. I am thinking that the response in the lambda for some reason isn't setting the field value to the new content correctly and still trying to use the data directly from Salesforce, thus throwing the error.
Has anyone set up lambdas for Kendra before that might know what I am doing wrong? This seems pretty common to be able to do things like strip PII information before it gets indexed, so I must be slightly off on my setup somewhere.
Any thoughts?
since you are still passing the rich text as a metadata filed of a document, the character limit still applies so the document would fail at validation step of the API call and would not reach the enrichment step. A work around is to somehow append those rich text fields to the body of the document so that your lambda can access it there. But if those fields are auto generated for your documents from your data sources, that might not be easy.

Show user rights and status for a REST resource

An user can have different rights to a REST resource. Like delete or edit the resource. Also child resources can have different user rights.
Example:
GET /cats -> return all cats
GET /cats/{id} -> return cat {id}
UPDATE /cats/{id} -> update cat {id}
POST /cats/{id}/like -> create a like to the cat {id}
DELETE /cats/{id}/like -> delete your like to the cat {id}
When an user requests a cat resource I want to show him the rights (allowed actions) and the status of the object.
In this example:
Is the user allowed to update the cat?
Is the user allowed to like the cat?
Does the user already like the cat?
Our UI should use this information to show allowed actions for an objects:
Update button
Like button
Dislike button
How can I add this information to my resource response. It should be possible to add the information to one resource, but also to a list of objects.
I thought about Links in the http header for all allowed actions. But this would only be possible for one object. Is their a better solution?
I'm unclear on why you can't include collection-specific links in the header of the response containing the collection. I'll take you at your word that that's not possible, but it seems like it should be an option.
Another option is to use an envelope around your response data. That will let you include metadata, including links, at the collection level.
GET /cats?owner=12
{
"totalRecords": 2,
"links": [ ... ],
"records": [ ... ]
}
EDIT (based on comment)
You should add a links property to the cat representation, either as an envelope or as a direct property. So your cat would look like:
GET /cats/354
{
"name": "Poke",
...,
"links": [
{ "rel": "like", "href": "/cats/12/like" },
....
]
}
Then, each cat in your collection will have the relevant links associated with it. This is a generally accepted alternative to using link headers.
Variations:
Some people like including the verb in the link resource, such as { "rel": "like", "verb": "POST", "href": "/cats/12/like" }
Some people like making the ref the name of the link property, such as "links": { "like": "/cats/12/like", "delete": "/cats/12" }

Getting number of page likes, post shares and website clicks

How can I get number of page likes, post shares and website clicks aggregated by ad group. Post comments and post likes are fetched through field 'inline_actions' - https://developers.facebook.com/docs/reference/ads-api/adreportstats#columns (/reportstats/date_preset=yesterday&data_columns=['adgroup_id','inline_actions']&actions_group_by=['action_type']). I need a way to fetch these report items using api, just like they are returned using https://www.facebook.com/ads/manage/reporting.php.
To get data per adgroup level you must include adgroup_id or adgroup_name in data_columns - as you're doing.
Comments, Likes and many other actions are returned in column actions
You can specify which actions types you're interested in by specifying filters:
filters=[
{
"field": "action_type",
"type": "in",
"value": [
"like",
"page_engagement",
"post_engagement",
"post_like",
"comment",
"games.plays",
"post",
"photo_view",
"link_click",
"receive_offer",
"checkin",
"mention",
"tab_view",
"vote",
"follow",
"gift_sale",
"video_play",
"video_view",
"offsite_conversion",
"offsite_conversion.checkout",
"offsite_conversion.registration",
"offsite_conversion.lead",
"offsite_conversion.key_page_view",
"offsite_conversion.add_to_cart",
"offsite_conversion.other",
"app_install",
"app_engagement",
"app_story",
"app_use",
"credit_spent",
"mobile_app_install",
"app_custom_event",
"app_custom_event.fb_mobile_activate_app",
"app_custom_event.fb_mobile_complete_registration",
"app_custom_event.fb_mobile_content_view",
"app_custom_event.fb_mobile_search",
"app_custom_event.fb_mobile_rate",
"app_custom_event.fb_mobile_tutorial_completion",
"app_custom_event.fb_mobile_add_to_cart",
"app_custom_event.fb_mobile_add_to_wishlist",
"app_custom_event.fb_mobile_initiated_checkout",
"app_custom_event.fb_mobile_add_payment_info",
"app_custom_event.fb_mobile_purchase",
"app_custom_event.fb_mobile_level_achieved",
"app_custom_event.fb_mobile_achievement_unlocked",
"app_custom_event.fb_mobile_spent_credits",
"app_custom_event.other",
"rsvp"
]
}
]
However that's optional IIRC, API should send you all non-zero actions by default.

Sharing a photo with text

The "Add a cat to that" example explains how to share a photo with my service.
But is there a way to share a photo with a text (using voice recorder) in a single item ?
Yup! You can do this using the REPLY built-in menu item.
However, the flow is a bit different than the Add a Cat to That flow. It works like this:
Subscribe to updates to the timeline collection.
Insert a timeline item with the REPLY built in action specified as shown here. Optionally, you can rename the menu item and customize the icon.
{
"text": "Hello world",
"menuItems": [
{
"action": "REPLY"
}
]
}
The timeline card will have a reply option in its menu. When the user selects it, they will be prompted to speak.
A new timeline card is then created which contains the text transcription and has an attached audio recording. Your Glassware has access to this card.
Your Glassware is then notified about this item insertion. The notification looks something like this:
{
"collection": "timeline",
"itemId": "3hidvm0xez6r8_dacdb3103b8b604_h8rpllg",
"operation": "INSERT",
"userToken": "harold_penguin",
"verifyToken": "random_hash_to_verify_referer",
"userActions": [
{
"type": "REPLY"
}
]
}
Fetch the indicated timeline item to access the transcribed text (in the text property) and the attached audio recording

real-time update page feed

here I am for real update "page", add fields to status to receive the "status" of
pages, I try to add as "link" fields to receive the subscription works but I do
not receive notification when I publish a link, it's really difficult to have
correct information
{
"object": "user",
"callback_url": "http://*/fbcallback.php",
"fields": [
"feed",
"link",
"status"
],
"active": true
}
http://bugs.developers.facebook.net/show_bug.cgi?id=18048#c40
As per the documentation at https://developers.facebook.com/docs/reference/api/realtime/ :
To setup a subscription, send a POST with the following parameters
It seems like you're posting a JSON object while you should do is a normal post with these variables (as if you're doing a with action="post").
Note, by the way, that the fields parameter needs to have a CSV value, so that would be "feed,link,status", and that there's no 'active' attribute.