From fa15d400df9fdf51085f98bce0ce8eeac4a3af3e Mon Sep 17 00:00:00 2001 From: qsheets Date: Thu, 24 Jan 2013 18:32:38 -0500 Subject: [PATCH 1/3] Fix length issues when sending long messages Fixes missing message parts when sending long PRIVMSG lines (incl. ACTIONs). Also, maintains 'userhost' string through nick and host mask changes. --- docs/API.rst | 11 ++++++----- lib/codes.js | 4 ++++ lib/irc.js | 36 +++++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/docs/API.rst b/docs/API.rst index c762a405..57a48d25 100644 --- a/docs/API.rst +++ b/docs/API.rst @@ -31,7 +31,7 @@ Client floodProtectionDelay: 1000, stripColors: false, channelPrefixes: "&#", - messageSplit: 512 + messageLength: 512 } `secure` (SSL connection) can be a true value or an object (the kind of object @@ -47,8 +47,9 @@ Client `floodProtectionDelay` sets the amount of time that the client will wait between sending subsequent messages when `floodProtection` is enabled. - `messageSplit` will split up large messages sent with the `say` method - into multiple messages of length fewer than `messageSplit` characters. + `messageLength` sets the character length at which messages sent with `msg` will + be split into multiple messages. This value should not be changed unless the + server explicitly indicates another value. `stripColors` removes mirc colors (0x03 followed by one or two ascii numbers for foreground,background) and ircII "effect" codes (0x02 @@ -348,7 +349,7 @@ Events .. js:data:: '+mode' - `function (channel, by, mode, argument, message) { }` + `function (channel, by, mode, argument, message) { }` Emitted when a mode is added to a user or channel. `channel` is the channel which the mode is being set on/in. `by` is the user setting the mode. `mode` @@ -360,7 +361,7 @@ Events .. js:data:: '-mode' - `function (channel, by, mode, argument, message) { }` + `function (channel, by, mode, argument, message) { }` Emitted when a mode is removed from a user or channel. `channel` is the channel which the mode is being set on/in. `by` is the user setting the mode. `mode` diff --git a/lib/codes.js b/lib/codes.js index cf2c4a1a..18e6126b 100644 --- a/lib/codes.js +++ b/lib/codes.js @@ -315,6 +315,10 @@ module.exports = { // {{{ "name" : "rpl_nousers", "type" : "reply" }, + "396" : { + "name" : "rpl_hosthidden", + "type" : "reply" + }, "401" : { "name" : "err_nosuchnick", "type" : "error" diff --git a/lib/irc.js b/lib/irc.js index 79e96007..537c6736 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -50,9 +50,13 @@ function Client(server, nick, opt) { floodProtectionDelay: 1000, stripColors: false, channelPrefixes: "&#", - messageSplit: 512 + messageLength: 512 }; + // All lines end with CR-LF (2 chars) plus 2 chars for + // server provided padding to be safe. + self.opt.messageLength -= 4; + // Features supported by the server // (initial values are RFC 1459 defaults. Zeros signify // no default or unlimited value) @@ -99,6 +103,7 @@ function Client(server, nick, opt) { // (normally this is because you chose something too long and // the server has shortened it self.nick = message.args[0]; + self.whois(self.nick, self._setUserhost); self.emit('registered', message); break; case "002": @@ -263,9 +268,11 @@ function Client(server, nick, opt) { }); break; case "NICK": - if ( message.nick == self.nick ) + if ( message.nick == self.nick ) { // the user just changed their own nick self.nick = message.args[0]; + self.userhost = self.nick+'!'+self.userhost.split('!')[1]; + } if ( self.opt.debug ) util.log("NICK: " + message.nick + " changes nick to " + message.args[0]); @@ -285,6 +292,9 @@ function Client(server, nick, opt) { // old nick, new nick, channels self.emit('nick', message.nick, message.args[0], channels, message); break; + case "rpl_hosthidden": + self.userhost = self.userhost.split('@')[0]+'@'+message.args[1]; + break; case "rpl_motdstart": self.motd = message.args[1] + "\n"; break; @@ -759,10 +769,11 @@ Client.prototype.part = function(channel, callback) { // {{{ Client.prototype.say = function(target, text) { // {{{ var self = this; if (typeof text !== 'undefined') { + var messageSplit = self.opt.messageLength - (12 + target.length + self.userhost.length); text.toString().split(/\r?\n/).filter(function(line) { return line.length > 0; }).forEach(function(line) { - var r = new RegExp(".{1," + self.opt.messageSplit + "}", "g"); + var r = new RegExp(".{1," + messageSplit + "}", "g"); while ((messagePart = r.exec(line)) != null) { self.send('PRIVMSG', target, messagePart[0]); self.emit('selfMessage', target, messagePart[0]); @@ -770,14 +781,22 @@ Client.prototype.say = function(target, text) { // {{{ }); } } // }}} -Client.prototype.action = function(channel, text) { // {{{ +Client.prototype.action = function(target, text) { // {{{ var self = this; if (typeof text !== 'undefined') { - text.toString().split(/\r?\n/).filter(function(line) { + var messageSplit = self.opt.messageLength - (21 + target.length + self.userhost.length); + var line = text.toString().split(/\r?\n/).filter(function(line) { return line.length > 0; - }).forEach(function(line) { - self.say(channel, '\u0001ACTION ' + line + '\u0001'); }); + + // It would be odd to continue an action over multiple lines as + // only the first would appear as an actual action. So that is + // all we are sending. + if (line[0]) { + var r = new RegExp(".{1," + messageSplit + "}"); + line = r.exec(line[0])[0]; + self.msg(target, '\1ACTION ' + line + '\1'); + } } } // }}} Client.prototype.notice = function(target, text) { // {{{ @@ -812,6 +831,9 @@ Client.prototype._clearWhoisData = function(nick) { // {{{ delete this._whoisData[nick]; return data; } // }}} +Client.prototype._setUserhost = function(info) { // {{{ + this.userhost = info.nick+'!'+info.user+'@'+info.host; +} // }}} Client.prototype._handleCTCP = function(from, to, text, type) { text = text.slice(1) text = text.slice(0, text.indexOf('\1')) From ed0eb790c9802966c4af36c1e4fec6cc28c67b40 Mon Sep 17 00:00:00 2001 From: qsheets Date: Sat, 7 Sep 2013 10:25:54 -0400 Subject: [PATCH 2/3] Add a warning to the log when a multi-line action is found. --- lib/irc.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/irc.js b/lib/irc.js index e2f11992..52048ed6 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -826,6 +826,9 @@ Client.prototype.action = function(target, text) { // {{{ // only the first would appear as an actual action. So that is // all we are sending. if (line[0]) { + if (line[1]) { + util.log("\033[01;31mWARNING: Action over multiple lines, only first line used.\033[0m"); + } var r = new RegExp(".{1," + messageSplit + "}"); line = r.exec(line[0])[0]; self.msg(target, '\1ACTION ' + line + '\1'); @@ -867,7 +870,7 @@ Client.prototype._clearWhoisData = function(nick) { // {{{ Client.prototype._setUserhost = function(info) { // {{{ this.userhost = info.nick+'!'+info.user+'@'+info.host; } // }}} -Client.prototype._handleCTCP = function(from, to, text, type) { +Client.prototype._handleCTCP = function(from, to, text, type, message) { text = text.slice(1) text = text.slice(0, text.indexOf('\1')) var parts = text.split(' ') From 1addea43d91a5ff6aff1aa5bf22d66c37c9fa512 Mon Sep 17 00:00:00 2001 From: qsheets Date: Sat, 7 Sep 2013 10:31:46 -0400 Subject: [PATCH 3/3] Minor Formatting Tabs to spaces --- docs/API.rst | 1 + lib/irc.js | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/API.rst b/docs/API.rst index bdc1381f..0f974cdd 100644 --- a/docs/API.rst +++ b/docs/API.rst @@ -50,6 +50,7 @@ Client Set `sasl` to true to enable SASL support. You'll also want to set `nick`, `userName`, and `password` for authentication. + `messageLength` sets the character length at which messages sent with `msg` will be split into multiple messages. This value should not be changed unless the server explicitly indicates another value. diff --git a/lib/irc.js b/lib/irc.js index 52048ed6..126792fc 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -794,9 +794,9 @@ Client.prototype.part = function(channel, message, callback) { // {{{ } if (message) { - this.send('PART', channel, message); + this.send('PART', channel, message); } else { - this.send('PART', channel); + this.send('PART', channel); } } // }}} Client.prototype.say = function(target, text) { // {{{ @@ -826,9 +826,9 @@ Client.prototype.action = function(target, text) { // {{{ // only the first would appear as an actual action. So that is // all we are sending. if (line[0]) { - if (line[1]) { - util.log("\033[01;31mWARNING: Action over multiple lines, only first line used.\033[0m"); - } + if (line[1]) { + util.log("\033[01;31mWARNING: Action over multiple lines, only first line used.\033[0m"); + } var r = new RegExp(".{1," + messageSplit + "}"); line = r.exec(line[0])[0]; self.msg(target, '\1ACTION ' + line + '\1');