Automate login + posting to forum using nodejs + phantomjs - node.js

I am trying to automate login to a forum ( yet another forum , test forum available here: http://testforum.yetanotherforum.net/ ) using node-phantom.
This is my code:
/**
* Yet Another Forum Object
*
*
*/
var yaf = function() {}; //
module.exports = new yaf();
var phantom = require('node-phantom');
//var sleep = require('sleep');
var configTestForum = {
loginUrl: "http://testforum.yetanotherforum.net/login",
loginFormDetail: {
usernameBox: 'forum_ctl03_Login1_UserName', // dom element ID
passwordBox: 'forum_ctl03_Login1_Password',
submitButton: 'forum_ctl03_Login1_LoginButton'
},
loginInfo: {
username: 'testbot',
password: 'testbot123'
}
};
var config = configTestForum;
// program logic
yaf.prototype.login = function(username, password, cb) {
var steps = [];
var testindex = 0;
var loadInProgress = false; //This is set to true when a page is still loading
/*********SETTINGS*********************/
phantom.create(function(error, ph) {
ph.createPage(function(err, page) {
page.set('settings', {
userAgent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0",
javascriptEnabled: true,
loadImages: false,
});
phantom.cookiesEnabled = true;
phantom.javascriptEnabled = true;
/*********SETTINGS END*****************/
console.log('All settings loaded, start with execution');
/**********DEFINE STEPS THAT FANTOM SHOULD DO***********************/
steps = [
//Step 1 - Open Amazon home page
function() {
console.log('Step 1 - Open Login Page');
page.open(config.loginUrl, function(status) {
});
},
function() {
console.log('Step 2 - Populate and submit the login form');
var submitForm = function(config) {
console.log('Form Submit 1 ( putting login )');
document.getElementById(config.loginFormDetail.usernameBox).value = config.loginInfo.username;
console.log('Form Submit 2 ( putting pass )');
//jQuery('#' + config.loginFormDetail.passwordBox).val(config.loginInfo.password);
//jQuery('#' + config.loginFormDetail.usernameBox).val(config.loginInfo.password);
document.getElementById(config.loginFormDetail.passwordBox).value = config.loginInfo.password;
console.log('Form Submit 3 ( clicking button ) ');
document.getElementById(config.loginFormDetail.submitButton).click();
//var clickElement = function (el) {
// var ev = document.createEvent("MouseEvent");
// ev.initMouseEvent(
// "click",
// true /* bubble */, true /* cancelable */,
// window, null,
// 0, 0, 0, 0, /* coordinates */
// false, false, false, false, /* modifier keys */
// 0 /*left*/, null
// );
// el.dispatchEvent(ev);
// console.log('dispatched!');
//};
//document.getElementById(config.loginFormDetail.submitButton).click();
//clickElement(jQuery("#forum_ctl03_Login1_LoginButton")[0]);
//
//var form = document.getElementById('form1');
////var list = function(object) {
//// for(var key in object) {
//// console.log(key);
//// }
////};
////list(form);
//
//
//// jQuery('#form1').submit();
//
//form.submit();
//
//document.forms[0].submit();
//HTMLFormElement.prototype.submit.call(jQuery('form')[0]);
console.log('Form Has Been Submitted <-----------------');
};
var subittedForm = function(err, retVal) {
console.log('Form Submit error : ' + err);
console.log('Form Submit returned : ' + retVal);
};
//page.evaluateJavaScript(jsCode);
page.evaluate(submitForm, subittedForm, config);
},
//Step 3 - wait for submit form to finish loading..
function() {
//sleep.sleep(5);
console.log("Step 3 - wait for submit form to finish loading..");
//sleep.sleep(3);
page.render('loginComplete.png');
page.get('cookies', function(err, cookies) {
// console.log(cookies);
});
page.evaluate(function() {
console.log(document.URL);
});
},
function() {
console.log('Exiting');
}
];
/**********END STEPS THAT FANTOM SHOULD DO***********************/
//Execute steps one by one
interval = setInterval(executeRequestsStepByStep, 500);
function executeRequestsStepByStep() {
if (loadInProgress == false && typeof steps[testindex] == "function") {
//console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
ph.exit();
// cb(ph);
cb('done');
}
}
page.onLoadStarted = function() {
loadInProgress = true;
console.log('Loading started');
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log('Loading finished');
};
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function+'")' : ''));
});
}
console.error('\n' + msgStack.join('\n'));
};
page.onResourceError = function(resourceError) {
console.error('Unable to load resource (#' + resourceError.id + ' URL:' + resourceError.url + ')');
console.error('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.onResourceTimeout = function(msg) {
console.error('onResourceTimeout!!>' + msg);
};
page.onAlert = function(msg) {
console.error('onAlert!!> ' + msg);
};
});
});
// var page = webPage.create();
};
Output of the code is :
Step 1 - Open Login Page
Loading started
Loading finished
Step 2 - Populate and submit the login form
Form Submit 1(putting login)
Form Submit 2(putting pass)
Form Submit 3(clicking button)
Form Has Been Submitted < -----------------
Form Submit error: null
Form Submit returned: null
Unable to load resource(#14 URL:http://testforum.yetanotherforum.net/login?g= login &= )
Error code: 5.Description: Operation canceled
ERROR: TypeError: 'undefined'
is not an object(evaluating 'Sys.WebForms.Res.PRM_TimeoutError'), [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object]
Step 3 - wait
for submit form to finish loading..
http: //testforum.yetanotherforum.net/login
Exiting
test complete!
done
Option client store expiration is not valid.Please refer to the README.
Process finished with exit code 0
What it attempts to do is :
Open login page : http://testforum.yetanotherforum.net/login?returnurl=%2fcategory%2f1-Test-Category
Try to login using login name / password and then clicking the button.
Take a screenshot and Retrieve the cookies ( containing the auth data )
Currently it is getting stuck in step 2. It can populate the login and password box, but no kind of clicking or submitting the form is working.Basically it is stuck as shown:
(as you can see the login / password are filled correctly ).
By looking at step 2 ( Step 2 - Populate and submit the login form ) in my code, do you notice anything obvious? or am I doing something wrong in the page settings?

Related

How to kill spawn program nodejs based on button in frontend

In the backend, I run a script when user clicks button however, I need the ability for frontend to be able to click button to stop the script. I am using eventSource on the frontend to stream the output of the script to the frontend. I have tried spawn.kill(), kill(), and everything. I can't seem to get it to stop the script. The script still continues even though i close the eventSource and call spw.kill() in the res.socket.on function. Any help will be appreciated!
Frontend code here
const fetchStream = (e) => {
e.preventDefault();
var evtSource = new EventSource(
`http://${process.env.REACT_APP_IP_ADDRESS}/run`
);
evtSource.onmessage = function (e) {
var d = Date.now();
var formatteddatestr = String(moment(d).format("M/D/YYYY-hh:mm:ss a"));
setData((data) => [...data, formatteddatestr + ": " + e.data]);
if (stopTest) {
// I have a button that turns this to true when user clicks it.
evtSource.close();
setStopTest(false);
setData((data) => []);
setRunning(false);
}
if (e.data.includes("Test done.")) {
evtSource.close();
createPDF(e);
}
};
evtSource.onerror = function (e) {
evtSource.close();
setRunning(false);
};
This is backend code
router.get("/", function (req, res) {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-control": "no-cache",
// Connection: "keep-alive",
});
// res.write("\n");
var d = new Date(Date.now());
var formatteddatestr = String(moment(d).format("M/D/YYYY-hh:mm:ss a"));
fs.writeFileSync(__dirname + "/start.txt", formatteddatestr);
var spw = spawn("./Validator", ["-d", "tests"], {
cwd: __dirname + "/../../../Validator",
detached: true,
}),
str = "";
var kill = false;
res.socket.on("end", (e) => {
// doesn't work here
// code gets here when user clicks button to stop script
spw.kill();
res.end();
});
spw.stdout.on("data", function (data) {
res.write("data: " + data + "\n\n");
});
spw.stderr.on("data", function (data) {
//works here
spw.kill();
});
});

