Load chat messages upon page load using websockets on node.js - ajax

Hi I'm developing a chat application using nodejs I'm new to node so I'm not very well familiar on its capabilities... I have made my application store its chat messages on mysql database only but I need to also display the past message and current one of a user here is the index.js
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var validator;
var connection = mysql.createConnection({ // setup the connection
host : "localhost",
user : "root",
password: "",
})
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
//res.sendfile(__dirname + '/' +validator);
res.send(validator);
});
//you should have only one io.on('connection')
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
var myMsg= msg; // obtain the incoming msg
var strQuery = "INSERT INTO chat_storage(chat) VALUES(?)"; // your SQL string
connection.query("use schat"); // select the db
connection.query( strQuery, myMsg, function(err, rows){
if(err) {
// handle errors
} else {
io.emit('chat message', msg);
// message received
}
});
});
});
getStdout('php', ['message.php'], function(output) {
validator = output;
//start your server after you get an output
http.listen(3000, function(){
console.log(validator);
});
});
now here is the page for loading the chat messages
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: "localhost:3000/includes/message/store_chat.php",
type: "POST",
dataType: "html",
success: function (result) {
$("#messages").html(result);
}
});
});
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>
My idea was to the chat messages once the page loads I was trying to achieve it using ajax as you can see on the script that I have provided.. but it was no good didnt work at all Please help me

Couple of suggestions:
1) Store all of your messages in-memory ( unless you see this growing to several MB of data ) so that you can catch up any new client quickly.
2) Use socket.io to send the chat messages that have been stored rather than an AJAX call.
I've also included SequelizeJS instead of raw MySQL - It has a much cleaner raw query model and allows you to transition into a DAO model of sorts if you want to.
app.js
// Highly suggest replacing raw mysql with SequelizeJS - http://sequelizejs.com/
var Sequelize = require('sequelize'),
app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http);
var validator;
var messages = [];
var sequelize = new Sequelize('schat', 'root', '');
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.get('/', function(req, res){
res.send(validator);
});
io.on('connection', function(socket){
// Send all previously sent messages
for( i in messages ) {
socket.emit('chat message', messages[i]);
}
socket.on('chat message', function(msg){
console.log('message: ' + msg);
// Push the message into the in-memory array.
messages.push(msg);
// Storage the message for when the application is restarted.
sequelize.query('INSERT INTO chat_storage(chat) VALUES("'+msg'")').success(function() {
// Insert was successful.
}).error(function (err) {
// Error inserting message
});
// Send the message to everyone
socket.broadcast.emit('chat message', msg);
});
});
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
// Load Messages
sequelize.query('SELECT chat FROM chat_storage').success(function (rows) {
for( i in rows ) {
messages.push(rows[i].chat);
}
getStdout('php', ['message.php'], function(output) {
validator = output;
http.listen(3000, function(){
// Start server.
});
});
}).error(function (err) {
// Error!
});
php include
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#messages').append($('li').text($('#m').val()));
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
<?php endblock(); ?>

Related

Notify specific user

