Disconnect event fired many times in socket.io - mysql

I've implemented a simple chat application .But when client leaves the page or closes browser tab disconnect event is called many times. Some time twice some time thrice. Inside disconnect call back function i'm inserting chat history into database. As callback function is calling many times same chat history is inserting many times. Dont know what is the problem. Please help.
Code is like this
Server side code
var sys = require('sys');
var fs = require('fs');
var io = require('socket.io');
var connection = function(){
sys.puts("Here")
var mysql = require('mysql');
var sql = mysql.createConnection({
host:'localhost',
port:3306,
user:'root',
password:'root'
});
sql.query('use chat');
sys.puts("Here" +sql)
return sql;
}
var Server = require('http').createServer(function(req, response){
sys.puts("request recieved");
response.writeHeader(200,{"Content-Type":"text/html"});
response.write("Hello World");
var rs = fs.createReadStream(__dirname + '/chat.html')
sys.pump(rs,response);
});
var history = "";
var socket = io.listen(Server);
var mysql = connection();
socket.sockets.on('connection',function(client){
sys.puts("socket connected ID "+client.id);
sys.puts("session id",client.handshake.sessionID)
var username;
client.send('Welcome to chat');
client.send('Enter your name');
client.on('message',function(message){
if(!username)
{
username = message;
client.send('Welcome,' +username);
return;
}
feedback = username+' sent:'+message;
history = history + feedback + '\n';
client.send(feedback)
client.broadcast.send(feedback);
sys.puts("History is " +history);
sys.puts("mysql" +mysql);
client.on('disconnect',function(){
mysql.query('insert into tblchatHistory (fldChatHistory) values ("'+history+'")',function(err){
sys.puts("error" +err);
history = "";
})
sys.puts("socket connected ID "+client.id);
})
})
})
Server.listen(4000);
Client side code
<script type="text/javascript">
var socket;
socket = new io.connect("http://localhost:4000");
var connect = false;
socket.on('connect',function(){
alert("connected "+socket.socket.sessionid);
connect = true;
})
function chat()
{
socket.on('message',function(message){
var data = message;
var list ='<li>' +data +'</li>'
document.getElementById("log").innerHTML +=list;
})
}
function sendMsg(event)
{
var entry = document.getElementById("entry");
var msg = entry.value;
if(event.keyCode != 13)return
if(msg)
{
if(connect)
{
socket.emit('message',msg);
entry.value = "";
}
}
}
</script>
<body onload="chat();">
<h1>Chat</h1>
<div><ul id="log"></ul></div>
<div id="console">
<input type="text" id="entry" onkeypress="sendMsg(event);"/>
</div>
<div><a href="http://localhost:8085/BillDesk/welcomeJSF.jsf" >Exit chat</a></div>
</body>

Related

Is it possible to detect the number of users currently interacting a section of html code?

