From a8b7171472938a002bdb5b02d94e79ad052d32bd Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 14:48:53 +0200 Subject: [PATCH 01/10] v0.21.0 - Baisc twitter login strategy (existing account only) --- app.js | 37 +++++++++++---------------- lib/mysql/index.js | 1 - middleware/loginCheck.js | 8 +++++- package.json | 10 +++++--- routes/auth/index.js | 11 +++++++++ routes/auth/login/index.js | 13 ++++++++++ routes/auth/twitter/index.js | 48 ++++++++++++++++++++++++++++++++++++ routes/chat/index.js | 13 ++++++++++ routes/index.js | 11 +++++++++ views/pages/login.ejs | 1 + 10 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 routes/auth/index.js create mode 100644 routes/auth/login/index.js create mode 100644 routes/auth/twitter/index.js create mode 100644 routes/chat/index.js diff --git a/app.js b/app.js index 2dc8e9c..0336585 100644 --- a/app.js +++ b/app.js @@ -1,18 +1,18 @@ // Requires var favicon = require('serve-favicon'); var s = require("underscore.string"); +var session = require('cookie-session'); var readline = require('readline'); +var passport = require("passport"); var express = require('express'); var sockjs = require('sockjs'); var https = require('https'); var chalk = require('chalk'); -var path = require('path'); var fs = require('fs'); //Library Wrappers -var pack = require("./package.json"); +var config = require('./lib/config/'); var logger = require('./lib/logger/'); -var mysql = require('./lib/mysql/'); //Middleware var loginCheck = require('./middleware/loginCheck.js'); @@ -24,13 +24,11 @@ var routes = require('./routes/index.js'); var app = express(); // Variables -var config = { - log: true, - readline: false, //This is breaking on some machines, also to be deprecated with express routes. - ipadr: '127.0.0.1' || 'localhost', - port: 3000, - ssl: false -}; +config.log = true; +config.readline = false; //This is breaking on some machines, also to be deprecated with express routes. +config.ipadr = '127.0.0.1' || 'localhost'; +config.port = 3000; +config.ssl = false; var logInfo = chalk.bold.blue('[Info] '); var logStop = chalk.bold.red.dim('[Stop] '); @@ -71,26 +69,19 @@ if(config.readline) { // Express -//app.use(logger.express); +app.set('trust proxy', 1); +app.use(session({keys: [config.express.key1, config.express.key2]})); +app.use(passport.initialize()); +app.use(logger.express); app.set('view engine', 'ejs'); app.use(favicon(__dirname + '/public/img/favicon.png')); +app.use(express.static(__dirname + '/public')); //Login Check app.use(loginCheck); -/* -Sets up res.locals.user object to be used. -res.locals.user.logged_in contains boolean for logged_in user. -*/ //Routes -app.use('/chat', express.static(__dirname + '/public')); -app.get('/chat', function (req, res) { - res.render('pages/index', {version:pack.version}); -}); - -app.use('/', function(req, res, next){ - res.redirect('/chat'); //Temp redirect pre-login -}); +app.use(routes); // Connections diff --git a/lib/mysql/index.js b/lib/mysql/index.js index 3476c36..f4b8712 100644 --- a/lib/mysql/index.js +++ b/lib/mysql/index.js @@ -1,6 +1,5 @@ var mysql = require('mysql'); var config = require('../../config/mysql.json'); -var logger = require('jethro'); var connection = mysql.createConnection({ host : config.host, diff --git a/middleware/loginCheck.js b/middleware/loginCheck.js index 070a9ea..f3dcf38 100644 --- a/middleware/loginCheck.js +++ b/middleware/loginCheck.js @@ -1,5 +1,11 @@ var cookie = require('cookie'); module.exports = function(req, res, next){ - console.log(req); + if (typeof req.session.user !== "undefined"){ + res.locals.user = req.session.user; + res.locals.user.logged_in = true; + } else { + res.locals.user = {}; + res.locals.user.logged_in = false; + } next(); }; \ No newline at end of file diff --git a/package.json b/package.json index fb0bb64..a52e109 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.20.31", + "version": "0.21.0", "private": true, "scripts": { "start": "node app.js" @@ -8,19 +8,21 @@ "dependencies": { "bcryptjs": "^2.1.0", "body-parser": "~1.12.0", + "chalk": "~1.0.0", "cookie": "^0.1.2", "cookie-parser": "~1.3.4", + "cookie-session": "^1.1.0", "debug": "~2.1.1", "ejs": "~2.3.1", "express": "~4.12.2", "jade": "~1.9.2", "jethro": "^1.2.7", - "jsonwebtoken": "^4.2.2", "mysql": "^2.6.0", + "passport": "^0.2.1", + "passport-twitter": "^1.0.3", "readline": "0.0.7", "serve-favicon": "~2.2.0", "sockjs": "~0.3.15", - "chalk": "~1.0.0", "underscore.string": "~3.0.3" } -} \ No newline at end of file +} diff --git a/routes/auth/index.js b/routes/auth/index.js new file mode 100644 index 0000000..a4aef3d --- /dev/null +++ b/routes/auth/index.js @@ -0,0 +1,11 @@ +var express = require('express'); +var router = express.Router(); + +//Routes +var login = require('./login/'); +var twitter = require('./twitter/'); + +router.use("/login", login); +router.use('/twitter', twitter); + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/login/index.js b/routes/auth/login/index.js new file mode 100644 index 0000000..973af16 --- /dev/null +++ b/routes/auth/login/index.js @@ -0,0 +1,13 @@ +var express = require('express'); +var router = express.Router(); + +router.get('/',function(req, res, next){ + if (res.locals.user.logged_in === true){ + res.redirect("/chat"); + } else { + res.render("pages/login"); + } +}); + + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/twitter/index.js b/routes/auth/twitter/index.js new file mode 100644 index 0000000..42a2628 --- /dev/null +++ b/routes/auth/twitter/index.js @@ -0,0 +1,48 @@ +var express = require('express'); +var router = express.Router(); +var passport = require("passport"); +var TwitterStrategy = require('passport-twitter').Strategy; +var config = require('../../../lib/config/'); +var mysql = require('../../../lib/mysql'); + +passport.use(new TwitterStrategy({ + consumerKey: config.twitter.TWITTER_CONSUMER_KEY, + consumerSecret: config.twitter.TWITTER_CONSUMER_SECRET, + callbackURL: "http://localhost:3000/auth/twitter/callback", + session: false + }, + function(token, tokenSecret, profile, done) { + console.log(profile); + var q = "SELECT * FROM users WHERE token = '" + token + "'"; + console.log(q); + mysql.query(q, function(err, result){ + if (!err){ + if (result.length > 0){ + console.log("found user"); + if (result[0].tokenSecret === tokenSecret){ + done(null, result[0]); + } + } else { + console.log("not found"); + done("Not found"); + } + } else { + throw err; + } + }); + }) +); + +router.get('/', passport.authenticate('twitter')); +router.get('/callback', + passport.authenticate('twitter', { + session: false + }), + function(req, res) { + req.session.user = req.user; + console.log(req.session.user); + res.redirect("/chat"); + } +); + +module.exports = router; \ No newline at end of file diff --git a/routes/chat/index.js b/routes/chat/index.js new file mode 100644 index 0000000..095e801 --- /dev/null +++ b/routes/chat/index.js @@ -0,0 +1,13 @@ +var express = require('express'); +var router = express.Router(); +var pack = require('../../package.json'); + +router.use('/', function (req, res) { + if (res.locals.user.logged_in === true) { + res.render('pages/index', {version: pack.version}); + } else { + res.redirect("/auth/login"); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index e69de29..0022a23 100644 --- a/routes/index.js +++ b/routes/index.js @@ -0,0 +1,11 @@ +var express = require('express'); +var router = express.Router(); + +//Routes +var auth = require('./auth'); +var chat = require('./chat'); + +router.use("/auth", auth); +router.use("/chat", chat); + +module.exports = router; diff --git a/views/pages/login.ejs b/views/pages/login.ejs index e69de29..d70d8d8 100644 --- a/views/pages/login.ejs +++ b/views/pages/login.ejs @@ -0,0 +1 @@ +Sign in with Twitter \ No newline at end of file From 99aed57c75aa6ed7526bd2dbe4747524ceda9774 Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 14:53:15 +0200 Subject: [PATCH 02/10] v0.21.1 - Added logout route --- package.json | 2 +- routes/auth/index.js | 2 ++ routes/auth/logout/index.js | 9 +++++++++ routes/auth/twitter/index.js | 1 - 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 routes/auth/logout/index.js diff --git a/package.json b/package.json index a52e109..7f3c3ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.21.0", + "version": "0.21.1", "private": true, "scripts": { "start": "node app.js" diff --git a/routes/auth/index.js b/routes/auth/index.js index a4aef3d..68ed1a3 100644 --- a/routes/auth/index.js +++ b/routes/auth/index.js @@ -4,8 +4,10 @@ var router = express.Router(); //Routes var login = require('./login/'); var twitter = require('./twitter/'); +var logout = require('./logout'); router.use("/login", login); router.use('/twitter', twitter); +router.use("/logout", logout); module.exports = router; \ No newline at end of file diff --git a/routes/auth/logout/index.js b/routes/auth/logout/index.js new file mode 100644 index 0000000..936b26f --- /dev/null +++ b/routes/auth/logout/index.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +router.use("/", function(req, res, next){ + req.session = null; + res.redirect("/auth/login"); +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/auth/twitter/index.js b/routes/auth/twitter/index.js index 42a2628..7f6947b 100644 --- a/routes/auth/twitter/index.js +++ b/routes/auth/twitter/index.js @@ -18,7 +18,6 @@ passport.use(new TwitterStrategy({ mysql.query(q, function(err, result){ if (!err){ if (result.length > 0){ - console.log("found user"); if (result[0].tokenSecret === tokenSecret){ done(null, result[0]); } From d760bdf35d80b015e768f43aab420a7ad3308045 Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 15:00:02 +0200 Subject: [PATCH 03/10] v0.21.2 - Added account creation via twitter --- package.json | 2 +- routes/auth/twitter/index.js | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7f3c3ea..4a4078c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.21.1", + "version": "0.21.2", "private": true, "scripts": { "start": "node app.js" diff --git a/routes/auth/twitter/index.js b/routes/auth/twitter/index.js index 7f6947b..cb9da8c 100644 --- a/routes/auth/twitter/index.js +++ b/routes/auth/twitter/index.js @@ -22,8 +22,23 @@ passport.use(new TwitterStrategy({ done(null, result[0]); } } else { - console.log("not found"); - done("Not found"); + console.log(profile); + var user = { + id: profile.id, + token: token, + tokenSecret: tokenSecret, + name: profile._json.name, + username: profile.username, + location: profile._json.location, + description: profile._json.description + }; + mysql.query("INSERT INTO users SET ?", user, function(err, result){ + if (!err){ + done(null, user); + } else { + throw err; + } + }); } } else { throw err; From 6ff47fc1ad06c997914a9eb3232487696dd5c20f Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 18:18:02 +0200 Subject: [PATCH 04/10] Added documentation for changes --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index f0476a8..5f8bb66 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,39 @@ Clone this repo to your desktop and run `npm install` to install all the depende You might want to look into `app.js` and `public/js/chat.js` to make some adjustments such as changing the socket url to other than localhost, and set up a SSL certificate to work with it. +## Config +Along with version 0.21.0 and up, additional config files are required. + +These allow for furthered environment settings, controlled from within /lib/config/index.js + +The config module loads files from within /config/*, these are detailed below: + +##### mysql.json +``` +{ + "username":"", + "password":"", + "database":"", + "host":"" +} +``` +The credentials to connect to your mysql database. + +##### express.json +```{ + "key1":"", + "key2":"" +}``` + +These are the keys that encrypt the user cookie session + +##### twitter.json +```{ + "TWITTER_CONSUMER_KEY":"", + "TWITTER_CONSUMER_SECRET":"" +}``` +The keys in order to be able to use the Twitter oauth2 API. + ## Usage After you clone this repo to your desktop, go to its root directory and run `npm install` to install its dependencies. From 62db274a320cac489a0bf846d2835aa905ebce82 Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 18:20:24 +0200 Subject: [PATCH 05/10] Updated API docs --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5f8bb66..b0faba9 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ These allow for furthered environment settings, controlled from within /lib/conf The config module loads files from within /config/*, these are detailed below: -##### mysql.json +##### config/mysql.json ``` { "username":"", @@ -41,20 +41,22 @@ The config module loads files from within /config/*, these are detailed below: ``` The credentials to connect to your mysql database. -##### express.json +##### config/express.json ```{ "key1":"", "key2":"" }``` -These are the keys that encrypt the user cookie session +These are the keys that encrypt the user cookie session, they should be completely random, and not shared. -##### twitter.json +##### config/twitter.json ```{ "TWITTER_CONSUMER_KEY":"", "TWITTER_CONSUMER_SECRET":"" }``` + The keys in order to be able to use the Twitter oauth2 API. +You can get new keys here: https://apps.twitter.com/ ## Usage After you clone this repo to your desktop, go to its root directory and run `npm install` to install its dependencies. From 5896883da69b9c8412e18c91fca12ad42d388db5 Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Mon, 30 Mar 2015 18:41:35 +0200 Subject: [PATCH 06/10] Fixed git ignore issue, commit config lib --- .gitignore | 7 ++++--- lib/config/index.js | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 lib/config/index.js diff --git a/.gitignore b/.gitignore index 12c624b..1589b76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -.idea/ node_modules/ -config/ -logs/ \ No newline at end of file +.idea/ +config/express.json +config/mysql.json +config/twitter.json diff --git a/lib/config/index.js b/lib/config/index.js new file mode 100644 index 0000000..403172f --- /dev/null +++ b/lib/config/index.js @@ -0,0 +1,10 @@ +var config = {}; +var logger = require('../logger/'); + +config.mysql = require('../../config/mysql.json'); +config.twitter = require('../../config/twitter.json'); +config.express = require('../../config/express.json'); + +logger("info", "Config", "Successfully loaded config files!"); + +module.exports = config; From d8611f023e1bd877718c2d4f3fa1fb277583e52a Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Tue, 31 Mar 2015 02:45:17 +0200 Subject: [PATCH 07/10] v0.21.3 - Added auto input for username --- package.json | 2 +- views/pages/index.ejs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4a4078c..6dc8188 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.21.2", + "version": "0.21.3", "private": true, "scripts": { "start": "node app.js" diff --git a/views/pages/index.ejs b/views/pages/index.ejs index b846ecb..cfa7c91 100644 --- a/views/pages/index.ejs +++ b/views/pages/index.ejs @@ -81,7 +81,12 @@
- + <% var defaultText = user.username + if (typeof user.display_name !== "undefined"){ + defaultText = res.locals.user.display_name; + } + %> + From 0823a04142819fdc7d3e50d97810ec970b92c4fd Mon Sep 17 00:00:00 2001 From: "Sam Mills (Henchman)" Date: Tue, 31 Mar 2015 03:49:53 +0200 Subject: [PATCH 08/10] v0.21.4 - Added jwt support - WARNING: cookie-session deprecation soon! --- README.md | 8 ++++++++ app.js | 11 +++++++++-- config/jwt.json | 3 +++ lib/config/index.js | 1 + middleware/loginCheck.js | 1 + package.json | 3 ++- routes/auth/twitter/index.js | 10 +++++++++- 7 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 config/jwt.json diff --git a/README.md b/README.md index b0faba9..cab58b9 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,14 @@ These are the keys that encrypt the user cookie session, they should be complete "TWITTER_CONSUMER_SECRET":"" }``` +##### config/salt.json +```{ + "salt":"random_string" +}``` + +Salt to encrypt the json web token. + + The keys in order to be able to use the Twitter oauth2 API. You can get new keys here: https://apps.twitter.com/ diff --git a/app.js b/app.js index 0336585..2ce26c0 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,10 @@ // Requires +var session = require('cookie-session'); var favicon = require('serve-favicon'); var s = require("underscore.string"); -var session = require('cookie-session'); var readline = require('readline'); var passport = require("passport"); +var jwt = require("jsonwebtoken"); var express = require('express'); var sockjs = require('sockjs'); var https = require('https'); @@ -92,7 +93,10 @@ var server = app.listen(config.port, config.ipadr, function() { consoleLog(logStart, 'Listening at http://' + host + ':' + port); }); +var util = require('util'); + chat.on('connection', function(conn) { + //console.log(util.inspect(conn)); consoleLog(logSocket, chalk.underline(conn.id) +': connected'); rateLimit[conn.id] = 1; lastTime[conn.id] = Date.now(); @@ -158,7 +162,10 @@ chat.on('connection', function(conn) { }); }); -chat.installHandlers(server, {prefix:'/socket',log:function(){}}); +chat.installHandlers(server, { + prefix:'/socket', + log:function(){} +}); // Util diff --git a/config/jwt.json b/config/jwt.json new file mode 100644 index 0000000..bc4a912 --- /dev/null +++ b/config/jwt.json @@ -0,0 +1,3 @@ +{ + "salt":"uhaisbhdsabf" +} \ No newline at end of file diff --git a/lib/config/index.js b/lib/config/index.js index 403172f..363455c 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -4,6 +4,7 @@ var logger = require('../logger/'); config.mysql = require('../../config/mysql.json'); config.twitter = require('../../config/twitter.json'); config.express = require('../../config/express.json'); +config.jwt = require('../../config/jwt.json'); logger("info", "Config", "Successfully loaded config files!"); diff --git a/middleware/loginCheck.js b/middleware/loginCheck.js index f3dcf38..0286eb6 100644 --- a/middleware/loginCheck.js +++ b/middleware/loginCheck.js @@ -1,5 +1,6 @@ var cookie = require('cookie'); module.exports = function(req, res, next){ + //console.log(req.headers.cookie); if (typeof req.session.user !== "undefined"){ res.locals.user = req.session.user; res.locals.user.logged_in = true; diff --git a/package.json b/package.json index 6dc8188..1aae4ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-chat", - "version": "0.21.3", + "version": "0.21.4", "private": true, "scripts": { "start": "node app.js" @@ -17,6 +17,7 @@ "express": "~4.12.2", "jade": "~1.9.2", "jethro": "^1.2.7", + "jsonwebtoken": "^4.2.2", "mysql": "^2.6.0", "passport": "^0.2.1", "passport-twitter": "^1.0.3", diff --git a/routes/auth/twitter/index.js b/routes/auth/twitter/index.js index cb9da8c..5b8559f 100644 --- a/routes/auth/twitter/index.js +++ b/routes/auth/twitter/index.js @@ -47,6 +47,8 @@ passport.use(new TwitterStrategy({ }) ); +var jwt = require("jsonwebtoken"); + router.get('/', passport.authenticate('twitter')); router.get('/callback', passport.authenticate('twitter', { @@ -54,7 +56,13 @@ router.get('/callback', }), function(req, res) { req.session.user = req.user; - console.log(req.session.user); + var user = req.user; + req.session.token = jwt.sign({ + foo: true, + user: {id: user.id, username: user.username, type:"twitter"}, + date: new Date() + }, config.jwt.salt); + res.cookie('jwt', req.session.token, {httpOnly: true }); res.redirect("/chat"); } ); From 4a4cf63ac2cc6bc27e96cee51d9890d6f3f2dd7e Mon Sep 17 00:00:00 2001 From: Igor Antun Date: Mon, 30 Mar 2015 23:27:11 -0300 Subject: [PATCH 09/10] Made progress with login.ejs --- lib/mysql/index.js | 3 +- public/css/chat.css | 10 +- public/js/chat.js | 591 ------------------------------------------ public/test.ejs | 127 +++++++++ views/pages/login.ejs | 119 ++++++++- 5 files changed, 255 insertions(+), 595 deletions(-) delete mode 100644 public/js/chat.js create mode 100644 public/test.ejs diff --git a/lib/mysql/index.js b/lib/mysql/index.js index f4b8712..077041e 100644 --- a/lib/mysql/index.js +++ b/lib/mysql/index.js @@ -5,7 +5,8 @@ var connection = mysql.createConnection({ host : config.host, user : config.username, password : config.password, - database : config.database + database : config.database, + insecureAuth: true }); connection.connect(); diff --git a/public/css/chat.css b/public/css/chat.css index 0e08970..deee5f9 100644 --- a/public/css/chat.css +++ b/public/css/chat.css @@ -1,7 +1,13 @@ #panel { - height: 300px; + height: 45vh; overflow: auto; - max-height: 300px; + max-height: 45vh; +} + +#users-panel { + height: 55vh; + overflow: auto; + max-height: 55vh; } #emoji, #sound, #desktop, #greentext, #synthesis, #recognition { diff --git a/public/js/chat.js b/public/js/chat.js deleted file mode 100644 index 1a3c577..0000000 --- a/public/js/chat.js +++ /dev/null @@ -1,591 +0,0 @@ -// Variables -var user, - timer, - socket, - oldname, - username, - typeTimer, - clients = [], - usersTyping = [], - nmr = 0, - dev = true, - unread = 0, - focus = true, - typing = false, - connected = false, - version = VERSION, - blop = new Audio('sounds/blop.wav'); - -emojione.ascii = true; -emojione.imageType = 'png'; -emojione.unicodeAlt = false; -document.getElementById('version').innerHTML = version; - -var regex = /(‍| )/g; - -var settings = { - 'name': null, - 'emoji': true, - 'greentext': true, - 'sound': true, - 'desktop': false, - 'synthesis': false, - 'recognition': false -} - - -// Connection -var connect = function() { - socket = new WebSocket('ws://localhost:3000/socket/websocket'); - - socket.onopen = function() { - var ping = setInterval(function(){ - socket.send(JSON.stringify({type: 'ping'})); - }, 50 * 1000); - console.info('Connection established.'); - updateInfo(); - }; - - socket.onclose = function() { - clearTimeout(typeTimer); - $('#admin').hide(); - typing = false; - clients = []; - - if(connected) { - updateBar('mdi-action-autorenew spin', 'Connection lost, reconnecting...', true); - - timer = setTimeout(function() { - console.warn('Connection lost, reconnecting...'); - connect(); - }, 1500); - } - }; - - socket.onmessage = function(e) { - var data = JSON.parse(e.data); - if(dev) console.log(data); - - if(data.type == 'delete') - return $('div[data-mid="' + data.message + '"]').remove(); - - if(data.type == 'typing') { - var string; - if(data.user != username) { - if(data.typing) - usersTyping.push(data.user); - else - usersTyping.splice(usersTyping.indexOf(data.user), 1); - } - - - if(usersTyping.length == 1) { - string = usersTyping + ' is writing...'; - } else if(usersTyping.length > 4) { - string = 'Several people are writing...'; - } else if(usersTyping.length > 1) { - var lastUser = usersTyping.pop(); - string = usersTyping.join(', ') + ' and ' + lastUser + ' are writing...'; - usersTyping.push(lastUser); - } else { - string = '
'; - } - - return document.getElementById('typing').innerHTML = string; - } - - if(data.type == 'server') { - switch(data.info) { - case 'rejected': - var message; - if(data.reason == 'length') message = 'Your username must have at least 3 characters and no more than 16 characters'; - if(data.reason == 'format') message = 'Your username must only contain alphanumeric characters (numbers, letters and underscores)'; - if(data.reason == 'taken') message = 'This username is already taken'; - if(data.reason == 'banned') message = 'You have been banned from the server. You have to wait until you get unbanned to be able to connect again'; - showChat('light', null, message); - - if(!data.keep) { - username = undefined; - connected = false; - } else { - username = oldname; - } - break; - - case 'success': - document.getElementById('send').childNodes[0].nodeValue = 'Send'; - updateBar('mdi-content-send', 'Enter your message here', false); - connected = true; - settings.name = username; - localStorage.settings = JSON.stringify(settings); - break; - - case 'update': - showChat('info', null, data.user.oldun + ' changed its name to ' + data.user.un); - clients[data.user.id] = data.user; - break; - - case 'connection': - showChat('info', null, data.user.un + ' connected to the server'); - clients[data.user.id] = data.user; - document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; - break; - - case 'disconnection': - if(data.user.un != null) - showChat('info', null, data.user.un + ' disconnected from the server'); - delete clients[data.user.id]; - document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; - break; - - case 'spam': - showChat('light', null, 'You have to wait 1 second between messages'); - break; - - case 'clients': - clients = data.clients; - document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; - break; - - case 'user': - user = data.client.id; - break; - } - } else if((data.type == 'kick' || data.type == 'ban') && data.extra == username) { - location.reload() - } else { - if(data.message.indexOf('@' + username) > -1) - data.type = 'mention'; - - if(settings.synthesis) { - textToSpeech.text = data.message; - speechSynthesis.speak(textToSpeech); - } - - showChat(data.type, data.user, data.message, data.subtxt, data.mid); - } - - if(data.type == 'role') { - if(getUserByName(data.extra) != undefined) { - if(data.extra == username && data.role > 0) { - $('#admin').show(); - $('#menu-admin').show(); - } - - if(data.extra == username && data.role == 0) { - $('#admin').hide(); - $('#menu-admin').hide(); - } - - clients[getUserByName(data.extra).id].role = data.role; - } - } - - if(data.type == 'global' || data.type == 'pm' || data.type == 'mention') { - if(!focus) { - unread++; - document.title = '(' + unread + ') Node.JS Chat'; - if(settings.sound) - blop.play(); - if(settings.desktop) - desktopNotif(data.user + ': ' + data.message); - } - } - } -}; - -function sendSocket(value, method, other, txt) { - socket.send(JSON.stringify({ - type: method, - message: value, - subtxt: txt, - extra: other - })); -} - -function updateInfo() { - socket.send(JSON.stringify({ - user: username, - type: 'update' - })); -} - - -// Utilities -function getUserByName(name) { - for(client in clients) - if(clients[client].un == name) - return clients[client]; -} - -function updateBar(icon, placeholder, disable) { - document.getElementById('icon').className = 'mdi ' + icon; - $('#message').attr('placeholder', placeholder); - $('#message').prop('disabled', disable); - $('#send').prop('disabled', disable); -} - -function showChat(type, user, message, subtxt, mid) { - if(type == 'global' || type == 'kick' || type == 'ban' || type == 'info' || type == 'light' || type == 'help' || type == 'role') user = 'System'; - if(type == 'me' || type == 'em') type = 'emote'; - if(!mid) mid == 'system'; - - var nameclass = ''; - if(type == 'emote' || type == 'message') { - if(user == username && getUserByName(user).role == 0) nameclass = 'self'; - else { - if(getUserByName(user).role == 1) nameclass = 'helper'; - if(getUserByName(user).role == 2) nameclass = 'moderator'; - if(getUserByName(user).role == 3) nameclass = 'administrator'; - } - } - - if(!subtxt) - $('#panel').append('
' + user + 'DELETE' + getTime() + '' + message + '
'); - else - $('#panel').append('
' + user + '(' + subtxt + ') ' + getTime() + '' + message + '
'); - - $('#panel').animate({scrollTop: $('#panel').prop('scrollHeight')}, 500); - updateStyle(); - nmr++; -} - -function handleInput() { - var value = $('#message').val().replace(regex, ' ').trim(); - - if(value.length > 0) { - if(username === undefined) { - username = value; - connect(); - } else if(value.charAt(0) == '/') { - var command = value.substring(1).split(' '); - - switch(command[0].toLowerCase()) { - case 'pm': case 'msg': case 'role': case 'kick': case 'ban': case 'name': case 'alert': case 'me': case 'em': - if(value.substring(command[0].length).length > 1) { - if((command[0] == 'pm' || command[0] == 'msg') && value.substring(command[0].concat(command[1]).length).length > 2) - sendSocket(value.substring(command[0].concat(command[1]).length + 2), 'pm', command[1], 'PM'); - else if(command[0] == 'pm' || command[0] == 'msg') - showChat('light', 'Error', 'Use /' + command[0] + ' [user] [message]'); - - if(command[0] == 'ban' && value.substring(command[0].concat(command[1]).length).length > 2) - sendSocket(command[1], 'ban', command[2]); - else if(command[0] == 'ban') - showChat('light', 'Error', 'Use /ban [user] [minutes]'); - - if(command[0] == 'alert') - sendSocket(value.substring(command[0].length + 2), 'global', null, username); - - if((command[0] == 'role') && value.substring(command[0].concat(command[1]).length).length > 3) - sendSocket(command[1], 'role', value.substring(command[0].concat(command[1]).length + 3)); - else if(command[0] == 'role') - showChat('light', 'Error', 'Use /' + command[0] + ' [user] [0-3]'); - - if(command[0] == 'kick' || command[0] == 'me' || command[0] == 'em') - sendSocket(value.substring(command[0].length + 2), command[0]); - - if(command[0] == 'name') { - oldname = username; - username = value.substring(command[0].length + 2); - updateInfo(); - } - } else { - var variables; - if(command[0] == 'alert' || command[0] == 'me' || command[0] == 'em') - variables = ' [message]'; - if(command[0] == 'role') - variables = ' [user] [0-3]'; - if(command[0] == 'ban') - variables = ' [user] [minutes]'; - if(command[0] == 'pm') - variables = ' [user] [message]'; - if(command[0] == 'kick') - variables = ' [user]'; - if(command[0] == 'name') - variables = ' [name]'; - - showChat('light', 'Error', 'Use /' + command[0] + variables); - } - break; - - case 'clear': - nmr = 0; - document.getElementById('panel').innerHTML = ''; - showChat('light', 'System', 'Messages cleared'); - break; - - case 'shrug': - sendSocket(value.substring(6) + ' ¯\\_(ツ)_/¯', 'message'); - break; - - case 'help': - $('#help-dialog').modal('show'); - $('#message').val(''); - break; - - case 'reconnect': - socket.close(); - break; - - default: - showChat('light', 'Error', 'Unknown command, use /help to get a list of the available commands'); - break; - } - } else { - sendSocket(value, 'message'); - } - - $('#message').val(''); - } -} - -function getTime() { - var now = new Date(), - time = [now.getHours(), now.getMinutes(), now.getSeconds()]; - - for(var i = 0; i < 3; i++) { - if(time[i] < 10) - time[i] = '0' + time[i]; - } - - return time.join(':'); -} - -function updateStyle() { - $('#panel').linkify(); - var element = document.getElementsByClassName('msg')[nmr]; - - if(element.innerHTML != undefined) { - if(settings.greentext && element.innerHTML.indexOf('>') == 0) - element.style.color = '#689f38'; - - if(settings.emoji) { - var input = element.innerHTML; - var output = emojione.shortnameToImage(element.innerHTML); - element.innerHTML = output; - } - } -} - - -// Triggers -$(document).ready(function() { - $('#user').bind('click', function() { - var content = '', - admin; - - for(var i in clients) { - if(clients[i] != undefined) { - if(clients[i].role == 0) admin = '' - if(clients[i].role == 1) admin = ' - Helper'; - if(clients[i].role == 2) admin = ' - Moderator'; - if(clients[i].role == 3) admin = ' - Administrator'; - content += '
  • ID: ' + clients[i].id + ' - Name: ' + clients[i].un + admin; - } - } - - document.getElementById('users-content').innerHTML = content; - $('#users-dialog').modal('show'); - }); - - $('#panel').on('mouseenter', '.message', function() { - if(clients[user].role > 0) { - $(this).find('span:eq(1)').show(); - $(this).find('span:eq(2)').hide(); - } - }); - - $('#panel').on('mouseleave', '.message',function() { - if(clients[user].role > 0) { - $(this).find('span:eq(1)').hide(); - $(this).find('span:eq(2)').show(); - } - }); - - $('#panel').on('mouseenter', '.emote', function() { - if(clients[user].role > 0) { - $(this).find('span:eq(1)').show(); - $(this).find('span:eq(2)').hide(); - } - }); - - $('#panel').on('mouseleave', '.emote', function() { - if(clients[user].role > 0) { - $(this).find('span:eq(1)').hide(); - $(this).find('span:eq(2)').show(); - } - }); - - $('#panel').on('click', '.delete', function(e) { - var value = $(this)[0].parentElement.attributes[0].value; - sendSocket(value, 'delete'); - }); - - $('#panel').on('click', '.name', function(e) { - $('#message').val('@' + $(this)[0].children[0].children[0].innerHTML + ' '); - $('#message').focus(); - }); - - $('#send').bind('click', function() { - handleInput(); - }); - - $('#menu-admin').bind('click', function() { - $('#admin-help-dialog').modal('show'); - }); - - $('#help').bind('click', function() { - $('#help-dialog').modal('show'); - }); - - $('#options').bind('click', function() { - $('#options-dialog').modal('show'); - }); - - $('#menu-options').bind('click', function() { - $('#options-dialog').modal('show'); - }); - - $('#audio').bind('click', function() { - speechToText.start(); - updateBar('mdi-av-mic', 'Start speaking', true); - }); - - $('#emoji').bind('change', function() { - settings.emoji = document.getElementById('emoji').checked; - localStorage.settings = JSON.stringify(settings); - }); - - $('#greentext').bind('change', function() { - settings.greentext = document.getElementById('greentext').checked; - localStorage.settings = JSON.stringify(settings); - }); - - $('#sound').bind('change', function() { - settings.sound = document.getElementById('sound').checked; - localStorage.settings = JSON.stringify(settings); - }); - - $('#synthesis').bind('change', function() { - settings.synthesis = document.getElementById('synthesis').checked; - localStorage.settings = JSON.stringify(settings); - }); - - $('#desktop').bind('change', function() { - settings.desktop = document.getElementById('desktop').checked; - localStorage.settings = JSON.stringify(settings); - - if(Notification.permission !== 'granted') - Notification.requestPermission(); - }); - - $('#recognition').bind('change', function() { - settings.recognition = document.getElementById('recognition').checked; - localStorage.settings = JSON.stringify(settings); - - if(settings.recognition) - $('#audio').show(); - else { - $('#audio').hide(); - } - }); - - $('#message').keypress(function(e) { - if(e.which == 13) { - if(connected && typing) { - typing = false; - clearTimeout(typeTimer); - socket.send(JSON.stringify({type:'typing', typing:false})); - } - handleInput(); - } else if(connected) { - if(!typing) { - typing = true; - socket.send(JSON.stringify({type:'typing', typing:true})); - } - - clearTimeout(typeTimer); - typeTimer = setTimeout(function() { - typing = false; - socket.send(JSON.stringify({type:'typing', typing:false})); - }, 2000); - } - }); -}); - - -// Intern -if(Notification) { - $('#toggle-desktop').show(); -} - -if('speechSynthesis' in window) { - $('#toggle-synthesis').show(); - textToSpeech = new SpeechSynthesisUtterance(); - textToSpeech.lang = 'en'; -} - -if('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { - $('#toggle-recognition').show(); - var speechToText = new webkitSpeechRecognition(); - speechToText.interimResults = true; - speechToText.continuous = true; - speechToText.lang = 'en-US'; -} - -speechToText.onresult = function(event) { - $('#message').val(''); - - for (var i = event.resultIndex; i < event.results.length; ++i) { - if (event.results[i].isFinal) { - $('#message').val(event.results[i][0].transcript); - updateBar('mdi-content-send', 'Enter your message here', false); - speechToText.stop(); - handleInput(); - } else { - var oldval = $('#message').val(); - $('#message').val(oldval + event.results[i][0].transcript); - } - } -} - -speechToText.onerror = function(event) { - updateBar('mdi-content-send', 'Enter your message here', false); -} - -function desktopNotif(message) { - if(!Notification) - return; - - var notification = new Notification('You\'ve got a new message', { - icon: 'http://i.imgur.com/ehB0QcM.png', - body: message - }); -} - -if(typeof(Storage) !== 'undefined') { - if(!localStorage.settings) { - localStorage.settings = JSON.stringify(settings); - } else { - settings = JSON.parse(localStorage.settings); - document.getElementById('emoji').checked = settings.emoji; - document.getElementById('greentext').checked = settings.greentext; - document.getElementById('sound').checked = settings.sound; - document.getElementById('desktop').checked = settings.desktop; - document.getElementById('synthesis').checked = settings.synthesis; - document.getElementById('recognition').checked = settings.recognition; - - if(settings.recognition) - $('#audio').show(); - } -} - -window.onfocus = function() { - document.title = 'Node.JS Chat'; - focus = true; - unread = 0; -}; - -window.onblur = function() { - focus = false; -}; \ No newline at end of file diff --git a/public/test.ejs b/public/test.ejs new file mode 100644 index 0000000..998575c --- /dev/null +++ b/public/test.ejs @@ -0,0 +1,127 @@ + + + + + + + + + + + + Node.JS Chat- Login + + + + + + + + + + + + + + +
    + Fork me on GitHub + +
    +

    +
    + + +
    +
    +
    +
    +
    +

    Sign in

    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Created by Igor Antun

    +

    + +

    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/views/pages/login.ejs b/views/pages/login.ejs index d70d8d8..82026a9 100644 --- a/views/pages/login.ejs +++ b/views/pages/login.ejs @@ -1 +1,118 @@ -Sign in with Twitter \ No newline at end of file + + + + + + + + + + + + Node.JS Chat- Login + + + + + + + + + + +
    + Fork me on GitHub + +
    +

    + +
    + + +
    +
    +
    +

    Sign in

    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +

    Created by Igor Antun

    +

    + +

    +
    +
    +
    +
    +
    +
    + + + + + + + + + + \ No newline at end of file From 1c47efd2cc516e706d67252c0d7e8ccee7bae564 Mon Sep 17 00:00:00 2001 From: Igor Antun Date: Mon, 30 Mar 2015 23:31:52 -0300 Subject: [PATCH 10/10] Fix my shit --- public/js/chat.js | 591 ++++++++++++++++++++++++++++++++++++++++++++++ public/test.ejs | 127 ---------- 2 files changed, 591 insertions(+), 127 deletions(-) create mode 100644 public/js/chat.js delete mode 100644 public/test.ejs diff --git a/public/js/chat.js b/public/js/chat.js new file mode 100644 index 0000000..1a3c577 --- /dev/null +++ b/public/js/chat.js @@ -0,0 +1,591 @@ +// Variables +var user, + timer, + socket, + oldname, + username, + typeTimer, + clients = [], + usersTyping = [], + nmr = 0, + dev = true, + unread = 0, + focus = true, + typing = false, + connected = false, + version = VERSION, + blop = new Audio('sounds/blop.wav'); + +emojione.ascii = true; +emojione.imageType = 'png'; +emojione.unicodeAlt = false; +document.getElementById('version').innerHTML = version; + +var regex = /(‍| )/g; + +var settings = { + 'name': null, + 'emoji': true, + 'greentext': true, + 'sound': true, + 'desktop': false, + 'synthesis': false, + 'recognition': false +} + + +// Connection +var connect = function() { + socket = new WebSocket('ws://localhost:3000/socket/websocket'); + + socket.onopen = function() { + var ping = setInterval(function(){ + socket.send(JSON.stringify({type: 'ping'})); + }, 50 * 1000); + console.info('Connection established.'); + updateInfo(); + }; + + socket.onclose = function() { + clearTimeout(typeTimer); + $('#admin').hide(); + typing = false; + clients = []; + + if(connected) { + updateBar('mdi-action-autorenew spin', 'Connection lost, reconnecting...', true); + + timer = setTimeout(function() { + console.warn('Connection lost, reconnecting...'); + connect(); + }, 1500); + } + }; + + socket.onmessage = function(e) { + var data = JSON.parse(e.data); + if(dev) console.log(data); + + if(data.type == 'delete') + return $('div[data-mid="' + data.message + '"]').remove(); + + if(data.type == 'typing') { + var string; + if(data.user != username) { + if(data.typing) + usersTyping.push(data.user); + else + usersTyping.splice(usersTyping.indexOf(data.user), 1); + } + + + if(usersTyping.length == 1) { + string = usersTyping + ' is writing...'; + } else if(usersTyping.length > 4) { + string = 'Several people are writing...'; + } else if(usersTyping.length > 1) { + var lastUser = usersTyping.pop(); + string = usersTyping.join(', ') + ' and ' + lastUser + ' are writing...'; + usersTyping.push(lastUser); + } else { + string = '
    '; + } + + return document.getElementById('typing').innerHTML = string; + } + + if(data.type == 'server') { + switch(data.info) { + case 'rejected': + var message; + if(data.reason == 'length') message = 'Your username must have at least 3 characters and no more than 16 characters'; + if(data.reason == 'format') message = 'Your username must only contain alphanumeric characters (numbers, letters and underscores)'; + if(data.reason == 'taken') message = 'This username is already taken'; + if(data.reason == 'banned') message = 'You have been banned from the server. You have to wait until you get unbanned to be able to connect again'; + showChat('light', null, message); + + if(!data.keep) { + username = undefined; + connected = false; + } else { + username = oldname; + } + break; + + case 'success': + document.getElementById('send').childNodes[0].nodeValue = 'Send'; + updateBar('mdi-content-send', 'Enter your message here', false); + connected = true; + settings.name = username; + localStorage.settings = JSON.stringify(settings); + break; + + case 'update': + showChat('info', null, data.user.oldun + ' changed its name to ' + data.user.un); + clients[data.user.id] = data.user; + break; + + case 'connection': + showChat('info', null, data.user.un + ' connected to the server'); + clients[data.user.id] = data.user; + document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; + break; + + case 'disconnection': + if(data.user.un != null) + showChat('info', null, data.user.un + ' disconnected from the server'); + delete clients[data.user.id]; + document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; + break; + + case 'spam': + showChat('light', null, 'You have to wait 1 second between messages'); + break; + + case 'clients': + clients = data.clients; + document.getElementById('users').innerHTML = Object.keys(clients).length + ' USERS'; + break; + + case 'user': + user = data.client.id; + break; + } + } else if((data.type == 'kick' || data.type == 'ban') && data.extra == username) { + location.reload() + } else { + if(data.message.indexOf('@' + username) > -1) + data.type = 'mention'; + + if(settings.synthesis) { + textToSpeech.text = data.message; + speechSynthesis.speak(textToSpeech); + } + + showChat(data.type, data.user, data.message, data.subtxt, data.mid); + } + + if(data.type == 'role') { + if(getUserByName(data.extra) != undefined) { + if(data.extra == username && data.role > 0) { + $('#admin').show(); + $('#menu-admin').show(); + } + + if(data.extra == username && data.role == 0) { + $('#admin').hide(); + $('#menu-admin').hide(); + } + + clients[getUserByName(data.extra).id].role = data.role; + } + } + + if(data.type == 'global' || data.type == 'pm' || data.type == 'mention') { + if(!focus) { + unread++; + document.title = '(' + unread + ') Node.JS Chat'; + if(settings.sound) + blop.play(); + if(settings.desktop) + desktopNotif(data.user + ': ' + data.message); + } + } + } +}; + +function sendSocket(value, method, other, txt) { + socket.send(JSON.stringify({ + type: method, + message: value, + subtxt: txt, + extra: other + })); +} + +function updateInfo() { + socket.send(JSON.stringify({ + user: username, + type: 'update' + })); +} + + +// Utilities +function getUserByName(name) { + for(client in clients) + if(clients[client].un == name) + return clients[client]; +} + +function updateBar(icon, placeholder, disable) { + document.getElementById('icon').className = 'mdi ' + icon; + $('#message').attr('placeholder', placeholder); + $('#message').prop('disabled', disable); + $('#send').prop('disabled', disable); +} + +function showChat(type, user, message, subtxt, mid) { + if(type == 'global' || type == 'kick' || type == 'ban' || type == 'info' || type == 'light' || type == 'help' || type == 'role') user = 'System'; + if(type == 'me' || type == 'em') type = 'emote'; + if(!mid) mid == 'system'; + + var nameclass = ''; + if(type == 'emote' || type == 'message') { + if(user == username && getUserByName(user).role == 0) nameclass = 'self'; + else { + if(getUserByName(user).role == 1) nameclass = 'helper'; + if(getUserByName(user).role == 2) nameclass = 'moderator'; + if(getUserByName(user).role == 3) nameclass = 'administrator'; + } + } + + if(!subtxt) + $('#panel').append('
    ' + user + 'DELETE' + getTime() + '' + message + '
    '); + else + $('#panel').append('
    ' + user + '(' + subtxt + ') ' + getTime() + '' + message + '
    '); + + $('#panel').animate({scrollTop: $('#panel').prop('scrollHeight')}, 500); + updateStyle(); + nmr++; +} + +function handleInput() { + var value = $('#message').val().replace(regex, ' ').trim(); + + if(value.length > 0) { + if(username === undefined) { + username = value; + connect(); + } else if(value.charAt(0) == '/') { + var command = value.substring(1).split(' '); + + switch(command[0].toLowerCase()) { + case 'pm': case 'msg': case 'role': case 'kick': case 'ban': case 'name': case 'alert': case 'me': case 'em': + if(value.substring(command[0].length).length > 1) { + if((command[0] == 'pm' || command[0] == 'msg') && value.substring(command[0].concat(command[1]).length).length > 2) + sendSocket(value.substring(command[0].concat(command[1]).length + 2), 'pm', command[1], 'PM'); + else if(command[0] == 'pm' || command[0] == 'msg') + showChat('light', 'Error', 'Use /' + command[0] + ' [user] [message]'); + + if(command[0] == 'ban' && value.substring(command[0].concat(command[1]).length).length > 2) + sendSocket(command[1], 'ban', command[2]); + else if(command[0] == 'ban') + showChat('light', 'Error', 'Use /ban [user] [minutes]'); + + if(command[0] == 'alert') + sendSocket(value.substring(command[0].length + 2), 'global', null, username); + + if((command[0] == 'role') && value.substring(command[0].concat(command[1]).length).length > 3) + sendSocket(command[1], 'role', value.substring(command[0].concat(command[1]).length + 3)); + else if(command[0] == 'role') + showChat('light', 'Error', 'Use /' + command[0] + ' [user] [0-3]'); + + if(command[0] == 'kick' || command[0] == 'me' || command[0] == 'em') + sendSocket(value.substring(command[0].length + 2), command[0]); + + if(command[0] == 'name') { + oldname = username; + username = value.substring(command[0].length + 2); + updateInfo(); + } + } else { + var variables; + if(command[0] == 'alert' || command[0] == 'me' || command[0] == 'em') + variables = ' [message]'; + if(command[0] == 'role') + variables = ' [user] [0-3]'; + if(command[0] == 'ban') + variables = ' [user] [minutes]'; + if(command[0] == 'pm') + variables = ' [user] [message]'; + if(command[0] == 'kick') + variables = ' [user]'; + if(command[0] == 'name') + variables = ' [name]'; + + showChat('light', 'Error', 'Use /' + command[0] + variables); + } + break; + + case 'clear': + nmr = 0; + document.getElementById('panel').innerHTML = ''; + showChat('light', 'System', 'Messages cleared'); + break; + + case 'shrug': + sendSocket(value.substring(6) + ' ¯\\_(ツ)_/¯', 'message'); + break; + + case 'help': + $('#help-dialog').modal('show'); + $('#message').val(''); + break; + + case 'reconnect': + socket.close(); + break; + + default: + showChat('light', 'Error', 'Unknown command, use /help to get a list of the available commands'); + break; + } + } else { + sendSocket(value, 'message'); + } + + $('#message').val(''); + } +} + +function getTime() { + var now = new Date(), + time = [now.getHours(), now.getMinutes(), now.getSeconds()]; + + for(var i = 0; i < 3; i++) { + if(time[i] < 10) + time[i] = '0' + time[i]; + } + + return time.join(':'); +} + +function updateStyle() { + $('#panel').linkify(); + var element = document.getElementsByClassName('msg')[nmr]; + + if(element.innerHTML != undefined) { + if(settings.greentext && element.innerHTML.indexOf('>') == 0) + element.style.color = '#689f38'; + + if(settings.emoji) { + var input = element.innerHTML; + var output = emojione.shortnameToImage(element.innerHTML); + element.innerHTML = output; + } + } +} + + +// Triggers +$(document).ready(function() { + $('#user').bind('click', function() { + var content = '', + admin; + + for(var i in clients) { + if(clients[i] != undefined) { + if(clients[i].role == 0) admin = '
  • ' + if(clients[i].role == 1) admin = ' - Helper'; + if(clients[i].role == 2) admin = ' - Moderator'; + if(clients[i].role == 3) admin = ' - Administrator'; + content += '
  • ID: ' + clients[i].id + ' - Name: ' + clients[i].un + admin; + } + } + + document.getElementById('users-content').innerHTML = content; + $('#users-dialog').modal('show'); + }); + + $('#panel').on('mouseenter', '.message', function() { + if(clients[user].role > 0) { + $(this).find('span:eq(1)').show(); + $(this).find('span:eq(2)').hide(); + } + }); + + $('#panel').on('mouseleave', '.message',function() { + if(clients[user].role > 0) { + $(this).find('span:eq(1)').hide(); + $(this).find('span:eq(2)').show(); + } + }); + + $('#panel').on('mouseenter', '.emote', function() { + if(clients[user].role > 0) { + $(this).find('span:eq(1)').show(); + $(this).find('span:eq(2)').hide(); + } + }); + + $('#panel').on('mouseleave', '.emote', function() { + if(clients[user].role > 0) { + $(this).find('span:eq(1)').hide(); + $(this).find('span:eq(2)').show(); + } + }); + + $('#panel').on('click', '.delete', function(e) { + var value = $(this)[0].parentElement.attributes[0].value; + sendSocket(value, 'delete'); + }); + + $('#panel').on('click', '.name', function(e) { + $('#message').val('@' + $(this)[0].children[0].children[0].innerHTML + ' '); + $('#message').focus(); + }); + + $('#send').bind('click', function() { + handleInput(); + }); + + $('#menu-admin').bind('click', function() { + $('#admin-help-dialog').modal('show'); + }); + + $('#help').bind('click', function() { + $('#help-dialog').modal('show'); + }); + + $('#options').bind('click', function() { + $('#options-dialog').modal('show'); + }); + + $('#menu-options').bind('click', function() { + $('#options-dialog').modal('show'); + }); + + $('#audio').bind('click', function() { + speechToText.start(); + updateBar('mdi-av-mic', 'Start speaking', true); + }); + + $('#emoji').bind('change', function() { + settings.emoji = document.getElementById('emoji').checked; + localStorage.settings = JSON.stringify(settings); + }); + + $('#greentext').bind('change', function() { + settings.greentext = document.getElementById('greentext').checked; + localStorage.settings = JSON.stringify(settings); + }); + + $('#sound').bind('change', function() { + settings.sound = document.getElementById('sound').checked; + localStorage.settings = JSON.stringify(settings); + }); + + $('#synthesis').bind('change', function() { + settings.synthesis = document.getElementById('synthesis').checked; + localStorage.settings = JSON.stringify(settings); + }); + + $('#desktop').bind('change', function() { + settings.desktop = document.getElementById('desktop').checked; + localStorage.settings = JSON.stringify(settings); + + if(Notification.permission !== 'granted') + Notification.requestPermission(); + }); + + $('#recognition').bind('change', function() { + settings.recognition = document.getElementById('recognition').checked; + localStorage.settings = JSON.stringify(settings); + + if(settings.recognition) + $('#audio').show(); + else { + $('#audio').hide(); + } + }); + + $('#message').keypress(function(e) { + if(e.which == 13) { + if(connected && typing) { + typing = false; + clearTimeout(typeTimer); + socket.send(JSON.stringify({type:'typing', typing:false})); + } + handleInput(); + } else if(connected) { + if(!typing) { + typing = true; + socket.send(JSON.stringify({type:'typing', typing:true})); + } + + clearTimeout(typeTimer); + typeTimer = setTimeout(function() { + typing = false; + socket.send(JSON.stringify({type:'typing', typing:false})); + }, 2000); + } + }); +}); + + +// Intern +if(Notification) { + $('#toggle-desktop').show(); +} + +if('speechSynthesis' in window) { + $('#toggle-synthesis').show(); + textToSpeech = new SpeechSynthesisUtterance(); + textToSpeech.lang = 'en'; +} + +if('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { + $('#toggle-recognition').show(); + var speechToText = new webkitSpeechRecognition(); + speechToText.interimResults = true; + speechToText.continuous = true; + speechToText.lang = 'en-US'; +} + +speechToText.onresult = function(event) { + $('#message').val(''); + + for (var i = event.resultIndex; i < event.results.length; ++i) { + if (event.results[i].isFinal) { + $('#message').val(event.results[i][0].transcript); + updateBar('mdi-content-send', 'Enter your message here', false); + speechToText.stop(); + handleInput(); + } else { + var oldval = $('#message').val(); + $('#message').val(oldval + event.results[i][0].transcript); + } + } +} + +speechToText.onerror = function(event) { + updateBar('mdi-content-send', 'Enter your message here', false); +} + +function desktopNotif(message) { + if(!Notification) + return; + + var notification = new Notification('You\'ve got a new message', { + icon: 'http://i.imgur.com/ehB0QcM.png', + body: message + }); +} + +if(typeof(Storage) !== 'undefined') { + if(!localStorage.settings) { + localStorage.settings = JSON.stringify(settings); + } else { + settings = JSON.parse(localStorage.settings); + document.getElementById('emoji').checked = settings.emoji; + document.getElementById('greentext').checked = settings.greentext; + document.getElementById('sound').checked = settings.sound; + document.getElementById('desktop').checked = settings.desktop; + document.getElementById('synthesis').checked = settings.synthesis; + document.getElementById('recognition').checked = settings.recognition; + + if(settings.recognition) + $('#audio').show(); + } +} + +window.onfocus = function() { + document.title = 'Node.JS Chat'; + focus = true; + unread = 0; +}; + +window.onblur = function() { + focus = false; +}; \ No newline at end of file diff --git a/public/test.ejs b/public/test.ejs deleted file mode 100644 index 998575c..0000000 --- a/public/test.ejs +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - Node.JS Chat- Login - - - - - - - - - - - - - - -
    - Fork me on GitHub - -
    -

    -
    - - -
    -
    -
    -
    -
    -

    Sign in

    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    Created by Igor Antun

    -

    - -

    -
    -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - \ No newline at end of file