diff --git a/src/inc/clients/irc.js b/src/inc/clients/irc.js index 44b79ef..346245e 100644 --- a/src/inc/clients/irc.js +++ b/src/inc/clients/irc.js @@ -2,7 +2,8 @@ import { logger } from "../log.js"; const net = require("net") , tls = require("tls") , EventEmitter = require("events").EventEmitter - , util = require("util"); + , util = require("util") + , fs = require("fs"); class irc { constructor(options) { @@ -20,6 +21,16 @@ class irc { this.realname = this.options.realname || "test"; this.channels = this.options.channels || []; this._recachetime = 60 * 5; // 10 minutes + this._cmd = new Map(); + + const files = fs.readdirSync(__dirname + '/irc/'); + for(let file in files) { + if(files[file].substr(-3, 3) === ".js") { + logger.info(`loading cmd: ${files[file]}`); + require(`${__dirname}/irc/${files[file]}`)(this); + } + } + this.server = { motd: "", me: {}, @@ -39,9 +50,13 @@ class irc { this.socket.setEncoding("utf-8"); this.socket.on("data", msg => { msg = msg.split(/\r?\n|\r/); - for(let tmp in msg) - if(msg[tmp].length > 0) - this.cmd(this.parse(msg[tmp])); + for(let tmp in msg) { + if(msg[tmp].length > 0) { + const cmd = this.parse(msg[tmp]); + if(this._cmd.has(cmd.command)) + this._cmd.get(cmd.command)(cmd); + } + } }); } send(data) { @@ -61,156 +76,12 @@ class irc { params: tmp }; } - cmd(msg) { - let tmpuser = {}; - let tmpchan = {}; - let chans = []; - let prefix = ""; - switch (msg.command) { // auslagern! - case "307": // Rizon Account - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) - tmpuser = this.server.user.geti(msg.params[1]); - tmpuser.account = msg.params[1]; - tmpuser.registered = true; - this.server.user.set(msg.params[1], tmpuser); - break; - case "311": // first - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) - tmpuser = this.server.user.geti(msg.params[1]); - tmpuser.nickname = msg.params[1]; - tmpuser.username = msg.params[2]; - tmpuser.hostname = msg.params[3]; - tmpuser.realname = msg.params[5]; - this.server.user.set(msg.params[1], tmpuser); - break; - case "313": // Oper - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) - tmpuser = this.server.user.geti(msg.params[1]); - tmpuser.oper = true; - this.server.user.set(msg.params[1], tmpuser); - break; - case "318": // last (check Data) - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) - tmpuser = this.server.user.geti(msg.params[1]); - tmpuser = { - nickname: tmpuser.nickname || false, - username: tmpuser.username || false, - hostname: tmpuser.hostname || false, - realname: tmpuser.realname || false, - account: tmpuser.account || false, - registered: tmpuser.registered || false, - oper: tmpuser.oper || false, - channels: tmpuser.channels || [], - cached: ~~(Date.now() / 1000) - }; - this.server.user.set(msg.params[1], tmpuser); - break; - case "319": // Chanlist Todo - tmpchan = new Map(); - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) { - tmpuser = this.server.user.geti(msg.params[1]); - if (tmpuser.channels) - tmpchan = tmpuser.channels; - } - chans = msg.params[2].trim().split(" "); - for (let chan in chans) { - chan = chans[chan].split("#"); - tmpchan.set(`#${chan[1]}`, chan[0]); - } - tmpuser.channels = tmpchan; - this.server.user.set(msg.params[1], tmpuser); - break; - case "330": // Quarknet - tmpuser = {}; - if (this.server.user.hasi(msg.params[1])) - tmpuser = this.server.user.geti(msg.params[1]); - tmpuser.account = msg.params[2]; - tmpuser.registered = true; - this.server.user.set(msg.params[1], tmpuser); - break; - case "001": // welcome - this.server.me = msg.params[0]; - this.join(this.options.channels); - this.emit("data", ["connected", msg.params[1]]); - break; - case "352": // who_entry - if (!this.server.channel[msg.params[1]]) - this.server.channel[msg.params[1]] = new Map(); - this.server.channel[msg.params[1]].set(msg.params[5], { // chan - nick: msg.params[5], - username: msg.params[2], - hostname: msg.params[3] - }); - this.whois(msg.params[5]); - break; - case "315": // who_end - //console.log(this.server.channel); - break; - case "372": // motd - this.server.motd += `${msg.params[1]}\n`; - break; - case "375": // motd_start - this.server.motd = `${msg.params[1]}\n`; - break; - case "376": // motd_end - this.server.motd += `${msg.params[1]}\n`; - this.emit("data", ["motd", this.server.motd]); - break; - case "464": // Password required - if (this.options.password.length > 0 && !this.options.sasl) - this.send(`PASS ${this.options.password}`); // pwd - break; - case "PING": - this.send(`PONG ${msg.params.join``}`); - break; - case "JOIN": // wip - this.send(`WHO ${msg.params[0]}`); - break; - case "PART": // wip - delete this.server.user[msg.params[0]]; - break; - case "PRIVMSG": - this.emit("data", msg.params[1] === "\u0001VERSION\u0001" ? ["ctcp:version", this.reply(msg)] : ["message", this.reply(msg)]); - break; - case "NOTICE": - this.emit("data", ["notice", msg.params[1]]); - break; - case "NICK": // nickchange - prefix = parsePrefix(msg.prefix); - if(this.server.user.hasi(prefix.nick)) - this.server.user.deli(prefix.nick); - this.whois(msg.params[0], true); // force - break; - case "CAP": - switch (msg.params[1]) { - case "LS": - this.send(`CAP REQ :${msg.params[2]}`); - break; - case "ACK": // success - this.send("AUTHENTICATE PLAIN"); - break; - } - break; - case "AUTHENTICATE": - if (msg.params[0].match(/\+/)) - this.send(`AUTHENTICATE ${new Buffer(this.username + "\u0000" + this.username + "\u0000" + this.options.password).toString("base64")}`); - break; - case "900": - this.send("CAP END"); - break; - } - } reply(tmp) { return { type: "irc", network: this.network, channel: tmp.params[0], - user: parsePrefix(tmp.prefix), + user: this.parsePrefix(tmp.prefix), message: tmp.params[1], time: ~~(Date.now() / 1000), raw: tmp, @@ -219,6 +90,7 @@ class irc { replyNotice: msg => this.send(`NOTICE ${tmp.params[0]} :${msg}`), _chan: this.server.channel[tmp.params[0]], _user: this.server.user, + _cmd: this._cmd, join: chan => this.join(chan), part: (chan, msg) => this.part(chan, msg), whois: user => this.whois(user), @@ -238,21 +110,19 @@ class irc { return; this.send(`WHOIS ${user}`); } + parsePrefix(prefix) { + prefix = /:?(.*)\!(.*)@(.*)/.exec(prefix); + return { + nick: prefix[1], + username: prefix[2], + hostname: prefix[3] + }; + } } module.exports = irc; util.inherits(irc, EventEmitter); -function parsePrefix(prefix) { - let usertmp = prefix.replace(/^:/, "").split("!"); - let hosttmp = usertmp[1].split("@"); - return { - nick: usertmp[0], - username: hosttmp[0], - hostname: hosttmp[1] - }; -} - Map.prototype.hasi = function(val) { for (let [key] of this) if(key.toLowerCase() === val.toLowerCase()) diff --git a/src/inc/clients/irc/cap.js b/src/inc/clients/irc/cap.js new file mode 100644 index 0000000..b41999e --- /dev/null +++ b/src/inc/clients/irc/cap.js @@ -0,0 +1,21 @@ +module.exports = client => { + client._cmd.set("CAP", function (msg) { // capkram + switch (msg.params[1]) { + case "LS": // list + this.send(`CAP REQ :${msg.params[2]}`); + break; + case "ACK": // success + this.send("AUTHENTICATE PLAIN"); + break; + } + }.bind(client)); + + client._cmd.set("AUTHENTICATE", function (msg) { // auth + if (msg.params[0].match(/\+/)) + this.send(`AUTHENTICATE ${new Buffer(this.username + "\u0000" + this.username + "\u0000" + this.options.password).toString("base64")}`); + }.bind(client)); + + client._cmd.set("900", function (msg) { // cap end + this.send("CAP END"); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/join.js b/src/inc/clients/irc/join.js new file mode 100644 index 0000000..5ec6d7d --- /dev/null +++ b/src/inc/clients/irc/join.js @@ -0,0 +1,5 @@ +module.exports = client => { + client._cmd.set("JOIN", function (msg) { // join + this.send(`WHO ${msg.params[0]}`); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/motd.js b/src/inc/clients/irc/motd.js new file mode 100644 index 0000000..0a462fd --- /dev/null +++ b/src/inc/clients/irc/motd.js @@ -0,0 +1,14 @@ +module.exports = client => { + client._cmd.set("372", function (msg) { // motd_entry + this.server.motd += `${msg.params[1]}\n`; + }.bind(client)); + + client._cmd.set("375", function (msg) { // motd_start + this.server.motd = `${msg.params[1]}\n`; + }.bind(client)); + + client._cmd.set("376", function (msg) { // motd_end + this.server.motd += `${msg.params[1]}\n`; + this.emit("data", ["motd", this.server.motd]); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/msg.js b/src/inc/clients/irc/msg.js new file mode 100644 index 0000000..c05ef34 --- /dev/null +++ b/src/inc/clients/irc/msg.js @@ -0,0 +1,9 @@ +module.exports = client => { + client._cmd.set("PRIVMSG", function (msg) { // privmsg + this.emit("data", msg.params[1] === "\u0001VERSION\u0001" ? ["ctcp:version", this.reply(msg)] : ["message", this.reply(msg)]); + }.bind(client)); + + client._cmd.set("NOTICE", function (msg) { // notice + this.emit("data", ["notice", msg.params[1]]); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/nick.js b/src/inc/clients/irc/nick.js new file mode 100644 index 0000000..1b29d12 --- /dev/null +++ b/src/inc/clients/irc/nick.js @@ -0,0 +1,8 @@ +module.exports = client => { + client._cmd.set("NICK", function (msg) { // nickchange + let prefix = this.parsePrefix(msg.prefix); + if (this.server.user.hasi(prefix.nick)) + this.server.user.deli(prefix.nick); + this.whois(msg.params[0], true); // force + }.bind(client)); +}; diff --git a/src/inc/clients/irc/part.js b/src/inc/clients/irc/part.js new file mode 100644 index 0000000..82d586b --- /dev/null +++ b/src/inc/clients/irc/part.js @@ -0,0 +1,5 @@ +module.exports = client => { + client._cmd.set("PART", function (msg) { // part + //delete this.server.user[msg.params[0]]; + }.bind(client)); +}; diff --git a/src/inc/clients/irc/ping.js b/src/inc/clients/irc/ping.js new file mode 100644 index 0000000..7221778 --- /dev/null +++ b/src/inc/clients/irc/ping.js @@ -0,0 +1,5 @@ +module.exports = client => { + client._cmd.set("PING", function (msg) { // ping + this.send(`PONG ${msg.params.join``}`); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/pwdreq.js b/src/inc/clients/irc/pwdreq.js new file mode 100644 index 0000000..216961f --- /dev/null +++ b/src/inc/clients/irc/pwdreq.js @@ -0,0 +1,6 @@ +module.exports = client => { + client._cmd.set("464", function (msg) { // motd_entry + if (this.options.password.length > 0 && !this.options.sasl) + this.send(`PASS ${this.options.password}`); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/welcome.js b/src/inc/clients/irc/welcome.js new file mode 100644 index 0000000..743f3a8 --- /dev/null +++ b/src/inc/clients/irc/welcome.js @@ -0,0 +1,7 @@ +module.exports = client => { + client._cmd.set("001", function (msg) { // welcome + this.server.me = msg.params[0]; + this.join(this.options.channels); + this.emit("data", ["connected", msg.params[1]]); + }.bind(client)); +}; diff --git a/src/inc/clients/irc/who.js b/src/inc/clients/irc/who.js new file mode 100644 index 0000000..3616827 --- /dev/null +++ b/src/inc/clients/irc/who.js @@ -0,0 +1,16 @@ +module.exports = client => { + client._cmd.set("352", function (msg) { // who_entry + if (!this.server.channel[msg.params[1]]) + this.server.channel[msg.params[1]] = new Map(); + this.server.channel[msg.params[1]].set(msg.params[5], { // chan + nick: msg.params[5], + username: msg.params[2], + hostname: msg.params[3] + }); + this.whois(msg.params[5]); + }.bind(client)); + + client._cmd.set("315", function (msg) { // who_end + // + }.bind(client)); +}; diff --git a/src/inc/clients/irc/whois.js b/src/inc/clients/irc/whois.js new file mode 100644 index 0000000..bdfacf8 --- /dev/null +++ b/src/inc/clients/irc/whois.js @@ -0,0 +1,73 @@ +module.exports = client => { + client._cmd.set("307", function (msg) { // whois_identified (ircd-hybrid) + let tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) + tmpuser = this.server.user.geti(msg.params[1]); + tmpuser.account = msg.params[1]; + tmpuser.registered = true; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); + + client._cmd.set("311", function (msg) { // whois_userdata + let tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) + tmpuser = this.server.user.geti(msg.params[1]); + tmpuser.nickname = msg.params[1]; + tmpuser.username = msg.params[2]; + tmpuser.hostname = msg.params[3]; + tmpuser.realname = msg.params[5]; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); + + client._cmd.set("313", function (msg) { // whois_oper + let tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) + tmpuser = this.server.user.geti(msg.params[1]); + tmpuser.oper = true; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); + + client._cmd.set("318", function (msg) { // whois_end + let tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) + tmpuser = this.server.user.geti(msg.params[1]); + tmpuser = { + nickname: tmpuser.nickname || false, + username: tmpuser.username || false, + hostname: tmpuser.hostname || false, + realname: tmpuser.realname || false, + account: tmpuser.account || false, + registered: tmpuser.registered || false, + oper: tmpuser.oper || false, + channels: tmpuser.channels || [], + cached: ~~(Date.now() / 1000) + }; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); + + client._cmd.set("319", function (msg) { // whois_chanlist + let tmpchan = new Map() + , tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) { + tmpuser = this.server.user.geti(msg.params[1]); + if (tmpuser.channels) + tmpchan = tmpuser.channels; + } + let chans = msg.params[2].trim().split(" "); + for (let chan in chans) { + chan = chans[chan].split("#"); + tmpchan.set(`#${chan[1]}`, chan[0]); + } + tmpuser.channels = tmpchan; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); + + client._cmd.set("330", function (msg) { // whois_authed_as (snircd) + let tmpuser = {}; + if (this.server.user.hasi(msg.params[1])) + tmpuser = this.server.user.geti(msg.params[1]); + tmpuser.account = msg.params[2]; + tmpuser.registered = true; + this.server.user.set(msg.params[1], tmpuser); + }.bind(client)); +};