I'm trying to make a notification system, but I don't know why the code not working... The redis shoots the event, and the event is received... On the "node server.js in CMD" returns:
C:\xampp\htdocs\test>node socket.js
Listening on Port 3000
{"message":"teste","user":1} //returns when publish redis in controller.
Controller:
public function fire(){
$redis = LRedis::connection();
$data = ['message' => 'teste', 'user' => 1];
if($redis->publish('message', json_encode($data))){
return response()->json(['sucesss' => 1]);
} else {
return response()->json(['error' => 0]);
}
}
Template.blade.php:
<script>
var socket = io('http://localhost:3000');
//console.log(socket); IS CONNECTED...
socket.on('message', function (data) {
console.log(data);
});
</script>
socket.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('message', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log(message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
Console.log
Returns nothing...
If you help me to make work, how I can notify specific user? Example, user 1 creat a link, a link is commented by user 2, the user 1 be notified...

socket.io private updates in specific rooms

This question has been asked several times, but any of the answers is a solution to my problem.
issue:
There will be multiple accounts, and accounds will have multible users. In one specific account, the users will do some realtime updates - but the other accounts will be not affected from those real time changes, every accounts will be private.
We are planing to create room names for each account from cookie
Also we are using node in PHP project.
Sorry for my broken English!
// client side code
$( "#messageForm" ).submit( function() {
var nameVal = $( "#nameInput" ).val();
var msg = $("#messageInput").val();
socket.emit( 'message', { name: nameVal, message: msg } );
// Ajax call for saving datas
$.ajax({
url: "./ajax/insertMessage.php",
type: "POST",
data: { name: nameVal, message: msg },
success: function(data) {
}
});
return false;
});
socket.on( 'message', function( data ) {
var actualContent = $( "#messages" ).html();
var newMsgContent = '<li> <strong>' + data.name + '</strong> : ' + data.message + '</li>';
var content = newMsgContent + actualContent;
$( "#messages" ).append( newMsgContent );
});
//server side codes
var socket = require( 'socket.io' );
var express = require( 'express' );
var http = require( 'http' );
var app = express();
var server = http.createServer( app );
var io = socket.listen( server );
io.sockets.on( 'connection', function( client ) {
console.log( "New client !" );
client.on( 'message', function( data ) {
console.log( 'Message received ' + data.name + ":" + data.message );
//client.broadcast.emit( 'message', { name: data.name, message: data.message } );
io.sockets.emit( 'message', { name: data.name, message: data.message } );
});
});
server.listen( 8080 );
You can create private chat rooms as below.
Server side code
// usernames which are currently connected to the chat
var usernames = {};
// rooms which are currently available in chat
var rooms = ['room1','room2','room3'];
io.sockets.on('connection', function (socket) {
// when the client emits 'adduser', this listens and executes
socket.on('adduser', function(username){
// store the username in the socket session for this client
socket.username = username;
// store the room name in the socket session for this client
socket.room = 'room1';
// add the client's username to the global list
usernames[username] = username;
// send client to room 1
socket.join('room1');
// echo to client they've connected
socket.emit('updatechat', 'SERVER', 'you have connected to room1');
// echo to room 1 that a person has connected to their room
socket.broadcast.to('room1').emit('updatechat', 'SERVER', username + ' has connected to this room');
socket.emit('updaterooms', rooms, 'room1');
});
// when the client emits 'sendchat', this listens and executes
socket.on('sendchat', function (data) {
// we tell the client to execute 'updatechat' with 2 parameters
io.sockets.in(socket.room).emit('updatechat', socket.username, data);
});
socket.on('switchRoom', function(newroom){
// leave the current room (stored in session)
socket.leave(socket.room);
// join new room, received as function parameter
socket.join(newroom);
socket.emit('updatechat', 'SERVER', 'you have connected to '+ newroom);
// sent message to OLD room
socket.broadcast.to(socket.room).emit('updatechat', 'SERVER', socket.username+' has left this room');
// update socket session room title
socket.room = newroom;
socket.broadcast.to(newroom).emit('updatechat', 'SERVER', socket.username+' has joined this room');
socket.emit('updaterooms', rooms, newroom);
});
// when the user disconnects.. perform this
socket.on('disconnect', function(){
// remove the username from global usernames list
delete usernames[socket.username];
// update list of users in chat, client-side
io.sockets.emit('updateusers', usernames);
// echo globally that this client has left
socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
socket.leave(socket.room);
});
});
Client side code
var socket = io.connect('http://localhost:8080');
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser', prompt("What's your name?"));
});
// listener, whenever the server emits 'updatechat', this updates the chat body
socket.on('updatechat', function (username, data) {
$('#conversation').append('<b>'+username + ':</b> ' + data + '<br>');
});
// listener, whenever the server emits 'updaterooms', this updates the room the client is in
socket.on('updaterooms', function(rooms, current_room) {
$('#rooms').empty();
$.each(rooms, function(key, value) {
if(value == current_room){
$('#rooms').append('<div>' + value + '</div>');
}
else {
$('#rooms').append('<div>' + value + '</div>');
}
});
});
function switchRoom(room){
socket.emit('switchRoom', room);
}
// on load of page
$(function(){
// when the client clicks SEND
$('#datasend').click( function() {
var message = $('#data').val();
$('#data').val('');
// tell server to execute 'sendchat' and send along one parameter
socket.emit('sendchat', message);
});
// when the client hits ENTER on their keyboard
$('#data').keypress(function(e) {
if(e.which == 13) {
$(this).blur();
$('#datasend').focus().click();
}
});
});
</script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>ROOMS</b>
<div id="rooms"></div>
</div>
<div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;">
<div id="conversation"></div>
<input id="data" style="width:200px;" />
<input type="button" id="datasend" value="send" />
</div>
Reference Link:
http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/

