Node.js loop through nested Javascript object - javascript

I want to have posts + attachments from Facebook so I can create a list of posts. The problem is that I want to put attributes: id, message and any attachment in a array for every post feed. I'm not sure whether I need to iterate objects inside a array or can I select the ID and get the related information.
Also I'm using async.waterfall() to get synchronous calls because I will make other calls that depend on the previous call.
I tried this to get the id, message and src url of attachment:
var async = require("async");
var graph = require('fbgraph');
async.waterfall([
getFeed,
getPostPicture,
], function (err, result) {
});
function getFeed(callback) {
graph.get("/.../feed" + "?fields=message,attachments&access_token=APPID|APPSECRET", function(err, res) {
callback(null, res);
});
}
function getPostPicture(arg1, callback) {
var feedData = arg1.data;
for(var i in feedData)
{
var id = feedData[i].id;
var message = feedData[i].message;
var feedAttachment = feedData[i].attachments
for (var j in feedAttachment)
{
var attachment = feedAttachment.data;
var attachmentURL = attachment[i].src;
for (var j in attachmentURL)
{
var attachmentURL = feedAttachment.src;
}
}
}
console.log(attachment);
}
Above will output:
[ { description: 'post message 1',
media: { image: [Object] },
target:
{ id: '...',
url: 'https://www.facebook.com/.../photos/a............/.../?type=3' },
title: 'Timeline Photos',
type: 'photo',
url: 'https://www.facebook.com/.../photos/a............/.../?type=3' } ]
Below is the response where I first called graph.get in the source code
and I need { data -> [message, id, attachments -> data[src] ]}
{
"data": [
{
"message": "post message 1",
"id": "..._...",
"attachments": {
"data": [
{
"description": "picture 1",
"media": {
"image": {
"height": 256,
"src": "https://scontent.xx.fbcdn.net/v/t1.0-9/..._..._..._n.png?oh=...&oe=...",
"width": 256
}
},
"target": {
"id": "...",
"url": "https://www.facebook.com/.../photos/a............/.../?type=3"
},
"title": "Timeline Photos",
"type": "photo",
"url": "https://www.facebook.com/.../photos/a............./..../?type=3"
}
]
}
},
{
"message": "Test status update 123",
"id": "..._..."
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.8/.../feed?fields=message,attachments&format=json&since=...&access_token=...&limit=25&__paging_token=enc_...&__previous=1",
"next": "https://graph.facebook.com/v2.8/.../feed?fields=message,attachments&format=json&access_token=...&limit=25&until=...&__paging_token=enc_..."
}
}

When you are using the for loop in getPostPicture function, the i variable is actually the element in the array feedData, so you have to i.id or i.attachments and i.message. Also I think since you are using same j in 2 loops with one nested inside the other, it also won't work properly, so you might have to change that also, and explain you question with the kind of output you are expecting.

Related

Looping through items in an object for google sheets

I am trying to loop through an array that is part of a JSON object from a page speed insights call to add all of the unused javascript Urls to a google sheet using the script editor.
Here is an example of the JSON object:
"audits": {
"unused-javascript": {
"id": "unused-javascript",
"title": "Remove unused JavaScript",
"description": "Remove unused JavaScript to reduce bytes consumed by network activity. [Learn more](https://web.dev/unused-javascript/).",
"score": 0.43,
"scoreDisplayMode": "numeric",
"numericValue": 1350,
"numericUnit": "millisecond",
"displayValue": "Potential savings of 231 KiB",
"details": {
"type": "opportunity",
"headings": [
{
"key": "url",
"valueType": "url",
"subItemsHeading": {
"key": "source",
"valueType": "code"
},
"label": "URL"
},
{
"key": "totalBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceBytes"
},
"label": "Transfer Size"
},
{
"key": "wastedBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceWastedBytes"
},
"label": "Potential Savings"
}
],
"items": [
{
"url": "https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable",
"totalBytes": 140229,
"wastedBytes": 108197,
"wastedPercent": 77.15757011763822
},
{
"url": "https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js",
"totalBytes": 306716,
"wastedBytes": 106243,
"wastedPercent": 34.63892414884589
},
{
"url": "https://www.googletagmanager.com/gtm.js?id=GTM-KZ",
"totalBytes": 127214,
"wastedBytes": 21845,
"wastedPercent": 17.17151000374831
}
],
"overallSavingsMs": 1350,
"overallSavingsBytes": 236285
}
},
I am attempting to loop through the "items" array within the "unused-javascript" object and get all of the urls to show in google sheets.
Here is the code I have within the script editor. When I run this, only one URL shows on the sheet. However, I am trying to get all of the URLs added to the sheet.
function pageSpeed(Url) {
var key = "AIzaSyAyHY";
var serviceUrl = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + Url + "&key=" + key;
var array = [];
if (key == "YOUR_API_KEY")
return "Please enter your API key to the script";
var response = UrlFetchApp.fetch(serviceUrl);
if (response.getResponseCode() == 200) {
var content = JSON.parse(response.getContentText());
if ((content != null) && (content["lighthouseResult"] != null)) {
if (content["captchaResult"]) {
var timetointeractive = content["lighthouseResult"]["audits"]["interactive"]["displayValue"].slice(0, -2);
var firstcontentfulpaint = content["lighthouseResult"]["audits"]["first-contentful-paint"]["displayValue"].slice(0, -2);
var firstmeaningfulpaint = content["lighthouseResult"]["audits"]["first-meaningful-paint"]["displayValue"].slice(0, -2);
var speedindex = content["lighthouseResult"]["audits"]["speed-index"]["displayValue"].slice(0, -2);
var unusedJs = content["lighthouseResult"]["audits"]["unused-javascript"]["details"]["items"];
for (var i = 0; i < unusedJs.items.length; i++) {
var unusedUrl;
unusedUrl = unusedJs[i]["url"]
}
}
else {
var timetointeractive = "An error occured";
var firstcontentfulpaint = "An error occured";
var firstmeaningfulpaint = "An error occured";
var speedindex = "An error occured";
var unusedJs = "An error occured";
}
}
var currentDate = new Date().toJSON().slice(0, 10).replace(/-/g, '/');
array.push([timetointeractive, firstcontentfulpaint, firstmeaningfulpaint, speedindex, currentDate, "complete", unusedUrl]);
Utilities.sleep(1000);
return array;
}
}
Any and all help is appreciated!
You're on the right track.
Take a look below at my usage of Array.prototype.map. That's the simpler route.
Your for loop would work just as well IF you declared unusedUrl outside of (ie. before) the loop AND pushed to an existing array. As it is, there's an issue of scope, so unusedUrl is redeclared on every iteration, meaning you'll only assign the last iteration's value to unusedUrl.
Both solutions are below.
Using map
var content = {
lighthouseResult: {
audits: {
'unused-javascript': {
// Other stuff
details: {
// Other stuff
items: [
{
url:
'https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable',
totalBytes: 140229,
wastedBytes: 108197,
wastedPercent: 77.15757011763822,
},
{
url:
'https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js',
totalBytes: 306716,
wastedBytes: 106243,
wastedPercent: 34.63892414884589,
},
{
url: 'https://www.googletagmanager.com/gtm.js?id=GTM-KZ',
totalBytes: 127214,
wastedBytes: 21845,
wastedPercent: 17.17151000374831,
},
],
overallSavingsMs: 1350,
overallSavingsBytes: 236285,
},
},
},
},
}
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = items.map(item => item.url) // OR, using es6, items.map(({ url }) => url)
console.log(unusedUrls)
Using for
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = []
for (var i = 0; i < items.length; i++) {
unusedUrls.push(items[i]['url'])
}