Lambda function taking >3 seconds to run + 5-10 secs warmup each time

I have a simple node.js function with 2 REST API calls and a socket connection output hosted in an AWS lambda. It takes 5-10 secs warmup time and >3+ secs execution time.
When the code is run locally it executes both requests, socket connection and completes in about ~1300ms. Why is AWS more then double the execution time? I have set-timeout to 120seconds and memory at 128mb (default).
I appreciate the code is not very tidy; I am working on cleaning it but needed something going for the time being.
The project simply gets info from ServiceM8 via API when called by a webhook subscription, then formats the info into ZPL strings and forwards them to a tcp server for printing via thermal printer.
My questions are:
Is it my code bottle necking?
Can it be optimized to run faster?
Do i simply need to employ a warming plugin for my function to allow hot starting?
My function:
'use strict';
//Require libraries
var request = require("request");
var net = require('net');
exports.handler = (event, context, callback) => {
if (event.eventName != 'webhook_subscription') {
callback(null, {});
}
//Global Variables
var strAssetUUID;
var strAssetURL;
var strFormUUID;
var strTestDate;
var strRetestDate;
var appliancePass = true;
var strAccessToken;
var strResponseUUID;
//Printer Access
const tcpUrl = 'example.com';
const tcpPort = 12345;
var client = new net.Socket();
//UUID of Appliance Test Form.
const strTestFormUUID = 'UUID_of_form';
//Begin function
/**
* Inspect the `eventArgs.entry` argument to get details of the change that caused the webhook
* to fire.
*/
strResponseUUID = event.eventArgs.entry[0].uuid;
strAccessToken = event.auth.accessToken;
console.log('Response UUID: ' + strResponseUUID);
console.log('Access Token: ' + strAccessToken);
//URL Options for FormResponse UUID query
const urlFormResponse = {
url: 'https://api.servicem8.com/api_1.0/formresponse.json?%24filter=uuid%20eq%20' + strResponseUUID,
headers: {
// Use the temporary Access Token that was issued for this event
'Authorization': 'Bearer ' + strAccessToken
}
};
//Query form Response UUID to get information required.
request.get(urlFormResponse, function(err, res, body) {
//Check response code from API query
if (res.statusCode != 200) {
// Unable to query form response records
callback(null, {err: "Unable to query form response records, received HTTP " + res.statusCode + "\n\n" + body});
return;
}
//If we do recieve a 200 status code, begin
var arrRecords = JSON.parse(body);
//Store the UUID of the form used for the form response.
strFormUUID = arrRecords[0].form_uuid;
console.log('Form UUID: ' + strFormUUID);
//Store the UUID of the asset the form response relates to.
strAssetUUID = arrRecords[0].asset_uuid;
console.log('Asset UUID: ' + strAssetUUID);
if (strFormUUID == strTestFormUUID){
//Get the edited date and parse it into a JSON date object.
var strEditDate = new Date(arrRecords[0].edit_date);
//Reassemble JSON date to dd-mm-yyyy.
strTestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
//Extract the response for retest period.
var strRetestAnswer = JSON.parse(arrRecords[0].field_data);
strRetestAnswer = strRetestAnswer[0].Response;
//Appropriate function based on retest response.
switch(strRetestAnswer) {
case '3 Months':
//Add x months to current test date object
strEditDate.setMonth(strEditDate.getMonth() + 3);
strRetestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
break;
case '6 Months':
strEditDate.setMonth(strEditDate.getMonth() + 6);
strRetestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
break;
case '12 Months':
strEditDate.setMonth(strEditDate.getMonth() + 12);
strRetestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
break;
case '2 Years':
strEditDate.setMonth(strEditDate.getMonth() + 24);
strRetestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
break;
case '5 Years':
strEditDate.setMonth(strEditDate.getMonth() + 60);
strRetestDate = strEditDate.getDate() + '/' + (strEditDate.getMonth() + 1) + '/' + strEditDate.getFullYear();
break;
default:
strRetestDate = "FAIL";
appliancePass = false;
}
console.log('Appliance Pass: ' + appliancePass);
console.log('Test Date: ' + strTestDate);
console.log('Retest Period: ' + strRetestAnswer);
console.log('Retest Date: ' + strRetestDate);
//URL Options for Asset UUID query
const urlAssetResponse = {
url: 'https://api.servicem8.com/api_1.0/asset/' + strAssetUUID + '.json',
headers: {
// Use the temporary Access Token that was issued for this event
'Authorization': 'Bearer ' + strAccessToken
}
};
//Query the api for the asset URL of the provided asset UUID.
request.get(urlAssetResponse, function(err, res, body) {
//Check response code from API query
if (res.statusCode != 200) {
// Unable to query asset records
callback(null, {err: "Unable to query asset records, received HTTP " + res.statusCode + "\n\n" + body});
return;
}
//If we do recieve a 200 status code, begin
var strAssetResponse = JSON.parse(body);
//Store the asset URL
strAssetURL = 'https://sm8.io/' + strAssetResponse.asset_code;
console.log('Asset URL: ' + strAssetURL);
//generate tag and send to printer
var strZPLPass = ('^XA....^XZ\n');
var strZPLFail = ('^XA....^XZ\n');
//Now that we have our ZPL generated from our dates and URLs
//Send the correct ZPL to the printer.
client.connect(tcpPort, tcpUrl, function() {
console.log('Connected');
//Send Appropriate ZPL
if (appliancePass) {
client.write(strZPLPass);
}else {
client.write(strZPLFail);
}
console.log('Tag Successfully Printed!');
//As the tcp server receiving the string does not return any communication
//there is no way to know when the data has been succesfully received in full.
//So we simply timeout the connection after 750ms which is generally long enough
//to ensure complete transmission.
setTimeout(function () {
console.log('Timeout, connection closing...');
client.destroy();
}, 750);
});
});
}
});
};
First of all, I would suggest you stop using the request module and switch to native. Everything can be done without a tons of lines these days. request is a module with 48 total dependencies; if you do the math, that's thousands of lines for a simple GET request.
You should always minimize the complexity of your dependencies. I use a Lambda to check the health of my sites, grabbing the whole request and checking the HTML on completely different servers. VPS is located in Frankfurt, AWS in Ireland. My ms/request is ranging between 100~150 ms.
Here's a simple promise request I'm using:
function request(obj, timeout) {
return new Promise(function(res, rej) {
if (typeof obj !== "object") {
rej("Argument must be a valid http request options object")
}
obj.timeout = timeout;
obj.rejectUnauthorized = false;
let request = http.get(obj, (response) => {
if (response.statusCode !== 200) {
rej("Connection error");
}
var body = '';
response.on('data', (chunk) => {
body += chunk;
});
response.on('end', () => {
res(body);
});
response.on('error', (error) => {
rej(error);
});
});
request.setTimeout(timeout);
request.on('error', (error) => {
rej(error);
})
request.on('timeout', () => {
request.abort();
rej("Timeout!")
})
});
}
Example
const reqOpts = {
hostname: 'www.example.com',
port: 443,
path: '/hello',
method: 'GET',
headers: {
handshake: "eXTNxFMxQL4pRrj6JfzQycn3obHL",
remoteIpAddress: event.sourceIp || "lambda"
}
}
try {
httpTestCall = await request(reqOpts, 250);
}
catch (e) {
console.error(e);
}
Now based on that change switch your handler to async using exports.handler = async(event, context, callback) => {} and use console to measure the execution time of every request using console.time() and console.timeEnd() for your request or anything. From there you could see what's stepping down your code using Cloudwatch logs. Here's another example based on your code:
let reqOpts = {
hostname: 'api.servicem8.com',
port: 443,
path: '/api_1.0/formresponse.json?%24filter=uuid%20eq%20' + strResponseUUID,
method: 'GET',
headers: {
// Use the temporary Access Token that was issued for this event
'Authorization': 'Bearer ' + strAccessToken
}
}
console.time("=========MEASURE_servicem8=========")
let error = null;
await request(reqOpts, 5555).catch((e)=>{
error = e;
})
console.timerEnd("=========MEASURE_servicem8=========")
if (error){
callback(null, {err: "Unable to query form response records, received HTTP" + error}); /* or anything similar */
}
References
https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
aws lambdas are not fast by nature (as of writing this answer). The startup time is not guaranteed, and it is known to be high.
If you need performance - you will not get it this way.