Difference between io.on and socket.on in Socket.io?

I am confused on what the 'socket' parameter is that is passed with the function (In 'The enigma' section). Then the parameter gets used 'socket.on'. What is the difference between io.on and socket.on?
The following code is slightly adapted from the Socket.io chat application example.
Variables
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app)
var io = require('socket.io').listen(server);
The enigma
io.on('connection', function (socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
})
});
Start server
server.listen(3000, function() {
console.log('server is running');
});
index.jade
body
script(src="/socket.io/socket.io.js")
form(method='post', action="/")
input(type='text', id='user', autocomplete='off')
input(type='submit', onClick="myFunc()")
strong messages:
p(id="messages")
script.
var socket = io();
socket.on('message', function(msg) {
console.log('client: ' + msg);
});
function myFunc() {
var text = document.getElementById('user');
socket.emit('message', text.value);
text.value = '';
};
In your code example, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events.
The socket argument of the connection event listener callback function is an object that represents an incoming socket connection from a client.
Both of them can listen for events with the on method.
It might help you visually understand how the two are separate if you re-imagine your code sample like this:
var connectionEvent = function(socket) {
console.log('user connected');
socket.on('message', function(msg) {
console.log('message: ' + msg);
io.emit('message', msg);
});
};
io.on('connection', connectionEvent);

node.js - Socket IO times out after some time

I'm trying to build up a socket.io server for my own multiplayer game, but for some reason the server goes down after a certain amount of time and I don't know why. I have tried several ways to run the server (nodemon and forever, everything with or without screen). I don't think that this is an inactivity problem because I added a random stuff generator to simulate some activity on the server, yet the problem persists. My cpu load with the running server stays between 2-3 %. I'm running node 4.x and the current stable socket.io build (1.3.6).
And here is my code:
var shortId = require('shortid'),
io = require('socket.io')(process.env.PORT || 4567),
mysql = require('mysql'),
connection = mysql.createConnection({
host: 'localhost',
user: 'xxx',
password: 'xxx',
database: 'xxx'
});
var clients = [];
var clientLookup = {};
//Placed Components (builded stuff from players or enviroment)
var placed_components = 'Server1_PlacedC';
connection.connect(function (err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
});
setInterval(function () {
var random = Math.random();
//connection.query(
// 'INSERT INTO '+placed_components+' SET ?',
// {data:countdown},
// function(err,result){
// if (err) throw err;
// }
//);
console.log(random);
}, 100);
io.on('connection', function (socket) {
var currentClient;
console.log('connected', socket.id);
//////////////////////////////////////////////////////////////////////////////
socket.on('disconnect', function () {
console.log('player disconnected', currentClient.id);
socket.broadcast.emit('disconnected', currentClient)
var index = clientLookup[currentClient.id];
clients.splice(index, 1);
})
///////////////////////////////////////////////////////////////////////////// /
socket.on('register', function (data) {
currentClient = {
id: shortId.generate(),
health: 100,
isDead: false
};
console.log('registering', currentClient.id);
clients.push(currentClient);
clientLookup[currentClient.id] = currentClient;
socket.emit('registerSuccess', {id: currentClient.id});
socket.broadcast.emit('spawn', {id: currentClient.id});
console.log('connected players', clients.length);
clients.forEach(function (client) {
if (currentClient.id == client.id)
return;
socket.emit('spawn', {id: client.id});
console.log('sending spawn to new player for playerid', client.id);
})
});
socket.on('beep', function () { // Beep Request
socket.emit('boop');
console.log("received some beep!");
});
socket.on('move', function (data) {
data.id = currentClient.id;
socket.broadcast.emit('move', data);
//console.log(JSON.stringify(data));
});
socket.on('ShareObject', function (data) {
data.id = currentClient.id;
socket.broadcast.emit('ReveiveObject', data);
console.log(JSON.stringify(data));
});
socket.on('SharePlayerAnimation', function (data) {
data.id = currentClient.id;
socket.broadcast.emit('BroadcastPlayerAnimation', data);
console.log("a Player changed his animation" + JSON.stringify(data));
});
//////////////////////////////////////////////////////////////////////////////
socket.on('benchmark', function (data) {
console.log(data);
});
//////////////////////////////////////////////////////////////////////////////
})
console.log('server started');

