socket.io error when connecting from iframe - javascript

So I have a couple applications on different servers all from inside of our network and I am using node.js and socket.io js to handle real time communication between them which when each is run separately works fine, but when I put application 2 inside an iframe on application 1 I get the following error
"Blocked a frame with origin "http : // 192.128.1.97" from accessing a frame with origin "http : // intranet". Protocols, domains, and ports must match. "
*note I added spaces in the urls above because the page was telling me links weren't allowed.
is there some way to allow the iframe to connect to socket.io? the code is pretty simple, but here is the server code...
/**
* Server js file for node
* this will handle all of the incoming requests from all the apps
* and push them to the clients
*/
var express = require("express"),
app = express(),
http = require("http").createServer(app),
io = require("socket.io").listen(http);
_ = require("underscore");
var participants = [];
// setup the environment and tell node and express what it needs
app.set("ipaddr", "192.168.1.76");
app.set("port", 8080);
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
//further environment setup telling node and express what to use to handle requests
app.use(express.static("public", __dirname));
app.use(express.bodyParser());
//setup the default page
app.get("/", function(request, response) {
//render the view page
//response.render("node_home");
//just post a message to the screen
response.send("Server is up and running");
//respond with a json object
// reponse.json(200, {message: "Server is up and running"});
});
//setup a handler for requests to /message
app.post("/message", function(request, response) {
var message = request.body.message;
if(_.isUndefined(message) || _.isEmpty(message.trin())) {
return response.json(400, {error: "Message is invalid"});
}
var name = request.body.name;
io.sockets.emit("incomingMessage", {message: message, name: name});
response.json(200, {message: "Message received"});
})
io.on("connection", function(socket) {
socket.on("newUser", function(data) {
participants.push({id: data.id, name: data.name});
io.sockets.emit("newConnection", {participants: participants, badgeNumber: data.badgeNumber, id: data.id})
});
socket.on("nameChange", function(data) {
_findWhere(paticipants, {id: socket.id}).name = data.name;
io.sockets.emit("nameChanged", {id: data.id, name: data.name})
});
socket.on("disconnect", function() {
participants = _.without(participants, _.findWhere(participants, {id: socket.id}));
io.sockets.emit("userDisconnected", {id: socket.id, sender: "system"})
});
socket.on("phraseCheck", function(data) {
io.sockets.emit("checkPhrase", {id: data.id, phrase: data.phrase});
});
socket.on('newFluxClient', function(data) {
console.log(data);
io.sockets.emit('fluxConnection', {badgeNumber: data.badgeNumber, id: data.id});
});
socket.on('phraseAllowed', function(data) {
io.sockets.emit('allowedPhrase', {id: data.id, allowed: data.allowed});
});
socket.on('customFunction', function(data) {
console.log(data);
io.sockets.emit('customFunction', data);
});
});
//start the app and have it listen for incoming requests
http.listen(app.get("port"), app.get("ipaddr"), function() {
console.log("Server up and running. Go to http://" + app.get("ipaddr") + ":" + app.get("port"))
});
application 1 code....
/**
* client js file
* this will handle connecting to node and handle the incoming messages
* as well as sending responses and messages to the server
*/
var childSessionId = '',
sessionId = '',
socket = '',
serverBaseUrl = '',
participants = [];
function init() {
serverBaseUrl = 'http://192.168.1.76:8080';
socket = io.connect(serverBaseUrl);
sessionId = '';
function updateParticipants(part) {
participants = part;
$("#participants").html('');
for(var i=0; i<participants.length;i++) {
$("#participants").append('<span id="' + participants[i].id + '">' + participants[i].name + ' ' + (participants[i].id === sessionId ? '(You)' : '') + '<br /></span>');
}
}
socket.on('connect', function() {
sessionId = socket.socket.sessionid;
console.log('Connected ' + sessionId);
socket.emit("newUser", {id: sessionId, name: page.user});
});
socket.on('userDisconnect', function(data) {
$('#' + data.id).remove();
});
socket.on('nameChanged', function(data) {
$('#' + data.id).html(data.name + ' ' + (data.id === sessionId ? '(You)' : '') + '<br />');
});
socket.on('newConnection', function(data) {
if(data.badgeNumber === page.userBadgeNumber) {
childSessionId = data.id;
}
updateParticipants(data.participants);
});
socket.on('fluxConnection', function(data) {
console.log('flux connection data:');
console.log(data);
if(data.badgeNumber === "**********") {
childSessionId = data.id;
}
});
socket.on('incomingMessage', function(data) {
$("#messages").prepend('<b>' + data.name + '</b><br />' + data.message + '<hr />');
});
socket.on('error', function(reason) {
console.log('Unable to connect to server', reason);
});
socket.on('customFunction', function(data) {
console.log(data);
data.data();
});
socket.on('checkPhrase', function(data) {
if(data.id === childSessionId) {
var phrases = shoppingcart.getPhrasesInCart();
var allowed = ($.inArray(data.phrase, phrases) >= 0);
socket.emit('phraseAllowed', {id: data.id, allowed: allowed});
}
});
}
$(document).ready(function() {
init();
})
and application 2 code....
// NODE JS INITIALIZATION
var socket = null;
var sessionId = '';
function initialize_node(){
var serverBaseUrl = 'http://192.168.1.76:8080';
socket = io.connect(serverBaseUrl);
sessionId = '';
socket.on('connect', function() {
sessionId = socket.socket.sessionId;
socket.emit('newFluxClient', {id: sessionId, badgeNumber: "PDX000022", name: "matthew.hicks"});
// socket.emit('newUser', {id: sessionId, badgeNumber: user.badge, name: user.name});
})
socket.on('allowedPhrase', function(data) {
if(sessionId === data.id) {
alert("I'm a preddy little princess. Console logging data returned");
console.log(data);
/*
functions to allow or disallow the phrase
based on data.allowed
it will be true if the phrase is in the shopping cart
and false if it is not
*/
}
});
// $('#phrase').blur(function() {
// checkPhrase();
// })
};
function checkPhrase() {
//var phrase = $('#phrase').val();
var phrase = "Shindigs in Ptown";
socket.emit('phraseCheck', {id: sessionId, phrase: phrase});
}
$(document).ready(function () {
initialize_node();
});
Sorry for the mass amount of code but trying to give all the conte4xt necessary. Essentially server is up and running, application 1 connects and gets a unique session id, then when application 2 tries to connect from the iframe I get the above mentioned error, when application 2 is not in an iframe it connects just fine and gets a session id. Please help if you can, I can't figure out why it is getting blocked and I really need this up and running. Thank you in advance for any help