Making jquery ajax call in child process - node.js

I am using 'child_process'(fork method) to handle task of saving some records across server. For this I was using jquery ajax call in the child process to save the records. But somehow that code doesn't get executed.
I have already included the jquery.min.js file in the html in which I am including the file forking child process as well.
The file forking child process:
var childProcess = require('child_process');
var syncProcess;
function launchMindwaveDataSync(){
//alert("launchMindwaveDataSync fired");
var iconSync = document.getElementById("iconSync");
iconSync.src = "images/findDevice.gif";
iconDevice.title = "Synchronizing...";
//Launch the device reader script in a new V8 process.
syncProcess = childProcess.fork('./js/mindwaveDataSync.js');
syncProcess.on('message', function(message){
console.log(message);
switch(message.msg)
{
case "connected":
global.HEADSET_CONNECTED = true;
iconDevice.src = "images/icon-power.png";
iconDevice.title = "Connected to Mindwave Mobile device";
startSynchronizing();
break;
case "disconnected":
case "error":
case "close":
case "timeout":
global.HEADSET_CONNECTED = false;
iconDevice.src = "images/error.png";
iconDevice.title = "Mindwave Mobile device is disconnected";
break;
}
});
syncProcess.on('error', function(e){
console.log(e);
});
setTimeout(function(){
console.log('sending command initialize');
syncProcess.send({cmd:'initialize'});
},1000);
};
function startSynchronizing(){
syncProcess.send({cmd: 'synchronize'});
}
The child process which is supposed to make ajax call
var recursive = require('recursive-readdir');
var SecurConf = require('../js/secureConf');
var sconf = new SecurConf();
var filesToSync = [];
var crypto = require('crypto');
var options = {
//prompt : 'File Password : ',
algo : 'aes-128-ecb',
file : {
encoding : 'utf8',
out_text : 'hex'
}
};
process.on('message', function (command){
console.log(command);
switch(command.cmd)
{
case "initialize": initializeConnection();
break;
case "synchronize": checkForFiles();
break;
case "record":
client.resume();
break;
case "pause":
client.pause();
break;
case "stop":
client.destroy();
break;
}
//process.send({msg:"Sync Process: " + command.cmd});
});
function checkForFiles(){
recursive('C:/MindWaveData/Data/', function (err, files) {
// Files is an array of filename
filesToSync = files;
decryptFiles();
//process.send({msg:files});
});
}
function decryptFiles(){
var ajaxSuccess = function(res){
process.send({msg:res});
}
for(var i = 0; i < filesToSync.length; i++){
var ef = ""+filesToSync[i];
sconf.decryptFile(ef, function(err, file, content){
if(err){
process.send({msg:"some error occurred while decrypting..."});
} else {
var parsedContent = JSON.parse(content);
var decryptedContent = JSON.stringify(parsedContent, null,'\t');
for(var j = 0; j<parsedContent.length; j++){
$.ajax({
//async: false,
type: "POST",
url: "http://192.168.14.27:8001/admin/webservice",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
'ncFunction': 'login',
'ncParams': {
'ncUserEmail': "clarity_admin#yopmail.com",
'ncUserPassword': "cl123!##"
}
}),
success: function (res) {
ajaxSuccess(res);
},
error: function (xhr, type, err) {
ajaxSuccess(res);
}
});
}
});
}
}
function initializeConnection(){
//console.log('initializeConnection::function');
//process.send({msg:"initializeConnection called"});
checkConnection()
//process.send({msg:"connected"});
//call function to send ajax request
}
function checkConnection(){
//console.log('checkConnection::function');
//call ajax request 3 times to check the connection.. once in third try we get the response OK, we can send the process message as connected
var ajaxCallCount = 0;
var makeAjaxCall = function(){
//console.log('function makeAjaxCall');
//process.send({msg:"connected"});
if(ajaxCallCount < 2){
ajaxCallCount++;
//console.log('ajaxCallCount:'+ajaxCallCount);
//process.send({msg:'value of ajaxCallCount:'+ajaxCallCount});
connectionSuccess();
}
else{
process.send({msg:"connected"});
}
};
var connectionSuccess = function(){
//console.log('function connectionSuccess');
makeAjaxCall();
};
makeAjaxCall();
}
Can we use jquery ajax call in the child process like this? Plus I have included the file forking child process in one html file and on load of its body I am calling /launchMindwaveDataSync/ from the first file shown below.
Thanks in advance

