Can Facebook Messenger Webview access the LocalStorage API to store data on client side? - facebook-messenger

I want to store 6 booleans on the user side, if he reaches 6 sites in a city.
Can I use LocalStorage or even cookies, inside the Messenger Webview ?
If I close the Webview and open it again, will the data be still there ?

After test, yes it can.
So you can easily open a button to the Webview like that in your botfile app.js on the server :
function openWebview(sender_psid, text,button_text){
let button_response = {
"attachment": {
"type": "template",
"payload": {
"template_type": "button",
"text": text,
"buttons": [
{
"type":"web_url",
"url":"<URL>",
"title":button_text,
"webview_height_ratio": "compact",
"messenger_extensions": "true",
"fallback_url": "<FB_URL>"
}
],
}
}
}
callSendAPI(sender_psid, button_response);
}
to be complete...
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
request({
"uri": "https://graph.facebook.com/v2.6/me/messages",
"qs": { "access_token": PAGE_ACCESS_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!')
} else {
console.error("Unable to send message:" + err);
}
});
}
and on index.html on client side by example you can store simple data as easy as :
<div id='myDiv'>nothing for the moment</div>
<script>
localStorage.setItem('key1','myValue1')
var test = localStorage.getItem('key1')
document.getElementById('myDiv').innerHTML = test
</script>
You will now see 'myValue1' displayed on the Facebook Messenger Webview

Related

Github Login (oAuth ) from react- chrome extension

I am building a simple chrome extension which will make some simple API calls.
For this, I need the user to be logged in with a Github Account, however, if I set up a new oAuth app on github, I need to add Homepage URL and Authorization callback URL which, as far as I understand, we don't have from a Chrome Extension popup.
IMPORTANT: I don't want to use firebase. All I need is to be able to get the user code, which I can process in my backend after to get the token and all the rest.
Need you help here ! :-)
Here is my background file
const GITHUB_AUTHORIZATION_UL = "https://github.com/login/oauth/authorize";
const CLIENT_ID = encodeURIComponent("xxxx");
const SCOPE = encodeURIComponent("user:email");
let user_signed_in = false;
function create_auth_endpoint() {
let endpoint_url = `${GITHUB_AUTHORIZATION_UL}
?client_id=${CLIENT_ID}
&scope=${SCOPE}`;
return endpoint_url;
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === 'login') {
chrome.identity.launchWebAuthFlow({
url: create_auth_endpoint(),
interactive: true
}, (response) => {
console.log(response)
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError)
console.log("Could not authenticate.");
sendResponse('fail');
} else {
user_signed_in = true;
sendResponse('success');
}
});
return true;
} else if (request.message === 'logout') {
user_signed_in = false;
sendResponse('success');
}
});
And my login handler from popup.tsx
const handleLogin = () => {
chrome.runtime.sendMessage({ message: 'login' }, function (response) {
console.log(response)
if (response === "success") {
window.close();
}
});
Manifest:
{
"name": "test ext",
"description": "test ext",
"version": "1.0.0",
"manifest_version": 3,
"icons": {
"16": "favicon-32.png",
"48": "favicon-32.png",
"128": "favicon-32.png"
},
"action": {
"default_popup": "popup.html",
"default_title": "test ext",
"default_icon": "favicon-32.png"
},
"permissions": ["storage", "identity"],
"options_page": "options.html",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}
]
}
I tried with various options for the requested url for github such as : http://chrome-extension://CHROME_ID/popup.html
=> This fails directly.
Interestingly, if I just input https://www.google.com, I have a popup with the github login, then I am directly to google and it fail.
However, the extension authorization is added as "accepted" in my github account.
Here is my log from the background for response :
{message: 'The user did not approve access.'}eventhough I approved it. Once I am redirected to the popup with www.google.com it fails

Alexa Proactive Events API returns 403 for unicast type -- No enablement for clientId