Node.JS ajax to replace existing JSON data

I need help replacing data inside of a JSON file using NODE.JS. My current method adds it with the same ID which is correct. However, when the data is received back, it drops the last duplicate because it found the old value first. I think what I really need to do is select JSON element by ID. Then replace it with the new.
Here is my AJAX request:
putComment: function(commentJSON, success, error) {
$.ajax({
type: 'post',
url: 'http://localhost:8080',
data: JSON.stringify(commentJSON),
success: function(comment) {
success(comment)
},
error: error
});
},
Here's my NODE:
if (req.method == 'POST') {
req.on('data', function(chunk) {
var element = JSON.parse(chunk);
fs.readFile("comments-data.json", 'utf8', function(err, json) {
var array = JSON.parse(json);
array.push(element);
fs.writeFile("comments-data.json", JSON.stringify(array), function(err) {
if (err) {
console.log(err);
return;
}
console.log("The file was saved!");
});
});
res.end('{"msg": "success"}');
});
};
Here is the data with duplicate id's:
[
{
"id": "c1",
"parent": null,
"created": "2016-08-12T19:57:21.282Z",
"modified": "2016-08-12T19:57:21.282Z",
"content": "test",
"fullname": "John Clark",
"profile_picture_url": "https://viima-app.s3.amazonaws.com/media/user_profiles/user-icon.png",
"created_by_current_user": true,
"upvote_count": 0,
"user_has_upvoted": false
},
{
"id": "c1",
"parent": null,
"created": "2016-08-12T19:57:21.282Z",
"modified": 1471031853696,
"content": "test 123",
"fullname": "John Clark",
"profile_picture_url": "https://viima-app.s3.amazonaws.com/media/user_profiles/user-icon.png",
"created_by_current_user": true,
"upvote_count": 0,
"user_has_upvoted": false
}
]
Are you just trying to replace the item if it exists? If so, you could do something like this:
var array = JSON.parse(json);
var isNew = true;
for (var i = 0; i < array.length; i++) {
if (array[i].id === element.id) {
array[i] = element;
isNew = false;
break;
}
}
//doesn't exist yet
if (isNew) {
array.push(element);
}
fs.writeFile("comments-data.json", JSON.stringify(array), function(err) {
if (err) {
console.log(err);
return;
}
console.log("The file was saved!");
});

