diff --git a/README.md b/README.md index 84afe81..43bae73 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,3 @@ The client will be accessible at http://localhost:8080/ ### WebIRC The server will look for passwords in `webirc.data.json`. The format is: `"server-ip-address": "server webirc password"` - -###The (non-complete) TODO List (of things left to do) - -* [NORMAL] CAP negotiation -* [LOW] Better input -* [LOW] irc:// URL scheme handling -* [LOW] Connection presets -* [LOW] More command handling (use /quote for non-integrated commands) diff --git a/client.config.example.toml b/client.config.example.toml index e39df3b..b2ec372 100644 --- a/client.config.example.toml +++ b/client.config.example.toml @@ -10,6 +10,4 @@ secure_by_default=false timeout=3000 encoding="utf-8" - -[tls] - rejectUnauthorized=false + rejectUnauthorizedCertificates=false diff --git a/server/teemant_irc/index.js b/server/teemant_irc/index.js new file mode 100644 index 0000000..908fcf2 --- /dev/null +++ b/server/teemant_irc/index.js @@ -0,0 +1,7 @@ +let connector = require(__dirname+'/irc.js'); +let parser = require(__dirname+'/parser.js'); + +module.exports = { + IRCConnection: connector, + Parser: parser +} diff --git a/server/irc.js b/server/teemant_irc/irc.js similarity index 92% rename from server/irc.js rename to server/teemant_irc/irc.js index 37d5ce6..f519e54 100644 --- a/server/irc.js +++ b/server/teemant_irc/irc.js @@ -1,10 +1,8 @@ let EventEmitter = require('events').EventEmitter; let net = require('net'); let tls = require('tls'); -let configuration = require(__dirname+"/config"); -let pkg = require(__dirname+"/../package.json"); + let parse = require(__dirname+"/parser"); -let webirc = require(__dirname+"/webirc"); if (!String.prototype.format) { String.prototype.format = function() { @@ -39,7 +37,8 @@ class IRCConnectionHandler { this.conn.write('{0} {1}'.format(data.command.toUpperCase(), data.arguments[0])); break; case "quit": - this.conn.write('{0} :{1}'.format(data.command.toUpperCase(), (data.message == '' ? configuration.client.default_quit_msg : data.message))); + this.conn.write('{0} :{1}'.format(data.command.toUpperCase(), (data.message == '' ? + this.conn.globalConfig.default_quit_msg : data.message))); break; case "privmsg": this.conn.write('PRIVMSG {0} :{1}'.format(data.arguments[0], data.message)); @@ -89,25 +88,18 @@ class IRCConnectionHandler { ctcpManage(data) { let line = data.trailing.replace(/\x01/g, '').trim().split(' '); + if(!line[0]) return; + line[0] = line[0].toUpperCase(); let resp = "\x01"+line[0]+" {0}\x01"; - switch(line[0].toLowerCase()) { - case "ping": - if(line[1] != null && line[1] != '') - resp = resp.format(line.slice(1).join(' ')); - else - resp = null; - break; - case "version": - resp = resp.format("TeemantIRC ver. {0} - {1} - https://teemant.icynet.ml/".format(pkg.version, pkg.description)); - break; - case "source": - resp = resp.format("https://github.com/DiamondtechDev/TeemantIRC"); - break; - default: - resp = null; + if(line[0] == "PING" && line[1] != null && line[1] != '') { + resp = resp.format(line.slice(1).join(' ')); + } else if(this.conn.extras.ctcps && this.conn.extras.ctcps[line[0]] != null) { + resp = resp.format(this.conn.extras.ctcps[line[0]](data, this.conn)); + } else { + resp = null; } if (resp != null) @@ -418,24 +410,24 @@ class IRCConnectionHandler { } class IRCConnection extends EventEmitter { - constructor(providedInfo, userInfo) { + constructor(providedInfo, globalConfig, extras) { super(); + this.globalConfig = globalConfig; + this.extras = extras || { authenticationSteps: [], ctcps: {} }; this.config = { nickname: "teemant", - username: configuration.client.username, - realname: configuration.client.realname, + username: globalConfig.username, + realname: globalConfig.realname, server: "localhost", port: 6667, autojoin: [], - secure: configuration.client.secure_by_default, + secure: globalConfig.secure_by_default, password: "", address: "0.0.0.0", - rejectUnauthorized: configuration.tls.rejectUnauthorized + rejectUnauthorized: globalConfig.rejectUnauthorizedCertificates }; - this.userInfo = userInfo; - for(let a in providedInfo) { this.config[a] = providedInfo[a]; } @@ -472,8 +464,8 @@ class IRCConnection extends EventEmitter { this.authenticate(); }); - this.socket.setEncoding(configuration.client.encoding); - this.socket.setTimeout(configuration.client.timeout); + this.socket.setEncoding(this.globalConfig.encoding); + this.socket.setTimeout(this.globalConfig.timeout); this.socket.on('error', (data) => { this.emit('connerror', {type: "sock_error", message: "A socket error occured.", raw: data}); @@ -518,10 +510,12 @@ class IRCConnection extends EventEmitter { if (this.config.password) this.socket.write('PASS {0}\r\n'.format(this.config.password)); - let serverpass = webirc.get_password(this.config.address); - - if(serverpass) - this.socket.write('WEBIRC {0} {1} {2} {3}\r\n'.format(serverpass, this.config.username, this.userInfo.hostname, this.userInfo.ipaddr)); + if(this.extras.authenticationSteps) { + for(let i in this.extras.authenticationSteps) { + let step = this.extras.authenticationSteps[i]; + step.authenticate(this); + } + } this.socket.write('USER {0} 8 * :{1}\r\n'.format(this.config.username, this.config.realname)); this.socket.write('NICK {0}\r\n'.format(this.config.nickname)); @@ -534,7 +528,7 @@ class IRCConnection extends EventEmitter { } this.queue['close'] = true; - this.socket.write('QUIT :{0}\r\n'.format(message != null ? message : configuration.client.default_quit_msg)); + this.socket.write('QUIT :{0}\r\n'.format(message != null ? message : this.globalConfig.default_quit_msg)); } write(message) { diff --git a/server/parser.js b/server/teemant_irc/parser.js similarity index 100% rename from server/parser.js rename to server/teemant_irc/parser.js diff --git a/server/webirc.js b/server/webirc.js index ed88d23..ee5f152 100644 --- a/server/webirc.js +++ b/server/webirc.js @@ -31,8 +31,22 @@ function get_password(server_ip) { return null; } +class WebIRCAuthenticator { + constructor(userInfo) { + this.userInfo = userInfo; + } + + authenticate(connection) { + let serverpass = get_password(connection.config.address); + if(serverpass) + connection.socket.write('WEBIRC '+serverpass+' '+connection.config.username+ + ' '+this.userInfo.hostname+' '+this.userInfo.ipaddr+'\r\n'); + } +} + module.exports = { reload: reload, + authenticator: WebIRCAuthenticator, get_password: get_password, writeToFile: writeToFile } diff --git a/teemant.js b/teemant.js index 73b7388..49f4a2b 100755 --- a/teemant.js +++ b/teemant.js @@ -8,8 +8,11 @@ let app = express(); let router = express.Router(); let pubdir = path.join(__dirname, "public"); +let pkg = require(__dirname+"/package.json"); + let config = require(__dirname+'/server/config'); -let ircclient = require(__dirname+'/server/irc'); +let irclib = require(__dirname+'/server/teemant_irc'); +let webirc = require(__dirname+'/server/webirc'); let port = config.server.port || 8080; @@ -19,6 +22,15 @@ let runtime_stats = { let connections = {}; +let customCTCPs = { + VERSION: function(data, connection) { + return "TeemantIRC ver. "+pkg.version+" - "+pkg.description+" - https://teemant.icynet.ml/"; + }, + SOURCE: function(data, connection) { + return "https://github.com/DiamondtechDev/TeemantIRC"; + } +} + process.stdin.resume(); router.get("/", function(req, res){ @@ -135,7 +147,9 @@ io.sockets.on('connection', function (socket) { socket.emit('act_client', {type: 'connect_message', message: "Connecting to server..", error: false}); - let newConnection = new ircclient(connectiondata, connections[socket.id].host); + let newConnection = new irclib.IRCConnection(connectiondata, config.client, + {authenticationSteps: [new webirc.authenticator(connections[socket.id].host)], ctcps: customCTCPs}); + newConnection.connect(); connections[socket.id][connectiondata.server] = newConnection;