You have encountered Same Origin Policy.
The simplest solution is to run the iframe from the same server.
Since you have access to I.T time read up on CORS
You will basically have to configure the server to allow XSS from your domain.
You can also try something like:
document.domain = "intranet"
Read up on it here

Related

How to get the socket id of a disconnected client on the disconnect event in socket.io

I have started working on a web application for othello.... in it I used node.js and socket.io for handling the server side code. It runs a server.js file in the cloud.
This file handles some of the main client events, one of them is the disconnect event.
Here's the code for disconnect event:
io.sockets.on('connection', function(socket) {
log('Client connection by '+socket.id);
function log(){
var array = ['*** Server log Message'];
for(var i=0; i< arguments.length; i++) {
array.push(arguments[i]);
console.log(arguments[i]);
}
socket.emit('log', array);
socket.broadcast.emit('log', array);
}
/* disconnect command */
socket.on('disconnect', function(socket) {
log(socket);
log('Client disconnected '+ JSON.stringify(players[socket.id]));
if('undefined' !== typeof players[socket.id] && players[socket.id]) {
var username = players[socket.id].username;
var room = players[socket.id].room;
var payload = {
username: username,
socket_id: socket.id
};
delete players[socket.id];
io.in(room).emit('player_disconnected', payload);
}
});
});
This disconnect command should notify all the other cleints about the disconnected player and delete the data about it.
Here's the code for holding the temporary data of the active players:
/* join_room command */
socket.on('join_room', function(payload) {
log('\'join_room\' command '+ JSON.stringify(payload));
if(('undefined' === typeof payload) || !payload) {
var error_message = 'join_room had no payload, command aborted';
log(error_message);
socket.emit('join_room_response', {
result: 'fail',
message: error_message
});
return;
}
var room = payload.room;
if(('undefined' === typeof room) || !room) {
var error_message = 'join_room didn\'t specify a room, command aborted';
log(error_message);
socket.emit('join_room_response', {
result: 'fail',
message: error_message
});
return;
}
var username = payload.username;
if(('undefined' === typeof username) || !username) {
var error_message = 'join_room didn\'t specify a username, command aborted';
log(error_message);
socket.emit('join_room_response', {
result: 'fail',
message: error_message
});
return;
}
/* store information about new player */
players[socket.id] = {};
players[socket.id].username = username;
players[socket.id].room = room;
log(players);
socket.join(room);
var roomObject = io.sockets.adapter.rooms[room];
/* notify others about new player */
var sumCleints = roomObject.length;
var data = {
result: 'success',
room: room,
username: username,
socket_id: socket.id,
membership: sumCleints
};
io.in(room).emit('join_room_response', data);
for(var socket_in_room in roomObject.sockets) {
var data = {
result: 'success',
room: room,
username: players[socket_in_room].username,
socket_id: socket_in_room,
membership: sumCleints
};
socket.emit('join_room_response', data);
}
log('join_room success');
log('Room: '+ room + ' was just joined by '+ username)
});
But the issue is it doesn't. When I logged the socket.id, it returns undefined, I don't know why ... when I log the socket itself, it says: transport closed.
My question is how to get the socket id of a player who just disconnected.
Here's the client side code for handling the player_disconnected event:
/* when someone leaves a room */
socket.on('player_disconnected', function(payload) {
if (payload.result == 'fail') {
alert(payload.message);
return;
}
if(payload.socket_id == socket_id) {
return;
}
/* Delete all rows for new players that leave */
var dom_elements = $('.socket_'+payload.socket_id);
if(dom_elements.length != 0) {
dom_elements.slideUp(1000);
}
var newHTML = '<p>'+payload.username+' has left the lobby</p>';
var newNode = $(newHTML);
newNode.hide();
$('#messages').append(newNode);
newNode.slideDown(1000);
});
If someone could figure out the problem than please tell me, and please tell me how the disconnect event, and the other events actually work and what are the parameters for them, because I couldn't find any useful information in the docs... Thanks in advance.
On disconnect, you are overriding the socket variable with a different callback parameter. Try this:
/* disconnect command */
socket.on('disconnect', function() {
console.log(socket.id);
});

