From ac102e9d310410f0e027acc7df876fd615bd2bff Mon Sep 17 00:00:00 2001 From: Darren Date: Sat, 10 May 2014 20:38:11 +0100 Subject: [PATCH] Switching the old RPC methods to the websocketrpc --- client/src/models/gateway.js | 239 +++++++++-------------------------- server/client.js | 119 ++++++----------- server/clientcommands.js | 94 +++++++++++--- 3 files changed, 176 insertions(+), 276 deletions(-) diff --git a/client/src/models/gateway.js b/client/src/models/gateway.js index 3210654..7f9d641 100644 --- a/client/src/models/gateway.js +++ b/client/src/models/gateway.js @@ -161,7 +161,6 @@ _kiwi.model.Gateway = function () { */ this.makeIrcConnection = function(connection_info, callback_fn) { var server_info = { - command: 'connect', nick: connection_info.nick, hostname: connection_info.host, port: connection_info.port, @@ -175,7 +174,7 @@ _kiwi.model.Gateway = function () { if (connection_info.options.encoding) server_info.encoding = connection_info.options.encoding; - this.rpc.call('kiwi', server_info, function (err, server_num) { + this.rpc.call('kiwi.connect', server_info, function (err, server_num) { if (!err) { callback_fn && callback_fn(err, server_num); @@ -194,7 +193,7 @@ _kiwi.model.Gateway = function () { this.parseKiwi = function (command, data) { - var client_info_data; + var args; this.trigger('kiwi:' + command, data); this.trigger('kiwi', data); @@ -202,11 +201,10 @@ _kiwi.model.Gateway = function () { switch (command) { case 'connected': // Send some info on this client to the server - client_info_data = { - command: 'client_info', + args = { build_version: _kiwi.global.build_version }; - this.rpc.call('kiwi', client_info_data); + this.rpc.call('kiwi.client_info', args); this.connect_callback && this.connect_callback(); delete this.connect_callback; @@ -214,65 +212,11 @@ _kiwi.model.Gateway = function () { break; } }; - /* - Events: - msg - action - server_connect - options - motd - notice - userlist - nick - join - topic - part - kick - quit - whois - syncchannel_redirect - debug - */ + /** * Parses the response from the server */ this.parse = function (command, data) { - //console.log('gateway event', command, data); - - if (command !== undefined) { - switch (command) { - case 'options': - $.each(data.options, function (name, value) { - switch (name) { - case 'CHANTYPES': - that.set('channel_prefix', value.join('')); - break; - case 'NETWORK': - that.set('name', value); - break; - case 'PREFIX': - that.set('user_prefixes', value); - break; - } - }); - that.set('cap', data.cap); - break; - - /* - case 'sync': - if (_kiwi.gateway.onSync && _kiwi.gateway.syncing) { - _kiwi.gateway.syncing = false; - _kiwi.gateway.onSync(item); - } - break; - */ - - case 'kiwi': - this.emit('_kiwi.' + data.namespace, data.data); - break; - } - } - // Trigger the connection specific events (used by Network objects) if (typeof data.connection_id !== 'undefined') { @@ -286,21 +230,13 @@ _kiwi.model.Gateway = function () { that.trigger(command, data); }; - /** - * Sends data to the server - * @private - * @param {Object} data The data to send - * @param {Function} callback A callback function - */ - this.sendData = function (connection_id, data, callback) { - if (typeof connection_id === 'undefined' || connection_id === null) - connection_id = _kiwi.app.connections.active_connection.get('connection_id'); + this.rpcCall = function(method, connection_id) { + var args = Array.prototype.slice.call(arguments, 0); - var data_buffer = { - connection_id: connection_id, - data: JSON.stringify(data) - }; - this.rpc.call('irc', data_buffer, callback); + if (typeof args[1] === 'undefined' || args[1] === null) + args[1] = _kiwi.app.connections.active_connection.get('connection_id'); + + return this.rpc.call.apply(this.rpc, args); }; /** @@ -310,15 +246,12 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.privmsg = function (connection_id, target, msg, callback) { - var data = { - method: 'privmsg', - args: { - target: target, - msg: msg - } + var args = { + target: target, + msg: msg }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.privmsg', connection_id, args, callback); }; /** @@ -328,15 +261,12 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.notice = function (connection_id, target, msg, callback) { - var data = { - method: 'notice', - args: { - target: target, - msg: msg - } + var args = { + target: target, + msg: msg }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.notice', connection_id, args, callback); }; /** @@ -348,17 +278,14 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.ctcp = function (connection_id, request, type, target, params, callback) { - var data = { - method: 'ctcp', - args: { - request: request, - type: type, - target: target, - params: params - } + var args = { + request: request, + type: type, + target: target, + params: params }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.ctcp', connection_id, args, callback); }; /** @@ -377,29 +304,23 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.join = function (connection_id, channel, key, callback) { - var data = { - method: 'join', - args: { - channel: channel, - key: key - } + var args = { + channel: channel, + key: key }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.join', connection_id, args, callback); }; /** * Retrieves channel information */ this.channelInfo = function (connection_id, channel, callback) { - var data = { - method: 'channel_info', - args: { - channel: channel - } + var args = { + channel: channel }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.channel_info', connection_id, args, callback); }; /** @@ -408,14 +329,11 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.part = function (connection_id, channel, callback) { - var data = { - method: 'part', - args: { - channel: channel - } + var args = { + channel: channel }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.part', connection_id, args, callback); }; /** @@ -425,15 +343,12 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.topic = function (connection_id, channel, new_topic, callback) { - var data = { - method: 'topic', - args: { - channel: channel, - topic: new_topic - } + var args = { + channel: channel, + topic: new_topic }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.topic', connection_id, args, callback); }; /** @@ -444,16 +359,13 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.kick = function (connection_id, channel, nick, reason, callback) { - var data = { - method: 'kick', - args: { - channel: channel, - nick: nick, - reason: reason - } + var args = { + channel: channel, + nick: nick, + reason: reason }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.kick', connection_id, args, callback); }; /** @@ -463,14 +375,12 @@ _kiwi.model.Gateway = function () { */ this.quit = function (connection_id, msg, callback) { msg = msg || ""; - var data = { - method: 'quit', - args: { - message: msg - } + + var args = { + message: msg }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.quit', connection_id, args, callback); }; /** @@ -479,14 +389,11 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.raw = function (connection_id, data, callback) { - data = { - method: 'raw', - args: { - data: data - } + var args = { + data: data }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.raw', connection_id, args, callback); }; /** @@ -495,28 +402,22 @@ _kiwi.model.Gateway = function () { * @param {Function} callback A callback function */ this.changeNick = function (connection_id, new_nick, callback) { - var data = { - method: 'nick', - args: { - nick: new_nick - } + var args = { + nick: new_nick }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.nick', connection_id, args, callback); }; /** * Sets a mode for a target */ this.mode = function (connection_id, target, mode_string, callback) { - data = { - method: 'raw', - args: { - data: 'MODE ' + target + ' ' + mode_string - } + var args = { + data: 'MODE ' + target + ' ' + mode_string }; - this.sendData(connection_id, data, callback); + this.rpcCall('irc.raw', connection_id, args, callback); }; @@ -526,31 +427,11 @@ _kiwi.model.Gateway = function () { * @param {Fucntion} callback A callback function */ this.setEncoding = function (connection_id, new_encoding, callback) { - var data = { - method: 'encoding', - args: { - encoding: new_encoding - } - }; - this.sendData(connection_id, data, callback); - }; - - /** - * Sends data to a fellow Kiwi IRC user - * @param {String} target The nick of the Kiwi IRC user to send to - * @param {String} data The data to send - * @param {Function} callback A callback function - */ - this.kiwi = function (target, data, callback) { - data = { - method: 'kiwi', - args: { - target: target, - data: data - } + var args = { + encoding: new_encoding }; - this.sendData(data, callback); + this.rpcCall('irc.encoding', connection_id, args, callback); }; diff --git a/server/client.js b/server/client.js index 0d27ddb..8a0bc5f 100755 --- a/server/client.js +++ b/server/client.js @@ -34,13 +34,11 @@ var Client = function (websocket) { // Handler for any commands sent from the client this.client_commands = new ClientCommands(this); + this.client_commands.addRpcEvents(this, this.rpc); + + // Handles the kiwi.* RPC functions + this.attachKiwiCommands(); - this.rpc.on('irc', function (response, data) { - handleClientMessage.call(that, data, response); - }); - this.rpc.on('kiwi', function (response, data) { - kiwiCommand.call(that, data, response); - }); websocket.on('close', function () { websocketDisconnect.apply(that, arguments); }); @@ -80,88 +78,45 @@ Client.prototype.dispose = function () { this.removeAllListeners(); }; -function handleClientMessage(msg, callback) { - var that = this, - server; - - // Make sure we have a server number specified - if ((msg.connection_id === null) || (typeof msg.connection_id !== 'number')) { - return (typeof callback === 'function') ? callback('server not specified') : undefined; - } else if (!this.state.irc_connections[msg.connection_id]) { - return (typeof callback === 'function') ? callback('not connected to server') : undefined; - } - - // The server this command is directed to - server = this.state.irc_connections[msg.connection_id]; - - if (typeof callback !== 'function') { - callback = null; - } - - try { - msg.data = JSON.parse(msg.data); - } catch (e) { - kiwi.log('[handleClientMessage] JSON parsing error ' + msg.data); - return; - } - - // Run the client command - global.modules.emit('client command', { - command: msg.data, - server: server - }) - .done(function() { - that.client_commands.run(msg.data.method, msg.data.args, server, callback); - }); -} - - - -function kiwiCommand(command, callback) { - if (typeof callback !== 'function') { - callback = function () {}; - } - switch (command.command) { - case 'connect': - if (command.hostname && command.port && command.nick) { - var options = {}; - - // Get any optional parameters that may have been passed - if (command.encoding) - options.encoding = command.encoding; - - options.password = global.config.restrict_server_password || command.password; - - this.state.connect( - (global.config.restrict_server || command.hostname), - (global.config.restrict_server_port || command.port), - (typeof global.config.restrict_server_ssl !== 'undefined' ? - global.config.restrict_server_ssl : - command.ssl), - command.nick, - {hostname: this.websocket.meta.revdns, address: this.websocket.meta.real_address}, - options, - callback); - } else { - return callback('Hostname, port and nickname must be specified'); - } +Client.prototype.attachKiwiCommands = function() { + var that = this; - break; + this.rpc.on('kiwi.connect', function(callback, command) { + if (command.hostname && command.port && command.nick) { + var options = {}; + + // Get any optional parameters that may have been passed + if (command.encoding) + options.encoding = command.encoding; + + options.password = global.config.restrict_server_password || command.password; + + that.state.connect( + (global.config.restrict_server || command.hostname), + (global.config.restrict_server_port || command.port), + (typeof global.config.restrict_server_ssl !== 'undefined' ? + global.config.restrict_server_ssl : + command.ssl), + command.nick, + {hostname: that.websocket.meta.revdns, address: that.websocket.meta.real_address}, + options, + callback); + } else { + return callback('Hostname, port and nickname must be specified'); + } + }); - case 'client_info': - // keep hold of selected parts of the client_info - this.client_info = { - build_version: command.build_version.toString() || undefined - }; - break; + this.rpc.on('kiwi.client_info', function(callback, args) { + // keep hold of selected parts of the client_info + that.client_info = { + build_version: args.build_version.toString() || undefined + }; + }); +}; - default: - callback(); - } -} // Websocket has disconnected, so quit all the IRC connections diff --git a/server/clientcommands.js b/server/clientcommands.js index d87e13c..e7936ae 100644 --- a/server/clientcommands.js +++ b/server/clientcommands.js @@ -17,6 +17,69 @@ ClientCommands.prototype.run = function (command, args, irc_connection, callback return listeners[command.toUpperCase()](args, irc_connection, callback); }; +ClientCommands.prototype.addRpcEvents = function(client, rpc) { + // Called for each RPC call + // addRpcMethod() below prepends the incoming RPC call with the method name and + // the listener that handles this call, and passes that argument list to moduleEventWrap(). + // This gives us the chance to wrap all calls with connection_id checks and passing + // them off to the module system. + + var moduleEventWrap = function(rpc_method, the_fn, callback, connection_id) { + var connection, rpc_args, fn_args; + + // Make sure we have a connection_id specified + if (!connection_id && connection_id !== 0) { + return callback('server not specified'); + + } else if (!client.state.irc_connections[connection_id]) { + return callback('not connected to server'); + } + + // The server this command is directed to + connection = client.state.irc_connections[connection_id]; + + // Get the arguments for the RPC call only (starts at 4) + rpc_args = Array.prototype.slice.call(arguments, 4); + + global.modules.emit('rpc ' + rpc_method, { + arguments: rpc_args, + client: client, + connection: connection + }) + .done(function() { + // Listeners expect arguments in a (connection, callback, args..n) format, so preppend + // the connection + callback + fn_args = rpc_args.slice(0); + fn_args.unshift(connection, callback); + + the_fn.apply(client, fn_args); + }) + .prevented(function() { + // The RPC call was prevented from running by a module + }); + }; + + // Quick + easier way to call the above function + var addRpcMethod = function(rpc_method, fn) { + rpc.on(rpc_method, _.partial(moduleEventWrap, rpc_method, fn)); + }; + + addRpcMethod('irc.privmsg', listeners.privmsg); + addRpcMethod('irc.ctcp', listeners.ctcp); + addRpcMethod('irc.raw', listeners.raw); + addRpcMethod('irc.join', listeners.join); + addRpcMethod('irc.channel_info', listeners.channel_info); + addRpcMethod('irc.part', listeners.part); + addRpcMethod('irc.topic', listeners.topic); + addRpcMethod('irc.kick', listeners.kick); + addRpcMethod('irc.quit', listeners.quit); + addRpcMethod('irc.notice', listeners.notice); + addRpcMethod('irc.mode', listeners.mode); + addRpcMethod('irc.nick', listeners.nick); + addRpcMethod('irc.kiwi', listeners.kiwi); + addRpcMethod('irc.encoding', listeners.encoding); +}; + @@ -40,12 +103,12 @@ function truncateString(str, block_size) { var listeners = { - PRIVMSG: function (args, irc_connection, callback) { + privmsg: function (irc_connection, callback, args) { // Maximum length of target + message we can send to the IRC server is 500 characters // but we need to leave extra room for the sender prefix so the entire message can // be sent from the IRCd to the target without being truncated. - var blocks = truncateString(args.msg, 350); + blocks.forEach(function (block, idx) { // Apply the callback on the last message only var cb = (idx === blocks.length - 1) ? @@ -57,7 +120,7 @@ var listeners = { }, - CTCP: function (args, irc_connection, callback) { + ctcp: function (irc_connection, callback, args) { if ((args.target) && (args.type)) { if (args.request) { irc_connection.write('PRIVMSG ' + args.target + ' :' + String.fromCharCode(1) + args.type.toUpperCase() + ' ' + args.params + String.fromCharCode(1), callback); @@ -68,12 +131,13 @@ var listeners = { }, - RAW: function (args, irc_connection, callback) { + raw: function (irc_connection, callback, args) { irc_connection.write(args.data, callback); }, - JOIN: function (args, irc_connection, callback) { + join: function (irc_connection, callback, args) { + var channels, keys; if (args.channel) { channels = args.channel.split(","); keys = (args.key) ? args.key.split(",") : []; @@ -84,14 +148,14 @@ var listeners = { }, - CHANNEL_INFO: function (args, irc_connection, callback) { + channel_info: function (irc_connection, callback, args) { if (args.channel) { irc_connection.write('MODE ' + args.channel, callback); } }, - PART: function (args, irc_connection, callback) { + part: function (irc_connection, callback, args) { if (args.channel) { _.each(args.channel.split(","), function (chan) { irc_connection.write('PART ' + chan, callback); @@ -100,7 +164,7 @@ var listeners = { }, - TOPIC: function (args, irc_connection, callback) { + topic: function (irc_connection, callback, args) { if (args.channel) { if (args.topic) { irc_connection.write('TOPIC ' + args.channel + ' :' + args.topic, callback); @@ -111,14 +175,14 @@ var listeners = { }, - KICK: function (args, irc_connection, callback) { + kick: function (irc_connection, callback, args) { if ((args.channel) && (args.nick)) { irc_connection.write('KICK ' + args.channel + ' ' + args.nick + ' :' + args.reason, callback); } }, - QUIT: function (args, irc_connection, callback) { + quit: function (irc_connection, callback, args) { websocket.ircConnection.end('QUIT :' + args.message + '\r\n'); websocket.sentQUIT = true; websocket.ircConnection.destroySoon(); @@ -126,7 +190,7 @@ var listeners = { }, - NOTICE: function (args, irc_connection, callback) { + notice: function (irc_connection, callback, args) { // Maximum length of target + message we can send to the IRC server is 500 characters // but we need to leave extra room for the sender prefix so the entire message can // be sent from the IRCd to the target without being truncated. @@ -143,27 +207,27 @@ var listeners = { }, - MODE: function (args, irc_connection, callback) { + mode: function (irc_connection, callback, args) { if ((args.target) && (args.mode)) { irc_connection.write('MODE ' + args.target + ' ' + args.mode + ' ' + args.params, callback); } }, - NICK: function (args, irc_connection, callback) { + nick: function (irc_connection, callback, args) { if (args.nick) { irc_connection.write('NICK ' + args.nick, callback); } }, - KIWI: function (args, irc_connection, callback) { + kiwi: function (irc_connection, callback, args) { if ((args.target) && (args.data)) { irc_connection.write('PRIVMSG ' + args.target + ': ' + String.fromCharCode(1) + 'KIWI ' + args.data + String.fromCharCode(1), callback); } }, - ENCODING: function (args, irc_connection, callback) { + encoding: function (irc_connection, callback, args) { if (args.encoding) { return callback(irc_connection.setEncoding(args.encoding)); } -- 2.25.1