From c6b5e668f5334dc59d9488c107534907ed989b28 Mon Sep 17 00:00:00 2001 From: Jack Allnutt Date: Wed, 13 Jul 2011 19:27:56 +0100 Subject: [PATCH] Passes jslint with regexp: true, confusion: true, undef: false, node: true, sloppy: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 WHOIS, NAMES, PING, 001 and 005 handlers. --- node/kiwi.js | 148 ++++++++++++++++++++++++++++++++++++----- node/underscore.min.js | 27 ++++++++ 2 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 node/underscore.min.js diff --git a/node/kiwi.js b/node/kiwi.js index 17f593f..a36f6c7 100644 --- a/node/kiwi.js +++ b/node/kiwi.js @@ -1,38 +1,150 @@ var tls = require('tls'), - net = require("net"), + net = require('net'), http = require('http'), - ws = require("socket.io"); + ws = require('socket.io'), + _ = require('./underscore.min.js'); + +var ircNumerics = { + RPL_WHOISUSER: 311, + RPL_WHOISSERVER: 312, + RPL_WHOISOPERATOR: 313, + RPL_WHOISIDLE: 317, + RPL_ENDOFWHOIS: 318, + RPL_WHOISCHANNELS: 319, + RPL_NAMEREPLY: 353, + RPL_ENDOFNAMES: 366, + RPL_MOTD: 372, + RPL_WHOISMODES: 379 +}; + + +var parseIRCMessage = function (websocket, ircSocket, data) { + var msg, regex, opts, options, opt, i, j, matches, nick, users, chan, params, prefix, prefixes, nicklist; + regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@([a-z0-9\.\-:]+)) )?([a-z0-9]+)(?:(?: ([^:]+))?(?: :(.+))?)$/i; + msg = regex.exec(data); + if (msg) { + msg = { + prefix: msg[1], + nick: msg[2], + ident: msg[3], + hostname: msg[4], + command: msg[5], + params: msg[6] || '', + trailing: (msg[7]) ? msg[7].trim() : '' + }; + switch (msg.command.toUpperCase()) { + case 'PING': + ircSocket.write('PONG ' + msg.trailing + '\r\n'); + break; + case '001': + websocket.emit('message', {event: 'connect', connected: true, host: null}); + break; + case '005': + opts = msg.params.split(" "); + options = []; + for (i = 0; i < opts.length; i++) { + opt = opts[i].split("=", 2); + opt[0] = opt[0].toUpperCase(); + ircSocket.ircServer.options[opt[0]] = opt[1] || true; + if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES'], opt[0])) { + if (opt[0] === 'PREFIX') { + regex = /\(([^)]*)\)(.*)/; + matches = regex.exec(opt[1]); + if ((matches) && (matches.length === 3)) { + options[opt[0]] = {}; + for (j = 0; j < matches[2].length; j++) { + options[opt[0]][matches[2].charAt(j)] = matches[1].charAt(j); + } + } + } + } + } + websocket.emit('message', {event: 'options', server: '', "options": options}); + break; + case ircNumerics.RPL_WHOISUSER: + case ircNumerics.RPL_WHOISSERVER: + case ircNumerics.RPL_WHOISOPERATOR: + case ircNumerics.RPL_WHOISIDLE: + case ircNumerics.RPL_ENDOFWHOIS: + case ircNumerics.RPL_WHOISCHANNELS: + case ircNumerics.RPL_WHOISMODES: + websocket.emit('message', {event: 'whois', server: '', nick: msg.params.split(" ", 3)[1], "msg": msg.trailing}); + break; + case ircNumerics.RPL_MOTD: + websocket.emit('message', {event: 'motd', server: '', "msg": msg.trailing}); + break; + case ircNumerics.RPL_NAMEREPLY: + params = msg.params.split(" "); + nick = params[0]; + chan = params[2]; + users = msg.trailing.split(" "); + prefixes = _.values(ircSocket.ircServer.options.PREFIX); + _.each(users, function (user) { + if (_.include(prefix, user.charAt(0))) { + prefix = user.charAt(0); + user = user.substring(1); + nicklist[user] = prefix; + } + if (i >= 50) { + websocket.emit('message', {event: 'userlist', server: '', "users": nicklist, channel: chan}); + nicklist = {}; + i = 0; + } + i++; + }); + if (nicklist.length > 0) { + websocket.emit('message', {event: 'userlist', server: '', "users": nicklist, channel: chan}); + } + break; + case RPL_ENDOFNAMES: + chan = msg.params.split(" ")[1]; + websocket.emit('message', {event: 'userlist_end', server: '', channel: chan}); + break; + } + } else { + console.log("Unknown command.\r\n"); + } +}; //setup websocket listener -io = ws.listen(7777); -io.sockets.on('connection',function(websocket) { - websocket.on('irc connect',function(nick,host,port,ssl,callback) { - console.log(websocket); +var io = ws.listen(7777); +io.sockets.on('connection', function (websocket) { + websocket.on('irc connect', function (nick, host, port, ssl, callback) { + var ircSocket, i; //setup IRC connection - if(!ssl) { - ircSocket = net.createConnection(port,host); - } - else { - ircSocket = tls.connect(port,host); + if (!ssl) { + ircSocket = net.createConnection(port, host); + } else { + ircSocket = tls.connect(port, host); } ircSocket.setEncoding('ascii'); + ircSocket.ircServer = {options: {}}; - ircSocket.on('data',function(data) { - console.log(data); + ircSocket.on('data', function (data) { + data = data.split("\r\n"); + for (i = 0; i < data.length; i++) { + if (data[i]) { + console.log(data[i] + '\r\n'); + parseIRCMessage(websocket, ircSocket, data[i]); + } + } }); // Send the login data - ircSocket.write('NICK '+nick+'\r\n'); - ircSocket.write('USER '+nick+'_kiwi 0 0 :'+nick+'\r\n'); + ircSocket.write('NICK ' + nick + '\r\n'); + ircSocket.write('USER ' + nick + '_kiwi 0 0 :' + nick + '\r\n'); - if((callback)&&(typeof(callback) == 'function')) { + if ((callback) && (typeof (callback) === 'function')) { callback(); } }); - websocket.on('message',function(msg,callback) { + websocket.on('message', function (msg, callback) { console.log(msg); - if((callback)&&(typeof(callback) == 'function')) { + if ((callback) && (typeof (callback) === 'function')) { callback(); } }); }); + + + diff --git a/node/underscore.min.js b/node/underscore.min.js new file mode 100644 index 0000000..d5b4f47 --- /dev/null +++ b/node/underscore.min.js @@ -0,0 +1,27 @@ +// Underscore.js 1.1.6 +// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){var p=this,C=p._,m={},i=Array.prototype,n=Object.prototype,f=i.slice,D=i.unshift,E=n.toString,l=n.hasOwnProperty,s=i.forEach,t=i.map,u=i.reduce,v=i.reduceRight,w=i.filter,x=i.every,y=i.some,o=i.indexOf,z=i.lastIndexOf;n=Array.isArray;var F=Object.keys,q=Function.prototype.bind,b=function(a){return new j(a)};typeof module!=="undefined"&&module.exports?(module.exports=b,b._=b):p._=b;b.VERSION="1.1.6";var h=b.each=b.forEach=function(a,c,d){if(a!=null)if(s&&a.forEach===s)a.forEach(c,d);else if(b.isNumber(a.length))for(var e= +0,k=a.length;e=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a, +c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;bd?1:0}),"value")};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c), +e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=F||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)l.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a, +b.identity)};b.functions=b.methods=function(a){return b.filter(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a){h(f.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){h(f.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,c){if(a===c)return!0;var d=typeof a;if(d!= +typeof c)return!1;if(a==c)return!0;if(!a&&c||a&&!c)return!1;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return!1;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return!1;if(a.length&&a.length!==c.length)return!1;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return!1; +for(var f in a)if(!(f in c)||!b.isEqual(a[f],c[f]))return!1;return!0};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(l.call(a,c))return!1;return!0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=n||function(a){return E.call(a)==="[object Array]"};b.isArguments=function(a){return!(!a||!l.call(a,"callee"))};b.isFunction=function(a){return!(!a||!a.constructor||!a.call||!a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)}; +b.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===!0||a===!1};b.isDate=function(a){return!(!a||!a.getTimezoneOffset||!a.setUTCFullYear)};b.isRegExp=function(a){return!(!a||!a.test||!a.exec||!(a.ignoreCase||a.ignoreCase===!1))};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){p._=C;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e= +0;e/g,interpolate:/<%=([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate|| +null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return c?d(c):d};var j=function(a){this._wrapped=a};b.prototype=j.prototype;var r=function(a,c){return c?b(a).chain():a},H=function(a,c){j.prototype[a]=function(){var a=f.call(arguments);D.call(a,this._wrapped);return r(c.apply(b,a),this._chain)}};b.mixin(b);h(["pop","push","reverse","shift","sort", +"splice","unshift"],function(a){var b=i[a];j.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});h(["concat","join","slice"],function(a){var b=i[a];j.prototype[a]=function(){return r(b.apply(this._wrapped,arguments),this._chain)}});j.prototype.chain=function(){this._chain=!0;return this};j.prototype.value=function(){return this._wrapped}})(); + -- 2.25.1