I am using Amazon's Alexa skills API and proactive events API to send notifications to my Alexa skill. I am able to send notification with multicast, but it does not work for delivery type "Unicast"
I am getting HTTP status code: 403 and error message as:
"No enablement for clientId:amzn-*********"
I have followed the Alexa skills proactive API documentation
When sending notification to endpoint
https://api.amazonalexa.com/v1/proactiveEvents/stages/development
I obtain the accesstoken using skill credentials and add the accesstoken as bearer token to the request.
Note: I have already enabled the skill from https://alexa.amazon.in and
I got the Amazon userId, apiAccesstoken, and consentToken. I stored them in my database (mongoDB).
I use the Amazon userId to send the notification
<pre>
<code>
var uuid = require('node-uuid');
var accessToken = "This`enter code here` token will be obtained from amazon oauth api.";
var userId = "amzn1.ask.account.AH2ZEP5WGJGAEPWPOG3Getc.....";
var uuid = require('node-uuid');
var referenceId = uuid.v4();
var now = new Date();
var expiresOn = addMinutes(now, 300);
var eventData = {
"timestamp": new Date(),
"referenceId": uuid,
"expiryTime": expiresOn,
"event": {
"name": "AMAZON.MessageAlert.Activated",
"payload": {
"state": {
"status": "UNREAD",
"freshness": "NEW"
},
"messageGroup": {
"creator": {
"name": "Andy"
},
"count": 5,
"urgency": "URGENT"
}
}
},
"localizedAttributes": [
{
"locale": "en-US",
"MessageAlert": "UNREAD"
},
{
"locale": "en-GB",
"MessageAlert": "UNREAD"
}
],
"relevantAudience": {
"type": "Unicast",
"payload": {
"user": userId
}
}
};
var opt = {
data: eventData,
token: accessToken
}
sendRequest(opt, function(err, ret, code) {
console.log("err : ",JSON.stringify(err, null, 2));
console.log("ret : ",JSON.stringify(ret, null, 2));
console.log("code : ",JSON.stringify(code, null, 2));
});
function sendRequest(options, callback) {
var data = options.data;
var token = options.token;
var headers = {
"Content-Type": "application/json",
"Authorization":"Bearer "+token
};
var opt = {
url: "https://api.amazonalexa.com/v1/proactiveEvents/stages/development",
method: "POST",
headers: headers,
body: JSON.stringify(data)
};
request(opt, function(error, response, body){
var statusCode = (response && response.statusCode) ? response.statusCode : "";
if(error) {
return callback(error);
} else if(body) {
try {
var result = JSON.parse(body);
return callback(null, result, statusCode);
} catch(e) {
console.log("e.message : ",e.message);
return callback(null, body, statusCode);
}
} else {
return callback(null, body, statusCode);
}
});
}
</code>
</pre>
The result should be HTTP status code with 202.
But I receive the HTTP status code 403 and the error message as:
"No enablement for clientId: *************"

How to sort data coming from the API by date in Angular 4

