Socket.io show amount of user connections - javascript

I got a very simple socket.io application where I'm able to see when a user connects to my site and when a user leaves. The first user is able to see everybody that gets in, however the second will only see the people coming in after him, and so on.... What I want the user that connects to see are all current connected users
Server.js
var io = require("socket.io")(http);
var users = [];
io.on("connection", function (socket) {
console.log("User connected", socket.id);
Some loop to see user connected I think?!
socket.on("user_connected", function (username) {
users[username] = socket.id;
console.log(users);
if (username !== 'null'){
io.emit("user_connected", username);
}
});
socket.on("send_message", function (data) {
io.emit("new_message", data);
});
socket.on("user_left", function (datan) {
io.emit("user_remove", datan);
console.log("user left", datan);
});
});
site.html
window.onbeforeunload = function () {
io.emit("user_left", name);
};
var name = <?php echo json_encode($_SESSION['displayname']); ?>;
var bild = <?php echo json_encode($_SESSION['userpic']);?>;
var dt = new Date();
var tid = dt.getHours() + ":" + dt.getMinutes();
io.emit("user_connected", name);
sender = name;
io.on("user_connected", function (username) {
var html = "";
html += "<li data-username='" + username + "'>" + username + "</li>";
document.getElementById("users").innerHTML += html;
});
Looked into this question, but me a dumb coder doesn't understand what 'my_room' is towards my soloution. Sorry for weird question, I'm just kind of lost

If you want to send a user list to everyone, create an object like users, add a record each time a user connected, and broadcast to everyone.
if someone disconnects, then first remove that from your collection then send only disconnected user's info to clients, so clients can delete that user from their list.
If all you want is total number of questions, just send io.sockets.clients().length

Related

Express not doing anything but sending HTML file