Tableau json API WebConnector

I've written the following tableau webconnector to pull data from an internal API, using earthquakeUSGS.html as a guideline (https://github.com/tableau/webdataconnector). The API returns json (see code below). I've been using the "Web data connector simulator 2.0" and all has been going well. I get the correct Table, however, Im unable to "Fetch Table Data". As this is my first js script, Im very sure that is were the error is. To iterate through the data I used the answer from Korijn in this post Iterate through nested json object array
The Problem: Is probably with the js iterator over the json object. If anyone can take a look at the json (below), and have a look at my iterator, I would greatly appreciate it. This is what makes it impossible for me to fetch data.
test.js
(function() {
// Create the connector object
var myConnector = tableau.makeConnector();
// Define the schema
myConnector.getSchema = function(schemaCallback) {
var cols = [{
id: "prog",
alias: "PrognosisTime",
dataType: tableau.dataTypeEnum.string
}, {
id: "start",
alias: "Start",
dataType: tableau.dataTypeEnum.date
}, {
id: "val",
alias: "Value",
dataType: tableau.dataTypeEnum.float
}];
var tableSchema = {
id: "table",
alias: "187",
columns: cols
};
schemaCallback([tableSchema]);
};
// Download the data
myConnector.getData = function(table, doneCallback) {
$.getJSON("http://myapi.com/119%2C7777/Flattened?start=today&end=today&timeZone=CET&asOf=now&aggregation=None", function(resp) {
var feat = resp.features,
tableData = [];
tableData.push(
{"table":feat.properties.table}
);
// Iterate over the JSON object
//var SeriesId = feat.SeriesId
for(var i = 0; i <feat.DataPoints.length; i++){
var PrognosisTime = feat.DataPoints.PrognosisTime;
var Start = feat.DataPoints.Start;
var Value = feat.DataPoints.Value;
}
table.appendRows(tableData);
doneCallback();
});
};
tableau.registerConnector(myConnector);
// Create event listeners for when the user submits the form
$(document).ready(function() {
$("#submitButton").click(function() {
tableau.connectionName = "Neas"; // This will be the data source name in Tableau
tableau.submit(); // This sends the connector object to Tableau
});
});
})();
json from API
[
{
"SeriesId": 119,
"DataPoints": [
{
"PrognosisTime": null,
"Start": "2016-08-24T00:00:00",
"Value": 26.19
},
{
"PrognosisTime": null,
"Start": "2016-08-24T01:00:00",
"Value": 23.9
},
{
"PrognosisTime": null,
"Start": "2016-08-24T02:00:00",
"Value": 22.82
}
]
},
{
"SeriesId": 7777,
"DataPoints": [
{
"PrognosisTime": null,
"Start": "2016-08-24T00:00:00",
"Value": 36.39
},
{
"PrognosisTime": null,
"Start": "2016-08-24T00:15:00",
"Value": 28.81
},
{
"PrognosisTime": null,
"Start": "2016-08-24T00:30:00",
"Value": 24.28
}
]
}
]
The problem is this line:
var feat = resp.features
resp is an array from your JSON, there is nothing called features. So, simply iterate over resp (or feat = resp) and pull out your DataPoints array.