This is the JSON data i am fetching from POSTMAN. I want it to be ordered in a nearest to todays date. I tried many angular pipes but unfortunately nothings working. Any help would be great. I want to sort the date by the "broadcastOn" field. Thanks in advance.
[ {
"messageId": "09ca0609-bde7-4360-9d3f-04d6878f874c",
"broadcastOn": "2018-02-08T11:06:05.000Z",
"message": "{"title":"Server Side Test 2","text":"Different Message again","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0a5b4d0c-051e-4955-bd33-4d40c65ce8f7",
"broadcastOn": "2018-02-08T10:36:27.000Z",
"message": "{"title":"Broadcast","text":"Broadcast","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0a98a3f3-aa30-4e82-825a-c8c7efcef741",
"broadcastOn": "2018-02-08T11:45:00.000Z",
"message": "{"title":"Me sending the message","text":"Me sending the message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
},
{
"messageId": "0cb4e30f-756a-4730-a533-594ddcd45335",
"broadcastOn": "2018-02-08T11:01:57.000Z",
"message": "{"title":"Server Side Test","text":"Different Message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}"
}
]
Im adding a snippet from the service section as well for your reference..
addMessage(message) {
let header: Headers = new Headers();
header.append('Authorization', 'bearer' + this.authservice.getAccessToken());
let options = new RequestOptions({headers: header});
this.sent.push(message);
return this.http.post('https://sexhops8j5.execute-api.us-west-2.amazonaws.com/dev/notifications/broadcast', message, options)
.map(response =>
{
return response.json();
});
}
getMessage(){
let header: Headers = new Headers();
header.append('Authorization', 'bearer' + this.authservice.getAccessToken());
let options = new RequestOptions({headers: header});
return this.http.get('https://sexhops8j5.execute-api.us-west-2.amazonaws.com/dev/notifications/sent', options)
.map(response => {
let message=[];
for(let item of response.json()){
let parsedMessages = JSON.parse(item.message);
message.push({...parsedMessages, BroadcastOn: item.broadcastOn,MessageId: item.messageId});
}
console.log(message);
return message;
});
}
I'm adding a snippet of the .ts file as well
sendMessage(form){
this.messageService.addMessage({message:this.form.value.string, title:this.form.value.titleText, url:this.form.value.imageurl, image:this.form.value.image, broadcastOn:this.date})
.subscribe(message => { this.getSentMessages();console.log(message);}
);
this.message = '';
this.inputImage='';
this.inputTitle='';
this.inputString='';
this.inputUrl='';
}
getSentMessages(){
this.messageService.getMessage()
.subscribe(message => {this.sentMessages = message});
}
It's not necessary lodash, nor moment. broadcastOn is a string. The date is yyy-mm-ddTHH:mm, so, if a date is bigger that other, the string is bigger that other
getSentMessages(){
this.messageService.getMessage()
.subscribe(message => {
this.sentMessages = message.sort((a,b)=>{
return a.broadcastOn==b.broadcastOn?0
:a.broadcastOn>b.broadcastOn?1:-1
}));
});
}
With help of lodash and moment you can do it like this :
var sortedMessages = _.sortBy(messages, function(o) { return
moment(o.broadcastOn);
}).reverse();
//OR (With ES6 way)
var sortedMessages = _.sortBy(messages,(o) => moment(o.broadcastOn) ).reverse();
WORKING DEMO (Angular 5)
var messages = [ {
"messageId": "09ca0609-bde7-4360-9d3f-04d6878f874c",
"broadcastOn": "2018-02-08T11:06:05.000Z",
"message": {"title":"Server Side Test 2","text":"Different Message again","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0a5b4d0c-051e-4955-bd33-4d40c65ce8f7",
"broadcastOn": "2018-02-08T10:36:27.000Z",
"message": {"title":"Broadcast","text":"Broadcast","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0a98a3f3-aa30-4e82-825a-c8c7efcef741",
"broadcastOn": "2018-02-08T11:45:00.000Z",
"message": {"title":"Me sending the message","text":"Me sending the message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
},
{
"messageId": "0cb4e30f-756a-4730-a533-594ddcd45335",
"broadcastOn": "2018-02-08T11:01:57.000Z",
"message": {"title":"Server Side Test","text":"Different Message","image":"https://api.adorable.io/avatars/285/abott#adorable.png","url":"https://www.google.co.in"}
}
]
var sortedMessages = _.sortBy(messages, function(o) { return moment(o.broadcastOn); })
.reverse();
console.log(sortedMessages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.core.js"></script>

Can't get my Facebook messenger bot to respond with response from my service

I have made an Api.Ai bot and integrated it with both Slack and Facebook Messenger. When I write to it, it answers with the responses set up in Api.Ai for both Slack and Facebook Messenger, but on the fulfillment part, when Api.Ai makes a call to my service, it works fine in Slack, but I get no response from Facebook Messenger.
The format of the message I return from my service:
{
"contextOut": [
{
"lifespan": 2,
"name": "weather",
"parameters": {
"city": "Rome"
}
}
],
"data": {
"facebook": {
"message": {
"text": "Great success!"
},
"recipient": {
"id": "1454102654663349"
}
},
"slack": {
"attachments": [
{
"color": "#00A399",
"title": "Hello world!",
"title_link": "https://www.mywebsite.se"
}
],
"text": "Horray! Great success! :)"
}
},
"displayText": "Whatever!!",
"followupEvent": {
"followupEvent": {
"data": {
"parameter": "<parameter_value>"
},
"name": "<event_name>"
}
},
"source": "mywebsite.se",
"speech": "Whatever!?"
}
The Facebook recipient id comes from the request made to my service.
request.result.contexts[0].parameters.Facebook_sender_id
I have verified my webhook under the product settings tab in the Facebook app.
I have subscribed my app to the page using my page access token.
I have checked the following events under webhooks: messages, messaging_postbacks
I'm logged in as the admin user of the app, when trying the bot in Facebook.
I'm out of ideas, there must be something I've missed?
EDIT:
I've set up an Azure Function as my webhook for testing purposes.
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
var request = await req.Content.ReadAsAsync<ApiAiMessage>();
log.Info($"Incoming: {JsonConvert.SerializeObject(request)}");
var slack_message = new {
text = $"Horray! Great success! :)",
attachments = new[] {
new {
title = "Hello world!",
title_link = "https://www.mywebsite.se",
color = "#00A399"
}
}
};
var facebook_message = new {
recipient = new {
id = $"{request.result.contexts[0].parameters.Facebook_sender_id}"
},
message = new {
text = "Great success!"
}
};
var response = new
{
data = new
{
facebook = facebook_message,
slack = slack_message
},
speech = "Whatever!?",
displayText = "Whatever!!",
contextOut = new[] {
new {
name = "weather",
lifespan = 2,
parameters = new {
city = "Rome"
}
}
},
source = "mywebsite.se",
followupEvent = new {
followupEvent = new {
name = "<event_name>",
data = new {
parameter = "<parameter_value>"
}
}
}
};
log.Info($"Outgoing: {JsonConvert.SerializeObject(response)}");
return req.CreateResponse(HttpStatusCode.OK, response, new MediaTypeHeaderValue("application/json"));
}
Where are you actually sending the API.ai response back to Facebook Messenger? This requires some FB specifics like the 'page token' and the fact it works for Slack but not FB makes me believe it's just something simple left out like this. Here's an example in javascript of what the call would look like
function callSendAPI(messageData) {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {
access_token: config.FB_PAGE_TOKEN
},
method: 'POST',
json: messageData
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
if (messageId) {
console.log("Successfully sent message with id %s to recipient %s",
messageId, recipientId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
} else {
console.error("Failed calling Send API", response.statusCode, response.statusMessage, body.error);
}
});
}

Unable to Get Contacts on FirefoxOS

I have a FirefoxOS device and I am trying to create an application to manage the contacts. I am unable to get the contacts both from the Device and the Simulator (both have 1.3 version)
Following is my code (taken from the help):
var cursor = navigator.mozContacts.getAll({});
cursor.onsuccess = function() {
if (cursor.result) {
console.log("Got contact with name: " + cursor.result.name.join(" "));
cursor.continue();
} else {
alert("Done!");
}
};
cursor.onerror = function() {
alert("Error getting contacts");
console.log( cursor );
};
Following is the segment from my manifest file:
...
"permissions": {
"storage": {
"description": "Required for storing data"
},
"contacts": {
"description": "Needed to access the contacts",
"access": "readonly"
}
},
...
It always falls to the onerror function. Need help.
Did you set in the manifest:
"type": "privileged",
?
Otherwise please post the the value of cursor.error when it fails.

Resources