How to promisfy MongoDB/Mongoose .findOne before .push, in an array.forEach?

Have looked through the bluebird readMe examples, and am still wondering how to implement/convert some async code to involve promises with .then..
There are a number of ifStatements in here, though the main point is that while looping through the toArray, if the element exists in the database (findOne) then assign it to a variable to .push it to a field in an embedded doc of the new (.post & .save) db doc.
Here's the current async code that consequently runs the findOne after .save .. but it needs to run before:
// create a story (accessed at POST http://localhost:4200/api/v1/story)
.post(function(req, res) {
console.log('posting a new Story..from: ' + res.locals._id + '..' + res.locals.username );
var story = new Models.Story();
var toArray = req.body.to;
console.log(toArray); // [ 'user1', 'user2', 'user3' ]
toArray.forEach(toArrayLoop);
function toArrayLoop(element, index, array){
console.log('element: ' + element); // 'user1' .. 'user2' .. 'user3'
var out = false; // if sent to Self, out = true
if (element == res.locals.username) {out = true; console.log('to element: ' + element + ' == res.locals.username: ' + res.locals.username)}
var toUserId = '';
if (element) {
Models.User.findOne({username: element}, function (err, user) {
if (user) {
if (err) {
console.log(err);
res.send(err);
}
console.log('user._id = ' + user._id);
toUserId = user._id;
} else {
toUserId = '';
console.log('toUserId = ' + toUserId);
}
});
}
story.to.push({
user : toUserId, // push the findOne user._id
username : element, // push the toArray element
view :
{
inbox: true,
outbox: out,
archive: false,
},
updated : req.body.nowDatetime
});
}
var archive = false;
console.log('req.body.archive = ' + req.body.archive);
if (req.body.archive == 'true') { archive = true; console.log('archive = ' + archive); };
var in = false;
toArray.forEach(fromSelfLoop);
function fromSelfLoop(element, index, array){
console.log('checking if sent to Self: ' + element); // 'user1' .. if matches res.locals: (sent from/to Self)
if (element == res.locals.username) {in = true; console.log('from element: ' + element + ' == res.locals.username: ' + res.locals.username)}
} // if sent to Self, archive = true
story.from.push({
user : res.locals._id,
username : res.locals.username,
view :
{
inbox: in,
outbox: true,
archive: archive,
},
updated : req.body.nowDatetime
});
story.title = req.body.title;
// ..even more doc val assignments..
console.log('To: ' + req.body.to);
console.log('Story: ' + req.body.title);
story.save(function(err, result) {
if (err) {
console.log(err);
res.send(err);
}
console.log("The result: ", result);
res.json({ message: 'Story "' + story.title + '" Created' });
});
console.log('post success!');
})
You're way overkilling it in my opinion, Promises provide ways to synchronize this out of the box seamlessly.
You can use promise aggregation methods (in this case .join and .props) to map directly to the properties and get the values.
Assuming you promisified Mongoose (so Bluebird promises rather than Mongoose ones).
var story = new Models.Story();
var toArray = req.body.to; // [ 'user1', 'user2', 'user3' ]
var to = Promise.map(toArray,function(element){
return Promise.props({ // resolves all properties
user : Models.User.findOneAsync({username: element}),
username : element, // push the toArray element
view : {
inbox: true,
outbox: element == res.locals.user.username,
archive: false
},
updated : req.body.nowDatetime
});
});
var from = Promise.map(toArray,function(element){ // can be a normal map
return Promise.props({
user : res.locals._id,
username : res.locals.username,
view : {
inbox: element == res.locals.user.username,
outbox: true,
archive: archive,
},
updated : req.body.nowDatetime
});
});
Promise.join(to, from, function(to, from){
story.to = to;
story.from = from;
story.title = req.body.title;
return story.save();
}).then(function(){
console.log("Success! Story saved!");
}).catch(Promise.OperationalError, function(e){
// handle error in Mongoose save findOne etc, res.send(...)
}).catch(function(e){
// handle other exceptions here, this is most likely
// a 500 error where the top one is a 4XX, but pay close
// attention to how you handle errors here
});