I'm using an app.post method in Express like so:
app.post('/race', function(req,res) {
let raceResponse = {
user_name: req.body.userName
}
console.log('Express has received race.');
//Socket.IO
let race = io.of('/race').on('connection', (socket) => {
console.log('A user has entered the race!');
socket.on('racePageReady', function() {
console.log('race page ready recieved');
socket.emit('racePageInfo', raceResponse);
});
socket.on('createRoom', function(roomName) {
socket.join(roomName);
let clients = io.sockets.adapter.rooms[roomName].sockets;
console.log("A room with the name " + roomName + "was created.");
console.log(clients);
socket.emit('roomCreated', clients);
});
socket.on('joinRoom', function(roomName) {
socket.join(roomName);
let clients = io.sockets.adapter.rooms[roomName].sockets;
console.log('A user joined the room with the name: ' + roomName + ". The user's name is " + raceResponse.user_name);
console.log(clients);
socket.emit('roomCreated', clients);
});
});
res.sendFile(path.join(__dirname, '/client/race/index.html'));
}
The page is being sent fine, but the console.log and all the other Socket.IO stuff just doesn't happen. I'm finding this peculiar, because I have a different app.post method that works just fine, all console.logging and Socket.IO business happens. Here's the code:
app.post('/city', function(req,res) {
let cityResponse = {
user_name: req.body.userName
}
console.log('Express has received city.');
//Socket.IO
let city = io.of('/city').on('connection', (socket) => {
socket.id = Math.random();
socket.name = cityResponse.user_name;
SOCKET_LIST[socket.id] = socket; //defined earlier
User.onConnect(socket); //defined earlier
socket.on('cityPageReady', function() {
socket.emit('cityPageInfo', cityResponse);
console.log('city page ready recieved');
});
console.log('A user has connected to the city!');
console.log("Socket: " + socket);
console.log("Socket ID: " + socket.id);
console.log("SOCKET_LIST: ");
console.log(SOCKET_LIST);
socket.on('chat message', function(msg, user) {
console.log('User ' + user + ' sent the message : ' + msg);
socket.emit('chat message', msg, user);
});
});
res.sendFile(path.join(__dirname, '/client/city/index.html'));
});
As far as I can tell, both methods look pretty much the same, except for the Socket.IO stuff in the middle. I'm fairly certain that the io.of method is correct, as it's working for the City page, but not the race.
The only other difference is the way that the two pages are accessed. The City page is accessed through a HTML form with an action attribute, whereas the Race page is accessed through a HTML link (on the City page) with a href attribute.
Both methods are shown below:
CITY
<form id="cityForm" action="http://localhost:4000/city" method="POST">
User name: <input type="text" name="userName">
button type="submit" id="formSubmit">Submit</button>
</form>
RACE
<div><a href="http://localhost:4000/race"></div>
Can anyone see why this peculiar behaviour is occuring? If any other information is needed please let me know so that I can include it.
When clicking an on HTML link, the browser does a GET HTML request. When you submit a Form (with method="POST"), the browser does a POST request.
When using app.post(), you tell express to listen for POST requests. If you want express to listen for GET requests, you should use app.get()

Facebook email is returned as undefined from phonegap facebookConnect plugin

I am using the phonegap facebook Connect plugin to enable facebook login in my app.
However the facebook email is being returned as undefined.
Do I need to add something into my code?
I have looked up this issue on the internet and it seems my code should work. Everything else is returned except for the email address.
I would appreciate if you can help
Here is my javascript code:
facebookConnectPlugin.api('/me?fields=id, email, link, name, picture', ["public_profile"],function(data){
var fb_user_id = data.id;
var fb_email = data.email;
var fb_name = data.name;
var fb_picture_url = data.picture.data.url;
var fb_user_link = data.link;
alert("fb_email" + fb_email);
}); //end api call
Edit:
I tried a test user account with this code and the email address DID get returned. However for the real account I was testing with this doesn't work.
With more testing I tried adding in the email permission as follows however this did not work as the data that I got back stated "FACEBOOK_NON_JSON_RESULT"
facebookConnectPlugin.api('/me?fields=id, email, link, name, picture', ["public_profile", "email"],function(data){
var fb_user_id = data.id;
var fb_email = data.email;
var fb_name = data.name;
var fb_picture_url = data.picture.data.url;
var fb_user_link = data.link;
alert("fb_email" + fb_email);
}); //end api call
I find a workaround for this problem which was to do two separate api requests as follows:
facebookConnectPlugin.api('/me?fields=email', ["email"], function(apiResponse) {
//alert("api" + JSON.stringify(apiResponse));
fb_email = apiResponse.email;
alert("fb_email" +fb_email); //email being retrieved successfully
facebookConnectPlugin.api('/me?fields=id, name, link, picture', ["public_profile"],function(data) {
alert("data" + JSON.stringify(data));
var fb_user_id = data.id;
var fb_name = data.name;
var fb_picture_url = data.picture.data.url;
var fb_user_link = data.link;
alert("fb_user_id" + fb_user_id);
alert("fb_name" + fb_name);
alert("fb_picture_url" + fb_picture_url);
alert("fb_user_link" + fb_user_link);
//do stuff with facebook user data here
}
,function(error){
//api call failed
alert("api call Failed: " + JSON.stringify(error));
}); //end api
}
,function(error){
alert("email api call Failed: " + JSON.stringify(error));
}); //end api
This works perfect!

How would I make user wait to join until meeting organizer joins first

I am implementing a video conference room in which a user can create a video conference and invite other users.
Now I want to make sure that the user can't join the conference until the meeting organizer opens the room.
I have the following code but it is not working. The meeting organizer can open the room but when users click on "join conference" it doesn't join.
// https://github.com/muaz-khan/RTCMultiConnection
var rmc = new RTCMultiConnection();
rmc.userid = "<?php echo $user->fname . ' ' . $user->lname . ' (' . $user->username . ')' ; ?>";
rmc.session = {
video: true,
audio: true,
data: true
};
var room_status = 0; //room closed
$('#open-room').click(function () {
// http://www.rtcmulticonnection.org/docs/open/
room_status = 1; //room opened
rmc.open();
rmc.streams.mute({video : true});
document.getElementById("on-off-video").style.color= 'red';
});
$('#join-room').click(function () {
if(room_status == 1) {
// http://www.rtcmulticonnection.org/docs/connect/
rmc.connect();
rmc.streams.mute({video: true});
document.getElementById("on-off-video").style.color= 'red';
}
console.log("Waiting for meeting organizer");
});
// display a notification box
window.addEventListener('beforeunload', function () {
return 'Do you want to leave?';
}, false);
// leave here
window.addEventListener('unload', function () {
rmc.leave();
}, false);
rmc.onMediaCaptured = function () {
$('#share-screen').removeAttr('disabled');
$('#open-room').attr('disabled', 'disabled');
$('#join-room').attr('disabled', 'disabled');
};
//chat
rmc.onopen = function (event) {
//alert('Text chat has been opened between you and ' + event.userid);
document.getElementById('input-text-chat').disabled = false;
room_status = 1;
};
//end of chat
$('#disconnect').click(function () {
room_status = 0; //room closed
rmc.leave();
setTimeout("location.href = '../';",2000);
});
//to know the stream type
rmc.onstream = function (e) {
if (e.type == 'local') {
// alert("the stream is local");
}
if (e.type == 'remote') {
// alert("the stream is remote");
}
if (e.isVideo) {
var uibox = document.createElement("div");
uibox.appendChild(document.createTextNode(e.userid));
uibox.className = "userid";
uibox.id = "uibox-" + e.userid.replace(/ |\(|\)/g, '');
document.getElementById('video-container').appendChild(e.mediaElement);
document.getElementById('video-container').appendChild(uibox);
}
else if (e.isAudio) {
document.getElementById('video-container').appendChild(e.mediaElement);
}
else if (e.isScreen) {
$('#cotools-panel iframe').hide();
$('#cotools-panel video').remove();
document.getElementById('cotools-panel').appendChild(e.mediaElement);
}
};
//removes the div containing the userid of the user who is leaving
rmc.onleave = function (e) {
$('#' + "uibox-" + e.userid.replace(/ |\(|\)/g, '')).remove();
};
It seems you have 3 problems here.
1) First, I think you can't use only one RTCMultiConnection object to open and join a room. You have to create 2 separate objects. But, your code is not supposed to run in the same window for opening and joining the room. So It's not a problem if you run it once in a window to open the room and one in another window to join it.
In this case you have a more important problem. Your variable room_status is set to 1 when you open the room in one window. But in the other window, room_status is still equals to 0 so you don't call the code inside the if() in $('#join-room').click function.
It's not a big deal, for now, let's delete the if statement to be sure your code is executed (and read my point 3 for your original goal).
2) I look to the simple example given on https://github.com/muaz-khan/RTCMultiConnection : https://jsfiddle.net/c46de0L8/ and it seems you should use join and not connect. And above all, you should use a Channel ID and a Room Id to be able to connect 2 users.
So I change your code a little and it seems to work well :
var CHANNEL_ID = "MYCHANNEL-" + window.RMCDefaultChannel;
var ROOM_ID = "MYROOM";
var SESSION = {
video: true,
audio: true,
data: true
};
var USERID = "<?php echo $user->fname . ' ' . $user->lname . ' (' . $user->username . ')' ; ?>";
var rmc = undefined;
var room_status = 0; //room closed
$('#open-room').click(function () {
// http://www.rtcmulticonnection.org/docs/open/
room_status = 1; //room opened
rmc = new RTCMultiConnection(CHANNEL_ID);
rmc.userid = USERID;
rmc.session = SESSION;
rmc.open({
dontTransmit: true,
sessionid: ROOM_ID
});
rmc.streams.mute({video : true});
document.getElementById("on-off-video").style.color= 'red';
});
$('#join-room').click(function () {
//if(room_status == 1) {
// http://www.rtcmulticonnection.org/docs/connect/
rmc = new RTCMultiConnection(CHANNEL_ID);
rmc.join({
sessionid: ROOM_ID,
userid: USERID,
session: SESSION
});
rmc.streams.mute({video: true});
document.getElementById("on-off-video").style.color= 'red';
//}
console.log("Waiting for meeting organizer");
});
The rest of the code remains unchanged.
I put a rough working code in a JSFiddle: https://jsfiddle.net/sebdoncker/fjtkvnjq/2/
3) Now you still have the problem : How to be sure that the room is opened before to be able to join it. I think you can use the ROOM ID for this. When one user open a new room you should generate a ROOM ID. Now, you have to send this ROOM ID to your joiner user (by server communication or another way depending of your application architecture). And Since the joiner user doesn't have the ROOM ID, you can disable the join button.
It's just a lead, this depends of your overall application architecture.