This may be a naive question, sorry for that, but I'm trying to sort out a potential concurrency issue. I have a registration procedure which begins with the user selecting their category from a drop down menu. That triggers a query to a particular page in a google sheet where it retrieves an available ID number that is displayed to the user. There are a couple steps required before the final submit button is pressed. This (I think) creates a chance for more than one person to retrieve the same ID. I do use google's lockservice but on the function which writes the form information to my spreadsheet (based on a script of Martin Hawksley). If it was possible to determine how many people were currently viewing the registration page I could use that value in the query with an if statement such that a different row number is retrieved. This would eliminate the chance of duplicates.
Does that sound reasonable? Perhaps there is a much better way.
Any advice would be most appreciated.
If it was possible to determine how many people were currently viewing
the registration page
If you don't want to use Google Analytics. Here is a simple example of how you can poll with a client to maintain a session, and count how many users are active.
NOTE: I threw this together, it could be refactored a bit to be prettier, but it should get the gist of it across
Working Example Open this a couple times, you will see your session IDs in each and a count. Sessions expire after 60 seconds of no activity, and auto-end if you close the page.
Project file structure:
Code.gs
index.html
javascript.html
Apps Script
var sessionTimeout = 60; //60 seconds
//Triggered when the page is navigated to, serves up HTML
function doGet(){
var template = HtmlService.createTemplateFromFile('index');
template.userID = NewSession();
return template.evaluate()
.setTitle('Active Users')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
/*================ Polling ================*/
//Client calls this function to poll, updates cache, returns active users
function ClientPoll(id){
var scriptCache = CacheService.getScriptCache();
UpdateScriptCache(id, 0, scriptCache, true);
var activeIDs = GetActiveIDs(scriptCache);
return activeIDs;
}
function EndSession(id){
var scriptCache = CacheService.getScriptCache();
scriptCache.remove(id);
var activeIDs = GetActiveIDs(scriptCache);
activeIDs.splice(activeIDs.indexOf(id), 1);
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
}
//Server calls every minute to check for inactive sessions
function CheckForInactiveSessions(){
var scriptCache = CacheService.getScriptCache();
var activeIDs = GetActiveIDs(scriptCache);
var allSessions = scriptCache.getAll(activeIDs);
if(Object.keys(allSessions).length > 0){
var keys = Object.keys(allSessions);
var newActiveIDs = [];
for(var i = 0; i < keys.length; i++){
newActiveIDs.push(keys[i]);
}
Logger.log(keys.length);
UpdateScriptCache('ActiveIDs', newActiveIDs, scriptCache, false);
}
}
/*================ Session Creation & Cache ================*/
//Handles setting up a new session, called when page is opened
function NewSession(){
var id = GenerateUID();
AddNewActiveID(id);
return id;
}
//Gets a list of all active IDs
function GetActiveIDs(scriptCache){
if(!scriptCache){
scriptCache = CacheService.getScriptCache();
}
var active = scriptCache.get('ActiveIDs');
if(active !== null){
return JSON.parse(active);
}
return [];
}
//Adds a new ID to the cache
function AddNewActiveID(id){
var scriptCache = CacheService.getScriptCache();
var activeIDs = JSON.parse(scriptCache.get('ActiveIDs'));
if(activeIDs == null){
activeIDs = [];
}
activeIDs.push(id);
//Update the Active ID List
UpdateScriptCache('ActiveIDs', activeIDs, scriptCache, false);
//Add new ID to cache
UpdateScriptCache(id, 0, scriptCache, true);
}
//Handles updating the Active IDs cache and prevents race conditions or collisions
function UpdateScriptCache(key, data, cache, timeout){
var lock = LockService.getScriptLock();
lock.waitLock(15000);
if(timeout){
cache.put(key, JSON.stringify(data), sessionTimeout);
} else {
cache.put(key, JSON.stringify(data), 21600)
}
lock.releaseLock();
}
/*================ ID Generation ================*/
//Handles generating and returning a new ID
function GenerateUID(){
var generator = new IDGenerator();
var id = generator.generate();
return id;
}
//Generates a random(ish) ID;
function IDGenerator() {
this.length = 10;
this.timestamp = new Date().getTime();
var getRandomInt = function( min, max ) {
return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
}
this.generate = function(){
var timestamp = this.timestamp.toString();
var parts = timestamp.split('').reverse();
var id = '';
for(var i = 0; i < this.length; i++){
var index = getRandomInt(0, parts.length - 1);
id += parts[index];
}
return id;
}
}
JavaScript:
<script>
//Initilization
$(function(){
//Set the users ID in HTML
$('#userID').text(userID);
//Setup handler to end the session before the page closes
$(window).bind('beforeunload', function(){
EndSession();
});
//Start the timer
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
});
//Polls the server to update session and get active users
function PollServer(){
console.log('Polling server');
google.script.run.withSuccessHandler(UpdateActiveUsers).ClientPoll(userID);
var deadline = new Date(Date.parse(new Date()) + 5000);
initializeTimer('pollingIn', deadline);
}
//Ends the session right before the page closes
function EndSession(){
google.script.run.withSuccessHandler().EndSession(userID);
}
//Updates the active users div
function UpdateActiveUsers(users){
console.log(users)
var userText = '';
for(var i = 0; i < users.length; i++){
if(i == 0){
userText += users[i];
continue;
}
userText += ', ' + users[i];
}
$('#activeUsersCount').text(users.length);
$('#activeUsers').text(userText);
}
//Initilizes the timer
function initializeTimer(id, endtime) {
var timer = $('#'+id);
function updateTimer() {
var time = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((time / 1000) % 60);
timer.text(seconds);
if (time <= 0) {
clearInterval(timeInterval);
PollServer();
}
}
updateTimer();
var timeInterval = setInterval(updateTimer, 1000);
}
</script>
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="https://ssl.gstatic.com/docs/script/css/add-ons1.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
</head>
<body>
<div id="mainForm">
<h1>Active Users</h1>
<div class="box">
Active Users Count:
<span id="activeUsersCount">0</span>
</div>
<div class="box">
Active Users:
<span id="activeUsers"></span>
</div>
<div class="box">
Polling in:
<span id="pollingIn"></span>
</div>
<div class="box">
You Are:
<span id="userID"></span>
</div>
</div>
<?!= HtmlService.createHtmlOutputFromFile('javascript').getContent(); ?>
<script>
var userID = <?= userID ?>;
</script>
</body>
</html>
<style>
.box {
display: block;
padding: 0.5em;
}
body {
padding: 1em;
}
</style>

Express REST API response methods are not recognized

I have this really simple get request that returns json that I am trying to implement. I have followed the tutorials for Express Web Framework REST API, but for some reason I keep getting the same error
ERROR:
TypeError: res.status is not a function
or
TypeError: res.json is not a function
index.js:
var express = require('express');
var router = express.Router();
var pg = require('pg');
var connectionString = 'pg://postgres:postgres#postgres/feed';
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/api/leaderboard', function(resp, req){
var results = [];
pg.connect(connectionString, function(err, client, done){
if(err){
done();
console.log(err);
return res.status(500).json({ success: false, data: err});
}
var query = client.query("SELECT * FROM log WHERE (logged >= date_trunc('week', CURRENT_TIMESTAMP - interval '1 week') AND logged <= date_trunc('week', CURRENT_TIMESTAMP));");
var counter = 0;
var b1 = {};
var b2 = {};
var b3 = {};
var b4 = {};
b1.energy_sum_week = 0;
b2.energy_sum_week = 0;
b3.energy_sum_week = 0;
b4.energy_sum_week = 0;
b1.zne_sum_week = 30000;
b2.zne_sum_week = 30000;
b3.zne_sum_week = 30000;
b4.zne_sum_week = 30000;
query.on('row', function(row){
//results.push(row);
if(row['address'] == 215){
b1.energy_sum_week = row['kitchen'] + row['plugload'] + row['lights'] + row['ev'] + row['hvac'] + row['instahot'] - row['solar'];
}
else if (row['address'] == 1590) {
b2.energy_sum_week = row['kitchen'] + row['plugload'] + row['lights'] + row['ev'] + row['hvac'] + row['instahot'] - row['solar'];
} else if (row['address'] == 1605) {
console.log(row);
b3.energy_sum_week = row['kitchen'] + row['plugload'] + row['lights'] + row['ev'] + row['hvac'] + row['instahot'] - row['solar'];
} else if (row['address'] == 1715) {
b4.energy_sum_week = row['kitchen'] + row['plugload'] + row['lights'] + row['ev'] + row['hvac'] + row['instahot'] - row['solar'];
}
});
query.on('end', function(){
done();
//make zne lower than everything
results.push(b1);
results.push(b2);
results.push(b3);
results.push(b4);
resp.json(results);
});
});
});
module.exports = router;
It seems like it can't recognize the response object. Tried a bunch of different things like passing in the request and response's to the query callbacks, and using promises.
Getting kinda desperate here :/
The res variable doesn't exist in the current context, you probably expect that the line
router.get('/api/leaderboard', function(resp, req){
had this form
router.get('/api/leaderboard', function(req, res){
You are passing resp as the req object and the req as the resp object.
Try changing the order.
router.get('/api/leaderboard', function(req, resp){...}

Mongo Connection Exception handling

I am trying to make some exception handling on the following code. Basically I want a MessageBox.Show("ErrorMessage") to show if the connection to the server can't be established.
public List<MongoDBModel> MongoDBModel
{
get
{
string connectionString = "mongodb://127.0.0.1";
var mongoClient = new MongoClient(connectionString);
var mongoServer = mongoClient.GetServer();
var databaseName = "TestPointToPoint";
var db = mongoServer.GetDatabase(databaseName);
var mongodb = db.GetCollection<MongoDBModel>("OCS.MeterEntity");
var mongodbQuery = Query<MongoDBModel>.EQ(x => x._id, MeterUID);
List<MongoDBModel> Cursor = mongodb.FindAs<MongoDBModel>(mongodbQuery).ToList();
return Cursor;
}
}
I have already tryed with
if (mongoServer.State == MongoServerState.Connected)
{
var databaseName = "TestPointToPoint";
var db = mongoServer.GetDatabase(databaseName);
var mongodb = db.GetCollection<MongoDBModel>("OCS.MeterEntity");
var mongodbQuery = Query<MongoDBModel>.EQ(x => x._id, MeterUID);
List<MongoDBModel> Cursor = mongodb.FindAs<MongoDBModel>(mongodbQuery).ToList();
return Cursor;
}
else
{
MessageBox.Show("Connection to MongoDB lost");
return null;
}
but that did not work since the state of the mongoServer first changes to connected in the query.
What should I do to make it work?
I feel stupid now :P
Using a simple try-catch worked.
public List<MongoDBModel> MongoDBModel
{
get
{
string connectionString = "mongodb://127.0.0.1";
var mongoClient = new MongoClient(connectionString);
var mongoServer = mongoClient.GetServer();
var databaseName = "TestPointToPoint";
var db = mongoServer.GetDatabase(databaseName);
var mongodb = db.GetCollection<MongoDBModel>("OCS.MeterEntity");
try
{
var mongodbQuery = Query<MongoDBModel>.EQ(x => x._id, MeterUID);
List<MongoDBModel> Cursor = mongodb.FindAs<MongoDBModel>(mongodbQuery).ToList();
return Cursor;
}
catch (MongoConnectionException e)
{
MessageBox.Show(e.Message);
return null;
}
}
}
Sorry for your troubles.

How can I turn part of my casperjs script into a function so I can use it multiple times

Okay, so here is a part of my casperjs script below which works fine
if(casper.exists(ac1)){
var uel = "https://example.ws/send.html?f=1099817";
this.thenOpen(uel, function() {
casper.wait(10000, function() {
casper.then(function() {
this.evaluate(function() {
var amount = 0.29
var result = amount * 0.019
var result2 = result.toFixed(6);
var fresult = amount - result2;
var needed = fresult.toFixed(3);
document.getElementById('account').value = 'ydfg028';
document.getElementsByName('data')[0].value = needed;
});
this.click("input#sbt.button[type='submit']");
casper.wait(10000, function() {
casper.then(function() {
this.capture("filenadfgmedsfg.jpg");
var el2 = this.getHTML();
fs.write('results23.html', el2, 'w');
});
});
});
});
});
} else {
this.exit();
}
The problem I have is over 14 of the following statements
if(casper.exists()){
So what I am trying to do, is use the casperjs steps as a function. This is what I have tried below, but it just does nothing and casperjs ends when it reaches the function. Here's what I am trying
This is the casperjs function I have made
function casperstep(amount, user, location) {
var uel = "https://example.ws/send.html?f=" + location;
this.thenOpen(uel, function() {
casper.wait(10000, function() {
casper.then(function() {
this.evaluate(function() {
var result = amount * 0.019
var result2 = result.toFixed(6);
var fresult = amount - result2;
var needed = fresult.toFixed(3);
document.getElementById('account').value = user;
document.getElementsByName('data')[0].value = needed;
});
this.click("input#sbt.button[type='submit']");
casper.wait(10000, function() {
casper.then(function() {
this.capture("filenadfgmedsfg.jpg");
var el2 = this.getHTML();
fs.write('results23.html', el2, 'w');
});
});
});
});
});
}
Then when I try the following
if(casper.exists(ac1)){
casperstep(0.29, "username", "3245324");
}
it just does not work at all. The casper steps just do not fire. How can I fix this in theory? It should have worked.
What I have been trying with your answers...
My function
casper.captchaget = function (selector) {
var Loc = this.getHTML(selector, true).match(/src="(.*?)"/)[1];
var Ilocation = 'https://perfectmoney.is' + Loc;
var image = Loc;
var imagesplit = image.split ('?');
var split1 = imagesplit[1];
var string = split1 + ".jpg";
this.download(Ilocation, string);
}
and how I am trying to use it
casper.then(function(){
this.captchaget('img#cpt_img');//this.casperstep(0.29, "username", "3245324");
});
I tried the above to test out using casper extension.
Well, you want to add your own method to a casper object instance : http://casperjs.readthedocs.org/en/latest/extending.html
so :
casper.casperstep = function (amount, user, location) {
{your instructions....}
}
Then call it :
casper.start();
casper.then(function(){
if(casper.exists(ac1)){
casper.casperstep(0.29, "username", "3245324");//this.casperstep(0.29, "username", "3245324");
}
})
.run(function() {
test.done();
});
Old-monkey patching :)
To see other ways to do it : Custom casperjs modules

Implementing Login Using JSON in Titanium

I hope someone will help me.
I have an API which is implemented with JSON web-services. I want to implement Login. A user is created and I need to have login the user. That is when I enter username and password it must log the user in .
I have read the tutsplus tutorial, but I am unable to authenticate the user. Can anyone help me out.
Here is the code I am using:
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
var win1 = Titanium.UI.createWindow({
title:'Login',
backgroundColor:'#fff'
});
var username = Ti.UI.createTextField({
top:'10%',
borderRadius:3,
hintText:'username',
keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
width:'80%',
height:'auto',
left:'10%',
right:'10%',
touchEnabled: true,
});
win1.add(username);
var pass = Ti.UI.createTextField({
top:'30%',
borderRadius:3,
hintText:'password',
keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
width:'80%',
height:'auto',
left:'10%',
right:'10%',
touchEnabled: true,
passwordMask: true
});
win1.add(pass);
var loginBtn = Titanium.UI.createButton({
title:'Login',
top:'50%',
width:'60%',
height:'15%',
borderRadius:1,
font:{fontFamily:'Arial',fontWeight:'bold',fontSize:14}
});
win1.add(loginBtn);
var url = 'http://qudova.com/api.php?function=AuthenticateUser&u=ns.nadeem.m#gmail.com&p=qudovatest';
var json;
var loginReq = Titanium.Network.createHTTPClient();
loginBtn.addEventListener('click',function(e)
{
if (username.value != '' && pass.value != '')
{
// Here I will get the Token (asdfasdf....)
loginReq.open("GET",url);
authstr = 'Basic ' +Titanium.Utils.base64encode(username.value +':' +pass.value);
loginReq.setRequestHeader('Authorization', authstr);
loginReq.send();
}
else
{
alert("Username/Password are required");
}
});
loginReq.onload = function()
{
var jsonObject = JSON.parse(this.responseText);
// Here I have made a check if the Token is returned successfully it will alert the user that he authenticated
if (jsonObject.Token == "asdfadsfasdfadsf")
{
alert("Authenticated");
}
else
{
alert("response.message");
}
};
win1.open();
Thanks in Advance. Is my concept clear ?
You get a JSON array as response. So you should access jsonObject[0].Token.
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
var win1 = Titanium.UI.createWindow({
title:'Login',
backgroundColor:'#fff'
});
var username = Ti.UI.createTextField({
top:'10%',
borderRadius:3,
hintText:'username',
keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
width:'80%',
height:'auto',
left:'10%',
right:'10%',
touchEnabled: true,
});
win1.add(username);
var pass = Ti.UI.createTextField({
top:'30%',
borderRadius:3,
hintText:'password',
keyboardType:Titanium.UI.KEYBOARD_DEFAULT,
width:'80%',
height:'auto',
left:'10%',
right:'10%',
touchEnabled: true,
passwordMask: true
});
win1.add(pass);
var loginBtn = Titanium.UI.createButton({
title:'Login',
top:'50%',
width:'60%',
height:'15%',
borderRadius:1,
font:{fontFamily:'Arial',fontWeight:'bold',fontSize:14}
});
win1.add(loginBtn);
var url = 'http://qudova.com/api.php?function=AuthenticateUser&u=ns.nadeem.m#gmail.com&p=qudovatest';
var json;
var loginReq = Titanium.Network.createHTTPClient();
loginBtn.addEventListener('click',function(e)
{
if (username.value != '' && pass.value != '')
{
// Here I will get the Token (asdfasdf....)
loginReq.open("GET",url);
authstr = 'Basic ' +Titanium.Utils.base64encode(username.value +':' +pass.value);
loginReq.setRequestHeader('Authorization', authstr);
loginReq.send();
}
else
{
alert("Username/Password are required");
}
});
loginReq.onload = function()
{
var jsonObject = JSON.parse(this.responseText);
// Here I have made a check if the Token is returned successfully it will alert the user that he authenticated
if (jsonObject[0].Token === "asdfadsfasdfadsf")
{
alert("Authenticated");
}
else
{
alert("response.message");
}
};
win1.open();
Alternatively you can change your backend implementation, that the result will be an object instead of an array.
Nevertheless you should change your backend because at the moment it's possible to authenticate via plain GET parameters.