diff --git a/.eslintrc.yml b/.eslintrc.yml index 354baa99..de36b033 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -11,27 +11,34 @@ parserOptions: ecmaVersion: 6 rules: + block-scoped-var: 2 block-spacing: [2, always] brace-style: [2, 1tbs] comma-dangle: 0 curly: [2, all] + dot-notation: 2 eqeqeq: 2 + handle-callback-err: 2 indent: [2, tab] key-spacing: [2, {beforeColon: false, afterColon: true}] keyword-spacing: [2, {before: true, after: true}] linebreak-style: [2, unix] no-console: 0 no-control-regex: 0 - no-inner-declarations: 2 - no-invalid-regexp: 2 - no-irregular-whitespace: 2 + no-else-return: 2 + no-implicit-globals: 2 + no-multi-spaces: 2 + no-shadow: 2 + no-template-curly-in-string: 2 no-trailing-spaces: 2 - no-unexpected-multiline: 2 - no-unreachable: 2 + no-unsafe-negation: 2 + no-useless-escape: 2 object-curly-spacing: [2, never] + quote-props: [2, as-needed] quotes: [2, double, avoid-escape] semi: [2, always] space-before-blocks: 2 + space-before-function-paren: [2, never] space-infix-ops: 2 spaced-comment: [2, always] strict: 2 diff --git a/client/js/libs/handlebars/diff.js b/client/js/libs/handlebars/diff.js index 8cc0d135..17f366ab 100644 --- a/client/js/libs/handlebars/diff.js +++ b/client/js/libs/handlebars/diff.js @@ -7,8 +7,8 @@ Handlebars.registerHelper( if (a !== diff) { diff = a; return opt.fn(this); - } else { - return opt.inverse(this); } + + return opt.inverse(this); } ); diff --git a/client/js/libs/handlebars/equal.js b/client/js/libs/handlebars/equal.js index 426f54bd..4d8f34ef 100644 --- a/client/js/libs/handlebars/equal.js +++ b/client/js/libs/handlebars/equal.js @@ -6,8 +6,8 @@ Handlebars.registerHelper( b = b.toString(); if (a === b) { return opt.fn(this); - } else { - return opt.inverse(this); } + + return opt.inverse(this); } ); diff --git a/client/js/libs/handlebars/parse.js b/client/js/libs/handlebars/parse.js index b09086a6..71a45820 100644 --- a/client/js/libs/handlebars/parse.js +++ b/client/js/libs/handlebars/parse.js @@ -33,7 +33,7 @@ function uri(text) { */ function channels(text) { return text.replace( - /(^|\s|\x07|,)((?:#|&)[^\x07\s\,]{1,49})/g, + /(^|\s|\x07|,)((?:#|&)[^\x07\s,]{1,49})/g, '$1$2' ); } @@ -114,10 +114,10 @@ function colors(line) { return; } - result = result.replace(style.keyregex, function(match, text) { + result = result.replace(style.keyregex, function(matchedTrash, matchedText) { return styleTemplate({ - "style": style.style, - "text": text + style: style.style, + text: matchedText }); }); }); diff --git a/client/js/lounge.js b/client/js/lounge.js index 9b0cbaf1..34e55817 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -88,6 +88,7 @@ $(function() { socket.on("auth", function(data) { var login = $("#sign-in"); + var token; login.find(".btn").prop("disabled", false); @@ -99,7 +100,7 @@ $(function() { error.hide(); }); } else { - var token = window.localStorage.getItem("token"); + token = window.localStorage.getItem("token"); if (token) { $("#loading-page-message").text("Authorizing…"); socket.emit("auth", {token: token}); @@ -476,7 +477,7 @@ $(function() { socket.on("names", renderChannelUsers); var userStyles = $("#user-specified-css"); - var settings = $("#settings"); + var highlights = []; var options = $.extend({ coloredNicks: true, desktopNotifications: false, @@ -494,73 +495,75 @@ $(function() { userStyles: userStyles.text(), }, JSON.parse(window.localStorage.getItem("settings"))); - for (var i in options) { - if (i === "userStyles") { - if (!/[\?&]nocss/.test(window.location.search)) { - $(document.head).find("#user-specified-css").html(options[i]); - } - settings.find("#user-specified-css-input").val(options[i]); - } else if (i === "highlights") { - settings.find("input[name=" + i + "]").val(options[i]); - } else if (i === "theme") { - $("#theme").attr("href", "themes/" + options[i] + ".css"); - settings.find("select[name=" + i + "]").val(options[i]); - } else if (options[i]) { - settings.find("input[name=" + i + "]").prop("checked", true); - } - } + (function SettingsScope() { + var settings = $("#settings"); - var highlights = []; - - settings.on("change", "input, select, textarea", function() { - var self = $(this); - var name = self.attr("name"); - - if (self.attr("type") === "checkbox") { - options[name] = self.prop("checked"); - } else { - options[name] = self.val(); - } - - setLocalStorageItem("settings", JSON.stringify(options)); - - if ([ - "join", - "mode", - "motd", - "nick", - "part", - "quit", - "notifyAllMessages", - ].indexOf(name) !== -1) { - chat.toggleClass("hide-" + name, !self.prop("checked")); - } else if (name === "coloredNicks") { - chat.toggleClass("colored-nicks", self.prop("checked")); - } else if (name === "theme") { - $("#theme").attr("href", "themes/" + options[name] + ".css"); - } else if (name === "userStyles") { - $(document.head).find("#user-specified-css").html(options[name]); - } else if (name === "highlights") { - var highlightString = options[name]; - highlights = highlightString.split(",").map(function(h) { - return h.trim(); - }).filter(function(h) { - // Ensure we don't have empty string in the list of highlights - // otherwise, users get notifications for everything - return h !== ""; - }); - } - }).find("input") - .trigger("change"); - - $("#desktopNotifications").on("change", function() { - var self = $(this); - if (self.prop("checked")) { - if (Notification.permission !== "granted") { - Notification.requestPermission(updateDesktopNotificationStatus); + for (var i in options) { + if (i === "userStyles") { + if (!/[\?&]nocss/.test(window.location.search)) { + $(document.head).find("#user-specified-css").html(options[i]); + } + settings.find("#user-specified-css-input").val(options[i]); + } else if (i === "highlights") { + settings.find("input[name=" + i + "]").val(options[i]); + } else if (i === "theme") { + $("#theme").attr("href", "themes/" + options[i] + ".css"); + settings.find("select[name=" + i + "]").val(options[i]); + } else if (options[i]) { + settings.find("input[name=" + i + "]").prop("checked", true); } } - }); + + settings.on("change", "input, select, textarea", function() { + var self = $(this); + var name = self.attr("name"); + + if (self.attr("type") === "checkbox") { + options[name] = self.prop("checked"); + } else { + options[name] = self.val(); + } + + setLocalStorageItem("settings", JSON.stringify(options)); + + if ([ + "join", + "mode", + "motd", + "nick", + "part", + "quit", + "notifyAllMessages", + ].indexOf(name) !== -1) { + chat.toggleClass("hide-" + name, !self.prop("checked")); + } else if (name === "coloredNicks") { + chat.toggleClass("colored-nicks", self.prop("checked")); + } else if (name === "theme") { + $("#theme").attr("href", "themes/" + options[name] + ".css"); + } else if (name === "userStyles") { + userStyles.html(options[name]); + } else if (name === "highlights") { + var highlightString = options[name]; + highlights = highlightString.split(",").map(function(h) { + return h.trim(); + }).filter(function(h) { + // Ensure we don't have empty string in the list of highlights + // otherwise, users get notifications for everything + return h !== ""; + }); + } + }).find("input") + .trigger("change"); + + $("#desktopNotifications").on("change", function() { + var self = $(this); + if (self.prop("checked")) { + if (Notification.permission !== "granted") { + Notification.requestPermission(updateDesktopNotificationStatus); + } + } + }); + }()); var viewport = $("#viewport"); var sidebarSlide = window.slideoutMenu(viewport[0], sidebar[0]); @@ -676,9 +679,7 @@ $(function() { }) .tab(complete, {hint: false}); - var form = $("#form"); - - form.on("submit", function(e) { + $("#form").on("submit", function(e) { e.preventDefault(); var text = input.val(); @@ -804,7 +805,7 @@ $(function() { var text = ""; if (window.getSelection) { text = window.getSelection().toString(); - } else if (document.selection && document.selection.type !== "Control") { + } else if (document.selection && document.selection.type !== "Control") { text = document.selection.createRange().text; } if (!text) { @@ -1027,20 +1028,20 @@ $(function() { chat.on("click", ".toggle-button", function() { var self = $(this); - var chat = self.closest(".chat"); - var bottom = chat.isScrollBottom(); + var localChat = self.closest(".chat"); + var bottom = localChat.isScrollBottom(); var content = self.parent().next(".toggle-content"); if (bottom && !content.hasClass("show")) { var img = content.find("img"); if (img.length !== 0 && !img.width()) { img.on("load", function() { - chat.scrollBottom(); + localChat.scrollBottom(); }); } } content.toggleClass("show"); if (bottom) { - chat.scrollBottom(); + localChat.scrollBottom(); } }); @@ -1048,9 +1049,7 @@ $(function() { var forms = $("#sign-in, #connect, #change-password"); windows.on("show", "#sign-in", function() { - var self = $(this); - var inputs = self.find("input"); - inputs.each(function() { + $(this).find("input").each(function() { var self = $(this); if (self.val() === "") { self.focus(); diff --git a/scripts/build-fontawesome.js b/scripts/build-fontawesome.js index b7ce06f9..6c55863a 100644 --- a/scripts/build-fontawesome.js +++ b/scripts/build-fontawesome.js @@ -9,13 +9,13 @@ var fonts = [ "fontawesome-webfont.woff2" ]; -fs.ensureDir(destDir, function (err) { - if (err) { - console.error(err); +fs.ensureDir(destDir, function(dirErr) { + if (dirErr) { + console.error(dirErr); } - fonts.forEach(function (font) { - fs.copy(srcDir + font, destDir + font, function (err) { + fonts.forEach(function(font) { + fs.copy(srcDir + font, destDir + font, function(err) { if (err) { console.error(err); } else { diff --git a/src/client.js b/src/client.js index 6dc06c04..e18ed33a 100644 --- a/src/client.js +++ b/src/client.js @@ -118,12 +118,12 @@ Client.prototype.emit = function(event, data) { } }; -Client.prototype.find = function(id) { +Client.prototype.find = function(channelId) { var network = null; var chan = null; for (var i in this.networks) { var n = this.networks[i]; - chan = _.find(n.channels, {id: id}); + chan = _.find(n.channels, {id: channelId}); if (chan) { network = n; break; @@ -134,9 +134,9 @@ Client.prototype.find = function(id) { network: network, chan: chan }; - } else { - return false; } + + return false; }; Client.prototype.connect = function(args) { @@ -168,7 +168,7 @@ Client.prototype.connect = function(args) { // also used by the "connect" window } else if (args.join) { channels = args.join - .replace(/\,/g, " ") + .replace(/,/g, " ") .split(/\s+/g) .map(function(chan) { return new Chan({ @@ -278,6 +278,10 @@ Client.prototype.updateToken = function(callback) { var client = this; crypto.randomBytes(48, function(err, buf) { + if (err) { + throw err; + } + callback(client.config.token = buf.toString("hex")); }); }; diff --git a/src/clientManager.js b/src/clientManager.js index 1ec9f6ee..56774b63 100644 --- a/src/clientManager.js +++ b/src/clientManager.js @@ -34,8 +34,9 @@ ClientManager.prototype.loadUsers = function() { }; ClientManager.prototype.loadUser = function(name) { + let json; try { - var json = this.readUserConfig(name); + json = this.readUserConfig(name); } catch (e) { log.error("Failed to read user config", e); return; diff --git a/src/command-line/start.js b/src/command-line/start.js index a277e319..7bd40a79 100644 --- a/src/command-line/start.js +++ b/src/command-line/start.js @@ -6,11 +6,11 @@ var server = require("../server"); var Helper = require("../helper"); program - .option("-H, --host " , "host") - .option("-P, --port " , "port") - .option("-B, --bind " , "bind") - .option(" --public" , "mode") - .option(" --private" , "mode") + .option("-H, --host ", "host") + .option("-P, --port ", "port") + .option("-B, --bind ", "bind") + .option(" --public", "mode") + .option(" --private", "mode") .command("start") .description("Start the server") .action(function() { diff --git a/src/models/chan.js b/src/models/chan.js index 0eddf4a1..6a71eda4 100644 --- a/src/models/chan.js +++ b/src/models/chan.js @@ -78,9 +78,9 @@ Chan.prototype.getMode = function(name) { var user = _.find(this.users, {name: name}); if (user) { return user.mode; - } else { - return ""; } + + return ""; }; Chan.prototype.toJSON = function() { diff --git a/src/oidentd.js b/src/oidentd.js index 9412d6cd..80c42161 100644 --- a/src/oidentd.js +++ b/src/oidentd.js @@ -53,7 +53,7 @@ OidentdFile.prototype = { var file = "# Warning: file generated by The Lounge: changes will be overwritten!\n"; function makeRule(connection) { - return "to " + connection.socket.remoteAddress + return "to " + connection.socket.remoteAddress + " lport " + connection.socket.localPort + " from " + connection.socket.localAddress + " fport " + connection.socket.remotePort diff --git a/src/plugins/inputs/mode.js b/src/plugins/inputs/mode.js index cc26b80b..37bc490c 100644 --- a/src/plugins/inputs/mode.js +++ b/src/plugins/inputs/mode.js @@ -12,10 +12,10 @@ exports.input = function(network, chan, cmd, args) { if (cmd !== "mode") { user = args[0]; mode = { - "op": "+o", - "voice": "+v", - "deop": "-o", - "devoice": "-v" + op: "+o", + voice: "+v", + deop: "-o", + devoice: "-v" }[cmd]; } else if (args.length === 1) { return true; diff --git a/src/plugins/irc-events/link.js b/src/plugins/irc-events/link.js index 0aff8bc4..76cbfcba 100644 --- a/src/plugins/irc-events/link.js +++ b/src/plugins/irc-events/link.js @@ -90,8 +90,9 @@ function parse(msg, url, res, client) { } function fetch(url, cb) { + let req; try { - var req = request.get({ + req = request.get({ url: url, maxRedirects: 5, timeout: 5000, diff --git a/src/plugins/irc-events/message.js b/src/plugins/irc-events/message.js index 0f345cd7..558964e6 100644 --- a/src/plugins/irc-events/message.js +++ b/src/plugins/irc-events/message.js @@ -34,8 +34,9 @@ module.exports = function(irc, network) { }); function handleMessage(data) { - var highlight = false; - var self = data.nick === irc.user.nick; + let chan; + let highlight = false; + const self = data.nick === irc.user.nick; // Server messages go to server window, no questions asked if (data.from_server) { @@ -48,7 +49,7 @@ module.exports = function(irc, network) { target = data.nick; } - var chan = network.getChannel(target); + chan = network.getChannel(target); if (typeof chan === "undefined") { // Send notices that are not targeted at us into the server window if (data.type === Msg.Type.NOTICE) { diff --git a/src/plugins/irc-events/nick.js b/src/plugins/irc-events/nick.js index 8b3e9b20..51929f4c 100644 --- a/src/plugins/irc-events/nick.js +++ b/src/plugins/irc-events/nick.js @@ -6,12 +6,13 @@ var Msg = require("../../models/msg"); module.exports = function(irc, network) { var client = this; irc.on("nick", function(data) { + let msg; var self = false; if (data.nick === irc.user.nick) { network.setNick(data.new_nick); var lobby = network.channels[0]; - var msg = new Msg({ + msg = new Msg({ text: "You're now known as " + data.new_nick, }); lobby.pushMessage(client, msg); @@ -33,7 +34,7 @@ module.exports = function(irc, network) { client.emit("users", { chan: chan.id }); - var msg = new Msg({ + msg = new Msg({ time: data.time, type: Msg.Type.NICK, mode: chan.getMode(data.new_nick), diff --git a/src/server.js b/src/server.js index 80598fd0..c95102b2 100644 --- a/src/server.js +++ b/src/server.js @@ -127,13 +127,17 @@ function index(req, res, next) { } return fs.readFile("client/index.html", "utf-8", function(err, file) { + if (err) { + throw err; + } + var data = _.merge( pkg, Helper.config ); data.gitCommit = gitCommit; - data.themes = fs.readdirSync("client/themes/").filter(function(file) { - return file.endsWith(".css"); + data.themes = fs.readdirSync("client/themes/").filter(function(themeFile) { + return themeFile.endsWith(".css"); }).map(function(css) { return css.slice(0, -4); }); @@ -317,7 +321,7 @@ function auth(data) { manager.loadUser(data.user); client = manager.findClient(data.user); } - if (Helper.config.webirc !== null && !client.config["ip"]) { + if (Helper.config.webirc !== null && !client.config.ip) { reverseDnsLookup(socket, client); } else { init(socket, client, token); diff --git a/src/userLog.js b/src/userLog.js index e35df410..d8ce8a8b 100644 --- a/src/userLog.js +++ b/src/userLog.js @@ -6,8 +6,9 @@ var moment = require("moment"); var Helper = require("./helper"); module.exports.write = function(user, network, chan, msg) { + const path = Helper.getUserLogsPath(user, network); + try { - var path = Helper.getUserLogsPath(user, network); fsextra.ensureDirSync(path); } catch (e) { log.error("Unabled to create logs directory", e); diff --git a/test/models/network.js b/test/models/network.js index 04314b3d..65ae67ac 100644 --- a/test/models/network.js +++ b/test/models/network.js @@ -29,8 +29,8 @@ describe("Network", function() { ip: null, hostname: null, channels: [ - {"name": "#thelounge"}, - {"name": "&foobar"}, + {name: "#thelounge"}, + {name: "&foobar"}, ] }); });