Add video to Youtube playlist NodeJS

I am currently working through the code to programmatically create a youtube playlist using a nodejs server that I received from a previous question I had and am using the working code below to do so:
var google = require('googleapis');
var Lien = require("lien");
var OAuth2 = google.auth.OAuth2;
var server = new Lien({
host: "localhost"
, port: 5000
});
var oauth2Client = new OAuth2(
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET',
'http://localhost:5000/oauthcallback'
);
var scopes = [
'https://www.googleapis.com/auth/youtube'
];
var youtube = google.youtube({
version: 'v3',
auth: oauth2Client
});
server.addPage("/", lien => {
var url = oauth2Client.generateAuthUrl({
access_type: "offline",
scope: scopes
});
lien.end("<a href='"+url+"'>Authenticate yourself</a>");
})
server.addPage("/oauthcallback", lien => {
console.log("Code obtained: " + lien.query.code);
oauth2Client.getToken(lien.query.code, (err, tokens) => {
if(err){
return console.log(err);
}
oauth2Client.setCredentials(tokens);
youtube.playlists.insert({
part: 'id,snippet',
resource: {
snippet: {
title:"Test",
description:"Description",
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
lien.end(data);
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
});
});
I am now moving on to the part of my project where I am in need of a way to add videos to this playlist once I have created it. The sample code that I am following along with is only written in JS and does not detail nodejs and I am therefore stuck on how to achieve this implementation with nodejs. How could I create a method like this (received from the JS implementation from the link above):
function addToPlaylist(id, startPos, endPos) {
var details = {
videoId: id,
kind: 'youtube#video'
}
if (startPos != undefined) {
details['startAt'] = startPos;
}
if (endPos != undefined) {
details['endAt'] = endPos;
}
var request = gapi.client.youtube.playlistItems.insert({
part: 'snippet',
resource: {
snippet: {
playlistId: playlistId,
resourceId: details
}
}
});
request.execute(function(response) {
$('#status').html('<pre>' + JSON.stringify(response.result) + '</pre>');
});
}
in the NodeJS language using the implementation I have already started?
I get what you mean now.If you want to add a video on your playlist then you can do that in Node using this.
youtube.playlistItems.insert({
part: 'id,snippet',
resource: {
snippet: {
playlistId:"YOUR_PLAYLIST_ID",
resourceId:{
videoId:"THE_VIDEO_ID_THAT_YOU_WANT_TO_ADD",
kind:"youtube#video"
}
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
lien.end(data);
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
If you want to render the result as HTML, First you need to use a view engine like (jade or pug) then create a template then lastly render it along with the response.
Base on your example you can do it this way:
First Create a template( Im using Pug) Save it as results.pug
html
head
title= title
body
h1= title
p=description
img(src=thumbnails.medium.url)
Then update your code below:
var google = require('googleapis');
var Lien = require("lien");
var OAuth2 = google.auth.OAuth2;
var pug = require('pug')
var server = new Lien({
host: "localhost"
, port: 5000,
views:{
path:__dirname,
name:'pug'
}
});
var oauth2Client = new OAuth2(
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET',
'http://localhost:5000/oauthcallback'
);
var scopes = [
'https://www.googleapis.com/auth/youtube'
];
var youtube = google.youtube({
version: 'v3',
auth: oauth2Client
});
server.addPage("/", lien => {
var url = oauth2Client.generateAuthUrl({
access_type: "offline",
scope: scopes
});
lien.end("<a href='"+url+"'>Authenticate yourself</a>");
})
server.addPage("/oauthcallback", lien => {
console.log("Code obtained: " + lien.query.code);
oauth2Client.getToken(lien.query.code, (err, tokens) => {
if(err){
return console.log(err);
}
oauth2Client.setCredentials(tokens);
youtube.playlists.insert({
part: 'id,snippet',
resource: {
snippet: {
title:"Test",
description:"Description",
}
}
}, function (err, data, response) {
if (err) {
lien.end('Error: ' + err);
}
else if (data) {
//lien.end(data);
lien.render('results',data.snippet)
}
if (response) {
console.log('Status code: ' + response.statusCode);
}
});
});
});
The things that I update on your code are:
var server = new Lien({
host: "localhost"
, port: 5000,
views:{
path:__dirname,
name:'pug'
}
});
And
//lien.end(data);
lien.render('results',data.snippet)

Post - Cannot GET error - Local server

I am trying to create an API using a local server for testing. The route
'GET' works fine, however 'POST' has a problem and it is returning 'Cannot GET /add/name'. I am developing the API using node.js and Express. Why am I receiving get when the route is set to 'POST'? Where is the problem?
var fs = require('fs');
var data = fs.readFileSync('events.json');
var allEvents = JSON.parse(data);
console.log(allEvents);
console.log('Server running.');
var express = require('express');
var app = express();
var sever = app.listen(3000, listening);
function listening() {
console.log('Serving...');
}
app.use(express.static('website'));
//GET and send all data from JSON
app.get('/all', sendAll);
function sendAll(request, response) {
response.send(allEvents);
}
//POST new data to JSON
app.post('/add/:name', addData);
function addData(request, response) {
var newData = request.params;
var name = newData.name;
var eventType = newData.eventType;
var reply;
// var newEvent = {
// name: ":name",
// eventType: ":eventType",
// };
var newData = JSON.stringify(allEvents, null, 2);
fs.writeFile('events.json', newData, finished);
function finished(err) {
console.log('Writting');
console.log(err);
var reply = {
word: word,
score: score,
status: 'Success'
}
response.send(reply);
}
}
Request
$(function() {
//HTML
var $list = $('#list');
var jsonURL = '../events.json'
$.ajax({
type: 'GET',
url: '/all',
success: function(data) {
console.log('Data received', data);
$.each(data, function (type, string) {
$list.append('<li>' + type + " : " + string + '</li>');
});
},
error: function (err) {
console.log('Error, data not sent.', err);
}
});
$('#submit').on('click', function () {
// var newEvent = {
// name: $name.val(),
// eventType: $eventType.val(),
// };
var name = $('#fieldName').val();
var eventType = $('#fieldEventType').val();
console.log(name);
$.ajax({
type: 'PUT',
url: '/add/' + name,
success: function (addData) {
$list.append('<li>name: ' + name + '</li>');
},
error: function (err) {
console.log('Error saving order', err);
}
});
});
});
Thank you in advance.
For testing POST request, you can use Postman to test it. If you use the browser to call the api, it will be GET method instead of POST.

Redirecting after all functions finished

I am using the Parse hosting and Cloud Code functions.
I have a button that runs a function and then redirects to the same page to refresh it after the function has been called. The cloud function that is being called by the button then calls a number of different functions from there, including a httpRequest. From what I can see, the page is refreshing after the first function has been called, not the subsequent functions and httpRequests being called later. The data on the loaded page is still displaying old data, and has to be refreshed manually to see the updated data.
Here is the code the button is triggering:
// User Control Panel -- Logic
app.post('/panel', function(req, res) {
var currentUser = Parse.User.current();
if (currentUser) {
currentUser.fetch().then(function(fetchedUser){
var username = fetchedUser.getUsername();
if (fetchedUser.get("timeRemaining") < 10) {
res.redirect("/panel");
} else if (fetchedUser.get("isRunning") == false){
Parse.Cloud.run("dockerManager", {username: username}) // Ignoring the rest of the code, this is where the cloud function is called.
res.redirect("/panel");
} else {
res.redirect("/panel");
}
}, function(error){
});
} else {
res.redirect('/panel');
}
});
This is the cloud function that is running:
Parse.Cloud.define("dockerManager", function(request, response) {
var username = request.params.username;
var override = request.params.override;
var containerID = request.params.containerID;
//other irrelevant code here
} else {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.equalTo("username", username);
query.first(function(user) {
if (user.get("dockerID") == undefined) {
Parse.Cloud.run("createDockerContainer", {username: username});
response.success("[Docker Manager] Created Docker Container for username: " + username + " with Docker ID: " + user.get("dockerID"));
} else if (user.get("isRunning") == true) {
Parse.Cloud.run("stopDockerContainer", {username: username});
response.success("[Docker Manager] Stopped Docker Container for username: " + username + " with Docker ID: " + user.get("dockerID"));
} else if (user.get("isRunning") == false) {
if (user.get("timeRemaining") >= 10){
Parse.Cloud.run("startDockerContainer", {username: username});
response.success("[Docker Manager] Started Docker Container for username: " + username + " with Docker ID: " + user.get("dockerID"));
} else {
response.error("noTime");
}
}
});
}
});
Each of the functions this is calling send a httpReqest to another server, as shown below:
Parse.Cloud.define("stopDockerContainer", function(request, response) {
var username = request.params.username;
//irrelevant code
containerID = user.get("dockerID");
Parse.Cloud.httpRequest({
method: "POST",
url: "http://[redacted address]/containers/" + containerID + "/stop",
headers: {
"Content-Type": "application/json"
},
success: function(httpResponse) {
console.log("[Docker Stopper] Stopped Docker container for user: " + username + " with ID: " + containerID);
user.set("isRunning", false);
user.save();
response.success(true);
},
error: function(httpResponse) {
console.log("[Docker Stopper][CRITICAL] Error stopping docker container for username:" + username);
console.log("Request failed with response code " + httpResponse.status);
response.error(false);
}
});
});
});
Any ideas?

Nodejs exports.module How to export Variable to other Script

my goal is to get a list of files from a google drive folder and its subfolders as json string. so i can then use express to expose it as an API endpoint that other applications can connect to it.
the code is working. i get everything i want, but i do not know how to export my data variable to app.js
// get-filelist.js
var GoogleTokenProvider = require("refresh-token").GoogleTokenProvider,
request = require('request'),
async = require('async'),
data
const CLIENT_ID = "514...p24.apps.googleusercontent.com";
const CLIENT_SECRET = "VQs...VgF";
const REFRESH_TOKEN = "1/Fr...MdQ"; // get it from: https://developers.google.com/oauthplayground/
const FOLDER_ID = '0Bw...RXM';
async.waterfall([
//-----------------------------
// Obtain a new access token
//-----------------------------
function(callback) {
var tokenProvider = new GoogleTokenProvider({
'refresh_token': REFRESH_TOKEN,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
});
tokenProvider.getToken(callback);
},
//-----------------------------
// connect to google drive, look for the folder (FOLDER_ID) and list its content inclusive files inside subfolders.
// return a list of those files with its Title, Description, and view Url.
//-----------------------------
function(accessToken, callback) {
// access token is here
console.log(accessToken);
// function for token to connect to google api
var googleapis = require('./lib/googleapis.js');
var auth = new googleapis.OAuth2Client();
auth.setCredentials({
access_token: accessToken
});
googleapis.discover('drive', 'v2').execute(function(err, client) {
getFiles()
function getFiles(callback) {
retrieveAllFilesInFolder(FOLDER_ID, 'root' ,getFilesInfo);
}
function retrieveAllFilesInFolder(folderId, folderName, callback) {
var retrievePageOfChildren = function (request, result) {
request.execute(function (err, resp) {
result = result.concat(resp.items);
var nextPageToken = resp.nextPageToken;
if (nextPageToken) {
request = client.drive.children.list({
'folderId': folderId,
'pageToken': nextPageToken
}).withAuthClient(auth);
retrievePageOfChildren(request, result);
} else {
callback(result, folderName);
}
});
}
var initialRequest = client.drive.children.list({
'folderId': folderId
}).withAuthClient(auth);
retrievePageOfChildren(initialRequest, []);
}
function getFilesInfo(result, folderName) {
result.forEach(function (object) {
request = client.drive.files.get({
'fileId': object.id
}).withAuthClient(auth);
request.execute(function (err, resp) {
// if it's a folder lets get it's contents
if(resp.mimeType === "application/vnd.google-apps.folder"){
retrieveAllFilesInFolder(resp.id, resp.title, getFilesInfo);
}else{
/*if(!resp.hasOwnProperty(folderName)){
console.log(resp.mimeType);
}*/
url = "http://drive.google.com/uc?export=view&id="+ resp.id;
html = '<img src="' + url+ '"/>';
// here do stuff to get it to json
data = JSON.stringify({ title : resp.title, description : resp.description, url : url});
//console.log(data);
//console.log(resp.title);console.log(resp.description);console.log(url);
//.....
}
});
});
}
});
}
]);
// export the file list as json string to expose as an API endpoint
console.log('my data: ' + data);
exports.files = function() { return data; };
and in my app.js i use this
// app.js
var jsonData = require('./get-filelist');
console.log('output: ' + jsonData.files());
the data variable in app.js doesnt contain any data, while checking the output inside the function getFilesInfo() is working.
so, how to make my data variable accessible in other scripts?
You've got a problem with sync/async behavior.
app.js should be aware when to call the files() function exported from get-filelist. The code you've got there calls the files() function immediately after requiring the get-filelist module. At that moment the data variable is still empty.
Best solution would be to provide the files() function with a callback that will trigger once you've loaded the data variable.
Of course, you will need some extras:
the loaded flag so that you know whether to trigger the callback immediately (if data is already loaded) or postpone the trigger once the load is done.
the array for waiting callbacks that will be triggered upon load (callbacks).
// get-filelist.js
var GoogleTokenProvider = require("refresh-token").GoogleTokenProvider,
request = require('request'),
async = require('async'),
loaded = false, //loaded? Initially false
callbacks = [], //callbacks waiting for load to finish
data = [];
const CLIENT_ID = "514...p24.apps.googleusercontent.com";
const CLIENT_SECRET = "VQs...VgF";
const REFRESH_TOKEN = "1/Fr...MdQ"; // get it from: https://developers.google.com/oauthplayground/
const FOLDER_ID = '0Bw...RXM';
async.waterfall([
//-----------------------------
// Obtain a new access token
//-----------------------------
function(callback) {
var tokenProvider = new GoogleTokenProvider({
'refresh_token': REFRESH_TOKEN,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
});
tokenProvider.getToken(callback);
},
//-----------------------------
// connect to google drive, look for the folder (FOLDER_ID) and list its content inclusive files inside subfolders.
// return a list of those files with its Title, Description, and view Url.
//-----------------------------
function(accessToken, callback) {
// access token is here
console.log(accessToken);
// function for token to connect to google api
var googleapis = require('./lib/googleapis.js');
var auth = new googleapis.OAuth2Client();
auth.setCredentials({
access_token: accessToken
});
googleapis.discover('drive', 'v2').execute(function(err, client) {
getFiles()
function getFiles(callback) {
retrieveAllFilesInFolder(FOLDER_ID, 'root' ,getFilesInfo);
}
function retrieveAllFilesInFolder(folderId, folderName, callback) {
var retrievePageOfChildren = function (request, result) {
request.execute(function (err, resp) {
result = result.concat(resp.items);
var nextPageToken = resp.nextPageToken;
if (nextPageToken) {
request = client.drive.children.list({
'folderId': folderId,
'pageToken': nextPageToken
}).withAuthClient(auth);
retrievePageOfChildren(request, result);
} else {
callback(result, folderName);
}
});
}
var initialRequest = client.drive.children.list({
'folderId': folderId
}).withAuthClient(auth);
retrievePageOfChildren(initialRequest, []);
}
function getFilesInfo(result, folderName) {
data = []; //data is actually an array
result.forEach(function (object) {
request = client.drive.files.get({
'fileId': object.id
}).withAuthClient(auth);
request.execute(function (err, resp) {
// if it's a folder lets get it's contents
if(resp.mimeType === "application/vnd.google-apps.folder"){
retrieveAllFilesInFolder(resp.id, resp.title, getFilesInfo);
}else{
/*if(!resp.hasOwnProperty(folderName)){
console.log(resp.mimeType);
}*/
url = "http://drive.google.com/uc?export=view&id="+ resp.id;
html = '<img src="' + url+ '"/>';
// here do stuff to get it to json
data.push(JSON.stringify({ title : resp.title, description : resp.description, url : url}));
//console.log(resp.title);console.log(resp.description);console.log(url);
//.....
}
});
});
//console.log(data); //now, that the array is full
//loaded is true
loaded = true;
//trigger all the waiting callbacks
while(callbacks.length){
callbacks.shift()(data);
}
}
});
}
]);
// export the file list as json string to expose as an API endpoint
console.log('my data: ' + data);
exports.files = function(callback) {
if(loaded){
callback(data);
return;
}
callbacks.push(callback);
};
Now the app.js behavior needs to change:
// app.js
var jsonData = require('./get-filelist');
jsonData.files(function(data){
console.log('output: ' + data);
});
/* a much more elegant way:
jsonData.files(console.log.bind(console,'output:'));
//which is actually equivalent to
jsonData.files(function(data){
console.log('output: ',data); //without the string concatenation
});
*/

Categories

Resources