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

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>

Related

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

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

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: *************"

Angular 5 display result from JSON response

I am trying to access the "list" parameter in the following data set received from [Open weather map][1]. I basically need to access the list layer in the below set where I can get the temp parameter.
{
"cod":"200",
"message":0.0046,
"cnt":37,
"list":[
{
"dt":1518080400,
"main":{
"temp":297.81,
"temp_min":295.457,
"temp_max":297.81,
"pressure":1011.64,
"sea_level":1018.79,
"grnd_level":1011.64,
"humidity":71,
"temp_kf":2.35
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"clouds":{
"all":0
},
"wind":{
"speed":3.76,
"deg":322.502
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 09:00:00"
},
{
"dt":1518091200,
"main":{
"temp":298.03,
"temp_min":296.468,
"temp_max":298.03,
"pressure":1010.47,
"sea_level":1017.64,
"grnd_level":1010.47,
"humidity":65,
"temp_kf":1.57
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03d"
}
],
"clouds":{
"all":48
},
"wind":{
"speed":4.77,
"deg":315
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 12:00:00"
},
{
"dt":1518102000,
"main":{
"temp":294.89,
"temp_min":294.104,
"temp_max":294.89,
"pressure":1011.17,
"sea_level":1018.11,
"grnd_level":1011.17,
"humidity":77,
"temp_kf":0.78
},
"weather":[
{
"id":802,
"main":"Clouds",
"description":"scattered clouds",
"icon":"03d"
}
],
"clouds":{
"all":44
},
"wind":{
"speed":4.91,
"deg":287.002
},
"sys":{
"pod":"d"
},
"dt_txt":"2018-02-08 15:00:00"
}
]}
I am not sure as to how to go about it. I keep on getting this error "ERROR Error: Cannot find a differ supporting object"
I tried looping through it like below
this.http.get('http://api.openweathermap.org/data/2.5/forecast?id=3362024&APPID=bbcf57969e78d1300a815765b7d587f0').subscribe(data => {
this.items = JSON.stringify(data);
console.log(this.items);
for(var i = 0; i < this.items.length; i++){
this.min = this.items[i].dt;
console.log(this.min);
}
});
Try this. Make sure you import following import on top of the component
import 'rxjs/Rx';
or
import 'rxjs/add/operator/map'
getData(){
this.http.get('https://api.openweathermap.org/data/2.5/forecast?id=3362024&APPID=bbcf57969e78d1300a815765b7d587f0')
.map(res=>res.json()).subscribe(data => {
this.items = data;
console.log(this.items);
for(var i = 0; i < this.items.list.length; i++){
this.min = this.items.list[i].main;
console.log(this.min);
}
});
}
WORKING DEMO
Do console.log(data); and check what kind of data you are getting from API.
If you are getting JSON data from API, then do not do JSON.stringify(data);
If you are getting JSON contained in string then do JSON.parse();
After this you will get JSON in a variable and you can iterate it as follows
Also, do not post your api key in question , others can hit API using your api key
this.http.get('http://api.openweathermap.org/data/2.5/forecast?id=yourId&APPID=yourapikey')
.subscribe(data => {
var res = JSON.parse(data); //if you are getting JSON in a string, else do res = data;
for(var i = 0; i < res.list.length; i++){
console.log(res.list[i].main.temp);
}
});
Considering you are correctly getting json response:=>
One way is :
if you know response in advance and its basic structure is always same then:
you can create a model object similar to the json response and assign the json response to that object and access any values.
e.g.
export class TopLayer{
fieldName1: dataType;
fieldName2: Array<SecondLayer>;
}
export class SecondLayer{
fieldName1: datatype;
fieldName2: ThirdLayer;
}
export class ThirdLayer{
fieldName: datatype
}
another is: assign your json response to a var variable then access what you need:
e.g.
var x = response;
var list = x.list;
We can also do:
this.http.get("some-api-url")
.subscribe((response)=>{
for (let key in response) {
if (response.hasOwnProperty(key)) {
let element = response[key];
let singleData = {id: element.id, value: element.value};
this.dataArray.push(singleData);
}
}
},
(error)=>{
console.log(error)
});
When the response is like [{}, {}, ...]

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);
}
});
}

Handle multipart/form-data with Serverless?

How to handle multipart/form-data with serverless-framework? v.0.5.6
Just tried this:
"requestTemplates": {
"multipart/form-data": {
"httpMethod": "$context.httpMethod",
"body": "$input.json('$')",
"queryParams": "$input.params().querystring",
"headerParams": "$input.params().header",
"headerParamNames": "$input.params().header.keySet()",
"contentTypeValue": "$input.params().header.get('Content-Type')"
},
"application/json": {
"httpMethod": "$context.httpMethod",
"body": "$input.json('$')",
"queryParams": "$input.params().querystring",
"headerParams": "$input.params().header",
"headerParamNames": "$input.params().header.keySet()",
"contentTypeValue": "$input.params().header.get('Content-Type')"
}
}
action.js:
export function respond(event, cb) {
var form = new formidable.IncomingForm();
form.parse(event, function(err, fields, files) {
if (err == null) {
var response = {
status: "true",
data: fields,
error: []
};
return cb(null, response);
} else {
console.log(err);
return cb(null, ApiErrors.errors(402, err['message'] + fields));
}
});
}
But got an error: errorMessage = "Cannot read property 'content-length' of undefined";
I've got this working with serverless by emulating http.ClientRequest and using a form parser tool like formidable.
I'm using lambda-proxy for the API Gateway event configuration.
const Stream = require('stream').Readable;
const Formidable = require('formidable');
module.exports.upload = ( e, ctx, cb ) => {
let form = new Formidable.IncomingForm();
let stream = new Stream();
stream.push( e.body );
stream.push( null );
// NOTE: You'll likely want to toLowerCase() at least 'Content-Type' header key
stream.headers = e.headers;
form.parse( stream, (err, fields, files) => {
// Work with your parsed form results here.
});
}
Well, I couldnt make it as multipart/form-data, so I used base64 string.
action.js:
export function respond(event, cb) {
//console.log('Received event:', JSON.stringify(event, null, 2));
var key = new Date().toISOString().substr(0, 10) + '/' + String(Date.now());
var contentType = event.body["data"].substr(0, event.body["data"].indexOf(';'));
if (!contentType.match(/(\.|\/)(gif|jpe?g|png)$/i)) {
return cb(null, 'invalid content type, gif, jpg, and png supported');
}
var data = new Buffer(event.body["data"].replace(/^image\/\w+;base64,/, ''),'base64');
var params = {
Bucket: 'your-bucket',
Key: key,
Body: data,
ContentEncoding: 'base64',
ContentType: contentType,
ACL: 'public-read'
};
s3.upload(params, function (err, data) {
if (err) {
console.log(err);
return cb(null, ApiErrors.errors(402, err['message']));
} else {
var response = {
status: "true",
data: {
url: urlPrefix + key
},
error: []
};
return cb(null, response);
}
});
}
RequestTemplate:
"requestTemplates": {
"application/json": {
"httpMethod": "$context.httpMethod",
"body": "$input.json('$')",
"header": "$input.params().header.get($header)",
"headerParam": "$input.params().header.keySet()",
"contentType": "$input.params().header.get('Content-Type')"
}
},

Resources