Why isn't the server sending or the client receiving data via socket.io in my express app?

My node app posts an object (consisting of data collected in a form on the client) to Salesforce via their API. On receiving a success or error message, I would like to send it to the client-side, then display it. Socket.io seemed like the tool for this in my simple node/express3 app, but beyond the simple demo I'm not able to get data to pass between my server and my client.
My relevant server side code:
var express = require('express');
var port = 5432;
var app = module.exports = express();
var server = require('http').createServer(app);
var nforce = require('nforce');
var org = nforce.createConnection({
clientId: 'MY_CLIENT_ID',
clientSecret: 'MY_CLIENT_SECRET',
redirectUri: 'http://localhost:5432/oauth/_callback'
});
var io = require('socket.io').listen(server);
// here I authenticate with Salesforce, this works fine
app.post('/salesforce', function(req, res){
var lead = nforce.createSObject('Lead');
// here I construct the lead object, which also works fine
org.insert(lead, oauth, function(err, res) {
if (err === null) {
console.log(res);
leadSuccessMessage(res);
}
else {
console.log(err);
var error = {
errorCode: err.errorCode,
statusCode: err.statusCode,
messageBody: err.messageBody
};
console.log(error);
leadErrorMessage(error);
}
});
}
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
io.sockets.on('connection', function (socket) {
socket.emit('sfRes', resp);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
io.sockets.on('connection', function (socket) {
console.log("socket is: " + socket);
socket.emit('sfRes', err);
socket.on('thanks', function (data) {
console.log(data);
});
});
}
And my relevant client side scripts:
<script src="/socket.io/socket.io.js"></script>
<script>
current.page = document.URL;
console.log("current page is: " + current.page);
var socket = io.connect(current.page);
socket.on('sfRes', function (data) {
console.log("client received: " + data);
fst.showLeadStatus(data);
socket.emit('thanks', {message: "received server feedback"});
});
</script>
When I post the form containing valid data using a spicy little AJAX call:
postToSF: function(){
$('#submitLead').on('click', function(e){
e.preventDefault();
var formData = $('#lead_form').serialize();
$.ajax({
type: 'POST',
url: '/salesforce',
data: formData,
success: function(){
fst.log('success!');
},
error: function(xhr, ajaxOptions, thrownError){
console.error(xhr.status); // 0
console.error(thrownError);
}
});
});
}
All I get are tears, and these in the server-side console:
// the result of `console.log(res)`
{ id: '00Qa000001FZfhKEAT', success: true, errors: [] }
// and proof that `leadSuccessMessage()` got called
called success message from server
Instead of calling this function from a client-side object as it's supposed to:
showLeadStatus: function(response){
if (response.success) {
fst.log("showing lead status as: " + response);
$('#leadStatus').addClass('success').removeClass('error').fadeIn().delay(4000).fadeOut();
}
else {
fst.log("showing lead status as: " + response);
$('#leadStatus').text(response.messageBody).addClass('error').removeClass('success').fadeIn().delay('4000').fadeOut();
}
$('#startOver').click();
}
Which works fine if I call it in the console passing it the data the server is supposed to be socketing over:
// this works, gosh darn it
fst.showLeadStatus({ id: '00Qa000001FZfhKEAT', success: true, errors: [] });
The Salesforce post error case doesn't surface anything to the client either. And there are no errors in the client or server console to contend with.
I'm stumped. Please help!
I would do something like this -
var mysocket = null;
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
mysocket = socket;
socket.on('thanks', function (data) {
console.log(data);
});
});
app.post('/salesforce', function(req, res){
....
....
})
function leadSuccessMessage(res) {
var resp = res;
console.log('called success message from server');
if(mysocket)
mysocket.emit('sfRes', resp);
}
function leadErrorMessage(error) {
var err = error;
console.log('called error message from server');
if(mysocket)
mysocket.emit('sfRes', err);
}

Resources