Javascript passing variables

Okay so, I'm trying to get the facebook name and email of a user (succeed in that), and then use mandrill to email me that info. But for some reason, can't seem to get the name and email address to pass into the params object. (I deleted a lot of the facebook login stuff to make it clearer) Help!!
$(function() {
function getCurrentUserInfo() {
FB.api('/me', function(userInfo) {
console.log(userInfo.name + ': ' + userInfo.email);
temp = userInfo.email;
name = userInfo.name;
var needed = {
"name": userInfo.name,
"email": userInfo.email
}
function log(obj) {
$('#response').text(JSON.stringify(obj));
}
var m = new mandrill.Mandrill('key');
// create a variable for the API call parameters
var params = {
"message": {
"from_email":"emailf",
"to":[{"email":"emailg"}],
"subject": "New email",
"html": "*|NAME|* has the email *|EMAIL|* ",
"autotext": "true",
"track_opens": "true",
"track_clicks": "true",
"merge_vars": [
{
"rcpt": "emailrep",
"vars": [
{
"name": "NAME",
"content": "needed["name"]"
},
{
"name": "EMAIL",
"content": "needed["email"]"
}
]
}
]
}
};
You're passing strings when you need the variable:
"vars": [
{
"name": "NAME",
"content":needed["name"]
},
{
"name": "EMAIL",
"content": needed["email"]
}
]

Getting an array of users that edited a page

I am working on a user script for a Wikia community ( http://c.wikia.com ) and I need to get array of users (and possibly revision IDs) of a page. I have come up with the following code but cannot seem to make it work. Any help would be appreciated.
Code:
var revisions = [];
$.getJSON('/api.php', {
action: 'query',
prop: 'revisions',
titles: mw.config.get("wgPageName"),
rvprop: 'user',
rvlimit: '50',
format: 'json'
}, function (result) {
for (var i = 0; i < 50; i++) {
var revision = result.query.pages.page[i].revisions.user;
revisions.push(revision);
}
alert(revisions);
});
The query result looks something like this:
{
"query": {
"pages": {
"421588": {
"pageid": 421588,
"ns": 0,
"title": "Community Central",
"revisions": [
{
"user": "Mhadick"
},
{
"user": "Nblonkenfeld"
},
…
]
}
}
},
…
}
You'll notice that pages is an object with property named after the page id of the current page "421588" (judging from your code, you might be looking at the XML version of the response, you have to look at the JSON). To work with that, you can use something like:
var users = [];
$.getJSON('/api.php', {
action: 'query',
prop: 'revisions',
titles: mw.config.get("wgPageName"),
rvprop: 'user',
rvlimit: '50',
format: 'json'
}, function (result) {
var revisions = result.query.pages[mw.config.get("wgArticleId")].revisions;
$.each(revisions, function(key, revision) {
users.push(revision.user);
});
alert(users);
});

Categories

Resources