Instagram real time tag subscription only work for a minute - node.js

I am trying to get the real time tag subscription to work but it seems like the real time update only update within a minute. Here are my code, can you please point out what I am missing?
var Instagram = require('instagram-node-lib');
app.get('/GetInstagram', function(request, response){
// The GET callback for each subscription verification.
var params = url.parse(request.url, true).query;
response.send(params['hub.challenge'] || 'No hub.challenge present');
});
app.post('/GetInstagram', function (req, res) {
var tagName = 'love';
Instagram.set('client_id', 'clientID');
Instagram.set('client_secret', 'ClientSecret');
Instagram.tags.subscribe ({ object_id: tagName,access_token: null, client_id: 'clientid', client_secret: 'clientsecret', callback_url: 'http://myURL/GetInstagram', complete: function()
{
console.log('begin fetching');
Instagram.tags.recent({ name: tagName,aspect: 'media', complete: function(data, pagination )
{
var chunk = { 'pagination': pagination, 'data': data };
console.log (chunk.data.length);
var len = 0;
for (var i = 0, len = chunk.data.length; i < len; i++)
{
var url = '"' + chunk.data[i].images.standard_resolution.url + '"';
console.log('image from instagram image # ' + i + ' image URL' + chunk.data[i].images.standard_resolution.url );
}
res.end();
}
});
}
});
});
pretty sure you're not using the right method -- you want to use Instagram.subscriptions.subscribe for a real-time feed, not tags.subscribe

Resources