diff --git a/lib/plugins/errors.js b/lib/plugins/errors.js new file mode 100644 index 0000000..3e711fa --- /dev/null +++ b/lib/plugins/errors.js @@ -0,0 +1,20 @@ +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("errors", function(data) { + sockets.in("chat").emit("msg", { + msg: new Msg({ + type: "error", + from: "-!-", + text: data.message, + }), + }); + if (!network.connected) { + if (data.cmd == "ERR_NICKNAMEINUSE") { + var random = config.defaults.nick + Math.floor(10 + (Math.random() * 89)); + client.nick(random); + } + } + }); +}; diff --git a/lib/plugins/join.js b/lib/plugins/join.js new file mode 100644 index 0000000..b4f46fb --- /dev/null +++ b/lib/plugins/join.js @@ -0,0 +1,29 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("join", function(data) { + var chan = _.findWhere(network.channels, {name: data.channel}); + if (typeof chan === "undefined") { + chan = new Chan({ + name: data.channel, + }); + network.addChan(chan); + sockets.in("chat").emit("join", { + id: network.id, + chan: chan, + }); + } + var msg = new Msg({ + from: data.nick, + type: "join", + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/kick.js b/lib/plugins/kick.js new file mode 100644 index 0000000..c464642 --- /dev/null +++ b/lib/plugins/kick.js @@ -0,0 +1,32 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("kick", function(data) { + var chan = _.findWhere(network.channels, {name: data.channel}); + if (typeof chan === "undefined") { + return; + } + if (data.client == client.me) { + chan.users = []; + } else { + chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.client})); + } + sockets.in("chat").emit("users", { + id: chan.id, + users: chan.users, + }); + var msg = new Msg({ + type: "kick", + from: data.nick, + text: data.client, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/message.js b/lib/plugins/message.js new file mode 100644 index 0000000..0a97d5d --- /dev/null +++ b/lib/plugins/message.js @@ -0,0 +1,42 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); +var Network = require("../models/network"); + +module.exports = function(client, sockets) { + var network = this; + client.on("message", function(data) { + var target = data.to; + var chan = _.findWhere(network.channels, {name: target.charAt(0) == "#" ? target : data.from}); + if (typeof chan === "undefined") { + chan = new Chan({ + name: data.from, + type: "query", + }); + network.addChan(chan); + sockets.in("chat").emit("join", { + id: network.id, + chan: chan, + }); + } + var type = ""; + var text = data.message; + if (text.split(" ")[0] === "\u0001ACTION") { + type = "action"; + text = text.replace(/\u0001|ACTION/g, ""); + } + text.split(' ').forEach(function(w) { + if (w.indexOf(client.me) == 0) type += " highlight"; + }); + var msg = new Msg({ + type: type || "normal", + from: data.from, + text: text, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/mode.js b/lib/plugins/mode.js new file mode 100644 index 0000000..bbc4988 --- /dev/null +++ b/lib/plugins/mode.js @@ -0,0 +1,31 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + var timer = null; + client.on("mode", function(data) { + var chan = _.findWhere(network.channels, {name: data.target}); + if (typeof chan !== "undefined") { + clearTimeout(timer); + timer = setTimeout(function() { + client.write("NAMES " + data.target); + }, 200); + var nick = data.nick; + if (nick.indexOf(".") !== -1) { + nick = data.target; + } + var msg = new Msg({ + type: "mode", + from: nick, + text: data.mode + " " + data.client, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + } + }); +}; diff --git a/lib/plugins/motd.js b/lib/plugins/motd.js new file mode 100644 index 0000000..9282417 --- /dev/null +++ b/lib/plugins/motd.js @@ -0,0 +1,22 @@ +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("motd", function(data) { + var rows = data.motd; + var chan = network.channels[0]; + rows.forEach(function(text) { + var msg = new Msg({ + type: "motd", + from: "-!-", + text: text, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); + }); +}; diff --git a/lib/plugins/names.js b/lib/plugins/names.js new file mode 100644 index 0000000..fde207c --- /dev/null +++ b/lib/plugins/names.js @@ -0,0 +1,22 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var User = require("../models/user"); + +module.exports = function(client, sockets) { + var network = this; + client.on("names", function(data) { + var chan = _.findWhere(network.channels, {name: data.channel}); + if (typeof chan === "undefined") { + return; + } + chan.users = []; + _.each(data.names, function(n) { + chan.addUser(new User(n)); + }); + chan.sortUsers(); + sockets.in("chat").emit("users", { + id: chan.id, + users: chan.users, + }); + }); +}; diff --git a/lib/plugins/nick.js b/lib/plugins/nick.js new file mode 100644 index 0000000..58245b7 --- /dev/null +++ b/lib/plugins/nick.js @@ -0,0 +1,43 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("nick", function(data) { + if (data["new"] == client.me) { + var chan = network.channels[0]; + var msg = new Msg({ + from: "-!-", + text: "You're now known as " + data["new"], + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + } + network.channels.forEach(function(chan) { + var user = _.findWhere(chan.users, {name: data.nick}); + if (!user) { + return; + } + user.name = data["new"]; + chan.sortUsers(); + sockets.in("chat").emit("users", { + id: chan.id, + users: chan.users, + }); + var msg = new Msg({ + type: "nick", + from: data.nick, + text: data["new"], + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); + }); +}; diff --git a/lib/plugins/notice.js b/lib/plugins/notice.js new file mode 100644 index 0000000..64bad64 --- /dev/null +++ b/lib/plugins/notice.js @@ -0,0 +1,23 @@ +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("notice", function(data) { + var chan = network.channels[0]; + var from = data.from || "-!-"; + if (data.to == "*" || data.from.indexOf(".") !== -1) { + from = "-!-"; + } + var msg = new Msg({ + type: "notice", + from: from, + text: data.message, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/part.js b/lib/plugins/part.js new file mode 100644 index 0000000..c4840e2 --- /dev/null +++ b/lib/plugins/part.js @@ -0,0 +1,34 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("part", function(data) { + var chan = _.findWhere(network.channels, {name: data.channels[0]}); + if (typeof chan === "undefined") { + return; + } + if (data.nick == client.me) { + network.channels = _.without(network.channels, chan); + sockets.in("chat").emit("part", { + id: chan.id, + }); + } else { + chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.nick})); + sockets.in("chat").emit("users", { + id: chan.id, + users: chan.users, + }); + var msg = new Msg({ + type: "part", + from: data.nick, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + } + }); +}; diff --git a/lib/plugins/quit.js b/lib/plugins/quit.js new file mode 100644 index 0000000..9e39b09 --- /dev/null +++ b/lib/plugins/quit.js @@ -0,0 +1,29 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("quit", function(data) { + network.channels.forEach(function(chan) { + var user = _.findWhere(chan.users, {name: data.nick}); + if (!user) { + return; + } + chan.users = _.without(chan.users, user); + sockets.in("chat").emit("users", { + id: chan.id, + users: chan.users, + }); + var msg = new Msg({ + type: "quit", + from: data.nick, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); + }); +}; diff --git a/lib/plugins/topic.js b/lib/plugins/topic.js new file mode 100644 index 0000000..5c8b894 --- /dev/null +++ b/lib/plugins/topic.js @@ -0,0 +1,24 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("topic", function(data) { + var chan = _.findWhere(network.channels, {name: data.channel}); + if (typeof chan === "undefined") { + return; + } + var from = data.nick || chan.name; + var msg = new Msg({ + type: "topic", + from: from, + text: data.topic, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/welcome.js b/lib/plugins/welcome.js new file mode 100644 index 0000000..0125033 --- /dev/null +++ b/lib/plugins/welcome.js @@ -0,0 +1,19 @@ +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("welcome", function(data) { + network.connected = true; + var chan = network.channels[0]; + var msg = new Msg({ + from: "-!-", + text: "You're now known as " + data, + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/plugins/whois.js b/lib/plugins/whois.js new file mode 100644 index 0000000..1332a6d --- /dev/null +++ b/lib/plugins/whois.js @@ -0,0 +1,57 @@ +var _ = require("lodash"); +var Chan = require("../models/chan"); +var Msg = require("../models/msg"); + +module.exports = function(client, sockets) { + var network = this; + client.on("whois", function(err, data) { + if (!data) { + return; + } + var chan = _.findWhere(network.channels, {name: data.nickname}); + if (typeof chan === "undefined") { + chan = new Chan({ + type: "query", + name: data.nickname, + }); + network.addChan(chan); + sockets.in("chat").emit("join", { + id: network.id, + chan: chan, + }); + } + var prefix = { + hostname: "from", + realname: "is", + channels: "on", + server: "using", + }; + var i = 0; + for (var k in data) { + var key = prefix[k]; + if (!key || data[k].toString() == "") { + continue; + } + var msg = new Msg({ + type: "whois", + from: data.nickname, + text: key + " " + data[k], + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + } + var msg = new Msg({ + type: "whois", + from: data.nickname, + text: "End of /WHOIS list.", + }); + chan.addMsg(msg); + sockets.in("chat").emit("msg", { + id: chan.id, + msg: msg, + }); + }); +}; diff --git a/lib/server.js b/lib/server.js index a26d26e..c0c346f 100644 --- a/lib/server.js +++ b/lib/server.js @@ -7,17 +7,13 @@ var irc = require("slate-irc"); var net = require("net"); var tls = require("tls"); -// Models - -var Chan = require("./models/chan"); var Msg = require("./models/msg"); var Network = require("./models/network"); -var User = require("./models/user"); var sockets = null; var networks = []; -var events = [ +var plugins = [ "errors", "join", "kick", @@ -34,9 +30,7 @@ var events = [ "whois", ]; -module.exports = listen; - -function listen() { +module.exports = function listen() { var port = config.port || 9000; var app = http() .use(index) @@ -73,7 +67,7 @@ function init(login) { function index(req, res, next) { if (req.url != "/") return next(); - fs.readFile("client/index.html", function(err, file) { + return fs.readFile("client/index.html", function(err, file) { var data = _.merge( require("../package.json"), config @@ -116,10 +110,8 @@ function connect(params) { client.nick(params.nick); client.user(params.nick, params.realname); - events.forEach(function(e) { - client.on(e, function() { - event.apply(network, [e, arguments]); - }); + plugins.forEach(function(plugin) { + require("./plugins/" + plugin).apply(network, [client, sockets]); }); if (!params.onConnect) { @@ -127,20 +119,20 @@ function connect(params) { } client.once("welcome", function() { - (params.onConnect.join || []).forEach(function(chan) { + client.write("PING " + network.host); + var channels = params.onConnect.join || []; + channels.forEach(function(chan) { client.join.apply( client, chan.split(' ') ); }); - - // Trigger 'PONG' response. - client.write("PING " + network.host); }); client.once("pong", function() { var delay = 1000; - (params.onConnect.commands || []).forEach(function(cmd) { + var commands = params.onConnect.commands || []; + commands.forEach(function(cmd) { setTimeout(function() { input({ id: network.channels[0].id, @@ -397,7 +389,6 @@ function input(data) { } break; - // Send raw IRC messages. case "raw": case "send": if (client) { @@ -423,366 +414,6 @@ function fetch(data) { }); } -function event(e, data) { - var data = _.last(data); - var network = this; - - switch (e) { - case "errors": - sockets.in("chat").emit("msg", { - msg: new Msg({ - type: "error", - from: "-!-", - text: data.message, - }), - }); - if (!this.connected) { - if (data.cmd == "ERR_NICKNAMEINUSE") { - var random = config.defaults.nick + Math.floor(10 + (Math.random() * 89)); - this.client.nick(random); - } - } - break; - - case "join": - var chan = _.findWhere(this.channels, {name: data.channel}); - if (typeof chan === "undefined") { - chan = new Chan({ - name: data.channel, - }); - this.addChan(chan); - sockets.in("chat").emit("join", { - id: this.id, - chan: chan, - }); - } - var users = chan.users; - users.push(new User({name: data.nick})); - chan.sortUsers(); - sockets.in("chat").emit("users", { - id: chan.id, - users: users, - }); - var msg = new Msg({ - from: data.nick, - type: "join", - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "kick": - var chan = _.findWhere(this.channels, {name: data.channel}); - if (typeof chan === "undefined") { - break; - } - if (data.client == this.client.me) { - chan.users = []; - } else { - chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.client})); - } - sockets.in("chat").emit("users", { - id: chan.id, - users: chan.users, - }); - var msg = new Msg({ - type: "kick", - from: data.nick, - text: data.client, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "mode": - var chan = _.findWhere(this.channels, {name: data.target}); - if (typeof chan !== "undefined") { - clearTimeout(this.timer); - this.timer = setTimeout((function() { - this.client.write("NAMES " + data.target); - }).bind(this), 200); - var nick = data.nick; - if (nick.indexOf(".") !== -1) { - nick = data.target; - } - var msg = new Msg({ - type: "mode", - from: nick, - text: data.mode + " " + data.client, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - } - break; - - case "motd": - var chan = this.channels[0]; - data.motd.forEach(function(m) { - var msg = new Msg({ - type: "motd", - from: "-!-", - text: m, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - }); - break; - - case "message": - var target = data.to; - var chan = _.findWhere(this.channels, {name: target.charAt(0) == "#" ? target : data.from}); - if (typeof chan === "undefined") { - chan = new Chan({ - name: data.from, - type: "query", - }); - this.addChan(chan); - sockets.in("chat").emit("join", { - id: this.id, - chan: chan, - }); - } - var type = ""; - var text = data.message; - if (text.split(" ")[0] === "\u0001ACTION") { - type = "action"; - text = text.replace(/\u0001|ACTION/g, ""); - } - var network = this; - text.split(' ').forEach(function(w) { - if (w.indexOf(network.client.me) == 0) type += " highlight"; - }); - var msg = new Msg({ - type: type || "normal", - from: data.from, - text: text, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "names": - var chan = _.findWhere(this.channels, {name: data.channel}); - if (typeof chan === "undefined") { - break; - } - chan.users = []; - _.each(data.names, function(n) { - chan.addUser(new User(n)); - }); - chan.sortUsers(); - sockets.in("chat").emit("users", { - id: chan.id, - users: chan.users, - }); - break; - - case "nick": - if (data["new"] == this.client.me) { - var chan = this.channels[0]; - var msg = new Msg({ - from: "-!-", - text: "You're now known as " + data["new"], - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - } - this.channels.forEach(function(chan) { - var user = _.findWhere(chan.users, {name: data.nick}); - if (!user) { - return; - } - user.name = data["new"]; - chan.sortUsers(); - sockets.in("chat").emit("users", { - id: chan.id, - users: chan.users, - }); - var msg = new Msg({ - type: "nick", - from: data.nick, - text: data["new"], - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - }); - break; - - case "notice": - var chan = this.channels[0]; - var from = data.from || "-!-"; - if (data.to == "*" || data.from.indexOf(".") !== -1) { - from = "-!-"; - } - var msg = new Msg({ - type: "notice", - from: from, - text: data.message, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "part": - var chan = _.findWhere(this.channels, {name: data.channels[0]}); - if (typeof chan === "undefined") { - break; - } - if (data.nick == this.client.me) { - remove(chan.id); - sockets.in("chat").emit("part", { - id: chan.id, - }); - } else { - chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.nick})); - sockets.in("chat").emit("users", { - id: chan.id, - users: chan.users, - }); - var msg = new Msg({ - type: "part", - from: data.nick, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - } - break; - - case "quit": - this.channels.forEach(function(chan) { - var user = _.findWhere(chan.users, {name: data.nick}); - if (!user) { - return; - } - chan.users = _.without(chan.users, user); - sockets.in("chat").emit("users", { - id: chan.id, - users: chan.users, - }); - var msg = new Msg({ - type: "quit", - from: data.nick, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - }); - break; - - case "topic": - var chan = _.findWhere(this.channels, {name: data.channel}); - if (typeof chan === "undefined") { - break; - } - var from = data.nick || chan.name; - var msg = new Msg({ - type: "topic", - from: from, - text: data.topic, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "welcome": - this.connected = true; - var chan = this.channels[0]; - var msg = new Msg({ - from: "-!-", - text: "You're now known as " + data, - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - - case "whois": - if (!data) { - break; - } - var chan = _.findWhere(this.channels, {name: data.nickname}); - if (typeof chan === "undefined") { - chan = new Chan({ - type: "query", - name: data.nickname, - }); - this.addChan(chan); - sockets.in("chat").emit("join", { - id: this.id, - chan: chan, - }); - } - var prefix = { - hostname: "from", - realname: "is", - channels: "on", - server: "using", - }; - var i = 0; - for (var k in data) { - var key = prefix[k]; - if (!key || data[k].toString() == "") { - continue; - } - var msg = new Msg({ - type: "whois", - from: data.nickname, - text: key + " " + data[k], - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - } - var msg = new Msg({ - type: "whois", - from: data.nickname, - text: "End of /WHOIS list.", - }); - chan.addMsg(msg); - sockets.in("chat").emit("msg", { - id: chan.id, - msg: msg, - }); - break; - } -} - function find(id) { for (var i = 0; i < networks.length; i++) { var result = {