Bug 957918 - Port chat/ changes from Instantbird to comm-central - 7 - Bug 954088 - Configurable alternate IRC nicks, r=aleth.

This commit is contained in:
Patrick Cloke 2013-10-18 07:04:49 -04:00
Родитель b623feed0a
Коммит 14d31165dc
4 изменённых файлов: 162 добавлений и 83 удалений

Просмотреть файл

@ -31,6 +31,7 @@ options.encoding=Character Set
options.quitMessage=Quit message
options.partMessage=Part message
options.showServerTab=Show messages from the server
options.alternateNicks=Alternate nicks
# LOCALIZATION NOTE (ctcp.ping): Semi-colon list of plural forms.
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals

Просмотреть файл

@ -1145,6 +1145,76 @@ ircAccount.prototype = {
}
},
/*
* Generate a new nick to change to if the user requested nick is already in
* use or is otherwise invalid.
*
* First try all the alternate nicks that were chosen by the user, and if none
* of them work, then generate a new nick by:
* 1. If there was not a digit at the end of the nick, append a 1.
* 2. If there was a digit, then increment the number.
* 3. Add leading 0s back on.
* 4. Ensure the nick is an appropriate length.
*/
tryNewNick: function(aOldNick) {
// Split the string on commas, remove whitespace around the nicks and
// remove empty nicks.
let allNicks = this.getString("alternateNicks").split(",")
.map(n => n.trim()).filter(n => !!n);
allNicks.unshift(this._accountNickname);
// If the previously tried nick is in the array and not the last
// element, try the next nick in the array.
let oldIndex = allNicks.indexOf(aOldNick);
if (oldIndex != -1 && oldIndex < allNicks.length - 1) {
let newNick = allNicks[oldIndex + 1];
this.LOG(aOldNick + " is already in use, trying " + newNick);
this.sendMessage("NICK", newNick); // Nick message.
return true;
}
// Separate the nick into the text and digits part.
let nickParts = /^(.+?)(\d*)$/.exec(aOldNick);
let newNick = nickParts[1];
// No nick found from the user's preferences, so just generating one.
// If there is not a digit at the end of the nick, just append 1.
let newDigits = "1";
// If there is a digit at the end of the nick, increment it.
if (nickParts[2]) {
newDigits = (parseInt(nickParts[2], 10) + 1).toString();
// If there are leading 0s, add them back on, after we've incremented (e.g.
// 009 --> 010).
let numLeadingZeros = nickParts[2].length - newDigits.length;
if (numLeadingZeros > 0)
newDigits = "0".repeat(numLeadingZeros) + newDigits;
}
// If the nick will be too long, ensure all the digits fit.
if (newNick.length + newDigits.length > this.maxNicknameLength) {
// Handle the silly case of a single letter followed by all nines.
if (newDigits.length == this.maxNicknameLength)
newDigits = newDigits.slice(1);
newNick = newNick.slice(0, this.maxNicknameLength - newDigits.length);
}
// Append the digits.
newNick += newDigits;
if (this.normalize(newNick) == this.normalize(this._nickname)) {
// The nick we were about to try next is our current nick. This means
// the user attempted to change to a version of the nick with a lower or
// absent number suffix, and this failed.
let msg = _("message.nick.fail", this._nickname);
for each (let conversation in this._conversations)
conversation.writeMessage(this._nickname, msg, {system: true});
return true;
}
this.LOG(aOldNick + " is already in use, trying " + newNick);
this.sendMessage("NICK", newNick); // Nick message.
return true;
},
countBytes: function(aStr) {
// Assume that if it's not UTF-8 then each character is 1 byte.
if (this._encoding != "UTF-8")
@ -1637,7 +1707,8 @@ ircProtocol.prototype = {
"quitmsg": {get label() _("options.quitMessage"),
get default() Services.prefs.getCharPref("chat.irc.defaultQuitMessage")},
"partmsg": {get label() _("options.partMessage"), default: ""},
"showServerTab": {get label() _("options.showServerTab"), default: false}
"showServerTab": {get label() _("options.showServerTab"), default: false},
"alternateNicks": {get label() _("options.alternateNicks"), default: ""}
},
get chatHasTopic() true,

Просмотреть файл

@ -123,46 +123,6 @@ function serverErrorMessage(aAccount, aMessage, aError) {
return writeMessage(aAccount, aMessage, aError, "error")
}
// Try a new nick if the previous tried nick is already in use.
function tryNewNick(aAccount, aMessage) {
let nickParts = /^(.+?)(\d*)$/.exec(aMessage.params[1]);
let newNick = nickParts[1];
// If there was not a digit at the end of the nick, just append 1.
let newDigits = "1";
// If there was a digit at the end of the nick, increment it.
if (nickParts[2]) {
newDigits = (parseInt(nickParts[2], 10) + 1).toString();
// If there were leading 0s, add them back on, after we've incremented (e.g.
// 009 --> 010).
for (let len = nickParts[2].length - newDigits.length; len > 0; --len)
newDigits = "0" + newDigits;
}
// If the nick will be too long, ensure all the digits fit.
if (newNick.length + newDigits.length > aAccount.maxNicknameLength) {
// Handle the silly case of a single letter followed by all nines.
if (newDigits.length == aAccount.maxNicknameLength)
newDigits = newDigits.slice(1);
newNick = newNick.slice(0, aAccount.maxNicknameLength - newDigits.length);
}
// Append the digits.
newNick += newDigits;
if (aAccount.normalize(newNick) == aAccount.normalize(aAccount._nickname)) {
// The nick we were about to try next is our current nick. This means
// the user attempted to change to a version of the nick with a lower or
// absent number suffix, and this failed.
let msg = _("message.nick.fail", aAccount._nickname);
for each (let conversation in aAccount._conversations)
conversation.writeMessage(aAccount._nickname, msg, {system: true});
return true;
}
aAccount.LOG(aMessage.params[1] + " is already in use, trying " + newNick);
aAccount.sendMessage("NICK", newNick); // Nick message.
return true;
}
// See RFCs 2811 & 2812 (which obsoletes RFC 1459) for a description of these
// commands.
var ircBase = {
@ -1234,11 +1194,11 @@ var ircBase = {
},
"433": function(aMessage) { // ERR_NICKNAMEINUSE
// <nick> :Nickname is already in use
return tryNewNick(this, aMessage);
return this.tryNewNick(aMessage.params[1]);
},
"436": function(aMessage) { // ERR_NICKCOLLISION
// <nick> :Nickname collision KILL from <user>@<host>
return tryNewNick(this, aMessage);
return this.tryNewNick(aMessage.params[1]);
},
"437": function(aMessage) { // ERR_UNAVAILRESOURCE
// <nick/channel> :Nick/channel is temporarily unavailable

Просмотреть файл

@ -2,52 +2,99 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/Services.jsm");
let ircBase = {};
Services.scriptloader.loadSubScript("resource:///modules/ircBase.jsm", ircBase);
let irc = {};
Services.scriptloader.loadSubScript("resource:///components/irc.js", irc);
const testData = {
"clokep": "clokep1",
"clokep1": "clokep2",
"clokep10": "clokep11",
"clokep0": "clokep1",
"clokep01": "clokep02",
"clokep09": "clokep10",
// Now put a number in the "first part".
"clo1kep": "clo1kep1",
"clo1kep1": "clo1kep2",
"clo1kep10": "clo1kep11",
"clo1kep0": "clo1kep1",
"clo1kep01": "clo1kep02",
"clo1kep09": "clo1kep10",
// Some to test the max length.
"abcdefghi": "abcdefgh1",
"abcdefgh0": "abcdefgh1",
"abcdefgh9": "abcdefg10",
"a99999999": "a00000000" // You'd expect 100000000, but this is not valid!
};
function run_test() {
add_test(test_tryNewNick);
run_next_test();
const fakeProto = {
id: "fake-proto",
options: {alternateNicks: ""},
_getOptionDefault: function(aOption) this.options[aOption]
}
function test_tryNewNick() {
for (let currentNick in testData) {
let account = {
LOG: function(aStr) {},
maxNicknameLength: 9,
normalize: function(aStr) aStr,
sendMessage: function(aCommand, aNewNick) {
do_check_eq(aNewNick, testData[currentNick]);
}
};
let message = {params: [null, currentNick]};
const testData = {
"clokep": "clokep1",
"clokep1": "clokep2",
"clokep10": "clokep11",
"clokep0": "clokep1",
"clokep01": "clokep02",
"clokep09": "clokep10",
ircBase.tryNewNick(account, message);
// Now put a number in the "first part".
"clo1kep": "clo1kep1",
"clo1kep1": "clo1kep2",
"clo1kep10": "clo1kep11",
"clo1kep0": "clo1kep1",
"clo1kep01": "clo1kep02",
"clo1kep09": "clo1kep10",
// Some to test the max length.
"abcdefghi": "abcdefgh1",
"abcdefgh0": "abcdefgh1",
"abcdefgh9": "abcdefg10",
"a99999999": "a00000000" // You'd expect 100000000, but this is not valid!
};
let account = new irc.ircAccount(fakeProto,
{name: "clokep@instantbird.org"});
account.LOG = function(aStr) {};
account.maxNicknameLength = 9;
account.normalize = function(aStr) aStr;
for (let currentNick in testData) {
account.sendMessage = function(aCommand, aNewNick)
do_check_eq(aNewNick, testData[currentNick]);
account.tryNewNick(currentNick);
}
run_next_test();
}
function test_altNicks() {
const altNicks = ["clokep_", "clokep|"];
const testData = {
// Test account nick.
"clokep": [altNicks, "clokep_"],
// Test first element in list.
"clokep_": [altNicks, "clokep|"],
// Test last element in list.
"clokep|": [altNicks, "clokep|1"],
// Test element not in list with number at end.
"clokep1": [altNicks, "clokep2"],
// Test messy alternatives.
"clokep[": [" clokep ,\n clokep111,,,\tclokep[, clokep_", "clokep_"]
};
let account = new irc.ircAccount(fakeProto,
{name: "clokep@instantbird.org"});
account.LOG = function(aStr) {};
account.maxNicknameLength = 9;
account.normalize = function(aStr) aStr;
for (let currentNick in testData) {
// Only one pref is touched in here, override the default to return
// what this test needs.
account.getString = function(aStr) {
let data = testData[currentNick][0];
if (Array.isArray(data))
return data.join(",");
return data;
};
account.sendMessage = function(aCommand, aNewNick)
do_check_eq(aNewNick, testData[currentNick][1]);
account.tryNewNick(currentNick);
}
run_next_test();
}
function run_test() {
add_test(test_tryNewNick);
add_test(test_altNicks);
run_next_test();
}