diff --git a/src/models/network.js b/src/models/network.js index c3b48306..407eb618 100644 --- a/src/models/network.js +++ b/src/models/network.js @@ -19,6 +19,7 @@ const filteredFromClient = { irc: true, password: true, ignoreList: true, + keepNick: true, }; function Network(attr) { @@ -43,6 +44,7 @@ function Network(attr) { }, chanCache: [], ignoreList: [], + keepNick: null, }); if (!this.uuid) { @@ -188,6 +190,7 @@ Network.prototype.edit = function(client, args) { const oldNick = this.nick; const oldRealname = this.realname; + this.keepNick = null; this.nick = args.nick; this.host = String(args.host || ""); this.name = String(args.name || "") || this.host; @@ -217,7 +220,7 @@ Network.prototype.edit = function(client, args) { if (this.nick !== oldNick) { if (connected) { // Send new nick straight away - this.irc.raw("NICK", this.nick); + this.irc.changeNick(this.nick); } else { this.irc.options.nick = this.irc.user.nick = this.nick; @@ -269,6 +272,10 @@ Network.prototype.setNick = function(nick) { // Case insensitive search "i" ); + + if (this.keepNick === nick) { + this.keepNick = null; + } }; /** diff --git a/src/plugins/inputs/nick.js b/src/plugins/inputs/nick.js index a154061b..557f2e80 100644 --- a/src/plugins/inputs/nick.js +++ b/src/plugins/inputs/nick.js @@ -41,16 +41,27 @@ exports.input = function(network, chan, cmd, args) { return; } + // If we were trying to keep a nick and user changes nick, stop trying to keep the old one + network.keepNick = null; + // If connected to IRC, send to server and wait for ACK // otherwise update the nick and UI straight away - if (network.irc && network.irc.connection) { - network.irc.raw("NICK", newNick); - } else { - network.setNick(newNick); + if (network.irc) { + if (network.irc.connection && network.irc.connection.connected) { + network.irc.changeNick(newNick); - this.emit("nick", { - network: network.uuid, - nick: newNick, - }); + return; + } + + network.irc.options.nick = network.irc.user.nick = newNick; } + + network.setNick(newNick); + + this.emit("nick", { + network: network.uuid, + nick: newNick, + }); + + this.save(); }; diff --git a/src/plugins/irc-events/connection.js b/src/plugins/irc-events/connection.js index 572e72ac..6984a644 100644 --- a/src/plugins/irc-events/connection.js +++ b/src/plugins/irc-events/connection.js @@ -124,6 +124,19 @@ module.exports = function(irc, network) { ); } + if (network.keepNick) { + // We disconnected without getting our original nick back yet, just set it back locally + irc.options.nick = irc.user.nick = network.keepNick; + + network.setNick(network.keepNick); + network.keepNick = null; + + this.emit("nick", { + network: network.uuid, + nick: network.nick, + }); + } + sendStatus(); }); diff --git a/src/plugins/irc-events/error.js b/src/plugins/irc-events/error.js index 98dedfaf..56c49cfc 100644 --- a/src/plugins/irc-events/error.js +++ b/src/plugins/irc-events/error.js @@ -44,10 +44,22 @@ module.exports = function(irc, network) { }); irc.on("nick in use", function(data) { + let message = data.nick + ": " + (data.reason || "Nickname is already in use."); + + if (irc.connection.registered === false && !Helper.config.public) { + message += " An attempt to use it will be made when this nick quits."; + + // Clients usually get nick in use on connect when reconnecting to a network + // after a network failure (like ping timeout), and as a result of that, + // TL will append a random number to the nick. + // keepNick will try to set the original nick name back if it sees a QUIT for that nick. + network.keepNick = irc.user.nick; + } + const lobby = network.channels[0]; const msg = new Msg({ type: Msg.Type.ERROR, - text: data.nick + ": " + (data.reason || "Nickname is already in use."), + text: message, showInActive: true, }); lobby.pushMessage(client, msg, true); diff --git a/src/plugins/irc-events/quit.js b/src/plugins/irc-events/quit.js index c8771cb4..13ff2a8c 100644 --- a/src/plugins/irc-events/quit.js +++ b/src/plugins/irc-events/quit.js @@ -27,5 +27,11 @@ module.exports = function(irc, network) { chan: chan.id, }); }); + + // If user with the nick we are trying to keep has quit, try to get this nick + if (network.keepNick === data.nick) { + irc.changeNick(network.keepNick); + network.keepNick = null; + } }); };