Parse JS add user with role

I am trying to basically have a sign up form that will sign up a user and also add that user that just signed up to a certan role. I got the app signing up the user fine but it isnt creating the role and adding the user to that role. Here is what I had
<script type="text/javascript">
Parse.initialize("key", "key");
//set the user
var user = new Parse.User();
$( "form" ).submit(function( event ) {
//get the input data
var username = $('#username').val();
var email = $('#email').val();
var password = $('#password').val();
var facility = $('#facility').val();
//Set the user info
user.set("facility", "" + facility + "");
user.set("username", "" + username + "");
user.set("email", "" + email + "");
user.set("password", "" + password + "");
//Sign them up
user.signUp(null, {
success: function(user) {
// Hooray! Let them use the app now.
//Make the role
var roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
var role = new Parse.Role("Pro", roleACL);
role.getUsers().add(username);
role.save();
//Show and Hide the alert
$('#successModal').modal('show');
setTimeout(function(){
$('#successModal').modal('hide')
}, 4000);
//Clear the form
$( 'form' ).each(function(){
this.reset();
});
},
error: function(user, error) {
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});
return false
});
</script>
My thought was create the user then on successful user creation create the role and add the user to that role. Seems not to be working though.
code the querys a user
querys a role
then adds the user to the role
var qu = new Parse.Query(Parse.User);
var qr = new Parse.Query(Parse.Role);
qr.get(roleId, {
success: function(role) {
_role = role;
qu.get(userId, {
success: function(user) {
_role.getACL().setRoleReadAccess(_role, true);
_role.getUsers().add(user);
_role.save();
response.success(_role.toJSON());
},
error: function(object, error) {
console.log('got role, failed on get user');
}
});
The aim is to add the newly saved user to an existing role, so that role must be queried, not created when the user is saved.
Since you must the save of a user, query a role, and save that role -- three asynch operations that must be performed in sequence -- it's advisable to use promises, lest the code become unreadably indented, so...
// prepare the user as you have it, then
user.signUp().then(function(user) {
// query the role, you can get it with the role name
var roleQuery = new Parse.Query(Parse.Role);
roleQuery.equalTo("name", "Pro");
return roleQuery.first();
}).then(function(role) {
role.getUsers().add(user);
return role.save();
}).then(function() {
// no need to set a timer. with the promise, we know exactly when we are done
$('#successModal').modal('hide');
}, function(error) {
alert("Error: " + error.code + " " + error.message);
});
Be sure to first create the "Pro" role manually using the data browser. Read through the security section in the programming guide.
Also note, if this happens for every user, the role code is a good candidate to be part of an afterSave cloud function on PFUser.

node, socket.io - update client when new entry added to news feed?

I've created client and server of node with socket.io. server is executing 4 get requests of news feed and fetched the data. These data is sent to the client with socket.io.
client is displaying news feed on the occurrence of specific socket.io event.
This works well for once. Here is the code and working fiddle
server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, redis = require("redis");
var http = require("http");
// initialize the container for our data
var data = "";
var nfs = [
"http://economictimes.feedsportal.com/c/33041/f/534037/index.rss",
"http://www.timesonline.co.uk/tol/feeds/rss/uknews.xml",
"http://www.independent.co.uk/news/business/rss",
"http://www.dailymail.co.uk/money/index.rss"
];
//setInterval(function() {
for(var i=0; i<nfs.length; i++){
//console.log(nfs[i]);
http.get(nfs[i], function (http_res) {
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log("data received");
});
});
}
//}, 30000);
app.listen(8080);
function handler (req, res) {
fs.readFile(__dirname + '/client.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
//setInterval(function() {
socket.emit('news', data);
/*socket.on('my other event', function (data) {
console.log(data);
});*/
//}, 5000);
});
client.html
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.2.1.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
//socket io client
var socket = io.connect('http://localhost:8080');
//on connetion, updates connection state and sends subscribe request
socket.on('connect', function(data){
setStatus('connected');
socket.emit('subscribe', {channel:'notif'});
});
//when reconnection is attempted, updates status
socket.on('reconnecting', function(data){
setStatus('reconnecting');
});
//on new message adds a new message to display
socket.on('news', function (data) {
console.log(data);
//socket.emit('my other event', { my: 'data' });
addMessage(data);
});
/*socket.on('news', function (data) {
debugger;
socket.emit('my other event', { my: 'data' }
var msg = "";
if (data) {
msg = data;
}
addMessage(msg);
});*/
//updates status to the status div
function setStatus(msg) {
$('#status').html('Connection Status : ' + msg);
}
//adds message to messages div
function addMessage(msg) {
//debugger;
var $xml = $(msg);
var html = '';
$xml.find("item").each(function() {
var $item = $(this);
html += '<li>' +
'<h3><a href ="' + $item.find("link").text() + '" target="_new">' +
$item.find("title").text() + '</a></h3> ' +
'<p>' + $item.find("description").text() + '</p>' +
// '<p>' + $item.attr("c:date") + '</p>' +
'</li>';
});
$('#result').prepend(html);
}
</script>
</head>
<body>
<div id="status"></div><br><br>
<ul id="result"></ul>
</body>
</html>
What I understand about socket.io is that we don't need long server polling and so how do server come to know that news is added to the respected news feed.
How do I update the client with newly added news when news is added to the news feed rss ???
Update
Ok so from all the responses I get the point that it is not possible for socket.io to know that new entry has been added. So, how do I know (which tools/libraries do require to know that new entry has beed added and update the client as well) ???
Retrieving the messages from the news feeds are completely independent of socket.io unless the news feeds implement sockets on their end and your server becomes their client. So you will have to continue to poll them with http requests to know whether they have updated data.
In order to notify your clients of the update you would just emit the news event. Presumably you would have logic on the server to make sure you are only sending events which have not previously be sent.
There is no way for "node" to know when a new entry is added to the news feed. You will have to poll the news service like you are doing now. This really has nothing to do with Node or Socket.io unless I completely misunderstand what you are asking.

Categories