diff --git a/chat/protocols/irc/irc.js b/chat/protocols/irc/irc.js index 6f0a9c494c..79c8cb1eff 100644 --- a/chat/protocols/irc/irc.js +++ b/chat/protocols/irc/irc.js @@ -317,9 +317,12 @@ var GenericIRCConversation = { return; } - // Since the server doesn't send us a message back, just assume the - // message was received and immediately show it. - this.writeMessage(this._account._nickname, aMessage, { outgoing: true }); + // By default the server doesn't send the message back, but this can be + // enabled with the echo-message capability. If this is not enabled, just + // assume the message was received and immediately show it. + if (!this._account._activeCAPs.has("echo-message")) { + this.writeMessage(this._account._nickname, aMessage, { outgoing: true }); + } this._pendingMessage = true; }, @@ -2289,6 +2292,7 @@ function ircProtocol() { ChromeUtils.import("resource:///modules/ircServices.jsm", tempScope); // Extra features. + ChromeUtils.import("resource:///modules/ircEchoMessage.jsm", tempScope); ChromeUtils.import("resource:///modules/ircMultiPrefix.jsm", tempScope); ChromeUtils.import("resource:///modules/ircNonStandard.jsm", tempScope); ChromeUtils.import("resource:///modules/ircSASL.jsm", tempScope); @@ -2312,6 +2316,7 @@ function ircProtocol() { ircHandlers.registerCAPHandler(tempScope.capNotify); // Register extra features. + ircHandlers.registerCAPHandler(tempScope.capEchoMessage); ircHandlers.registerISUPPORTHandler(tempScope.isupportNAMESX); ircHandlers.registerCAPHandler(tempScope.capMultiPrefix); ircHandlers.registerHandler(tempScope.ircNonStandard); diff --git a/chat/protocols/irc/ircBase.jsm b/chat/protocols/irc/ircBase.jsm index c0a52f1377..a249664c83 100644 --- a/chat/protocols/irc/ircBase.jsm +++ b/chat/protocols/irc/ircBase.jsm @@ -32,7 +32,18 @@ var { } = ChromeUtils.import("resource:///modules/ircUtils.jsm"); function privmsg(aAccount, aMessage, aIsNotification) { - let params = { incoming: true, tags: aMessage.tags }; + let params = { tags: aMessage.tags }; + // If the echo-message capability is enabled and the message is from our nick, + // mark it as outgoing. Otherwise, the message is incoming. + if ( + aAccount._activeCAPs.has("echo-message") && + aAccount.normalizeNick(aMessage.origin) == + aAccount.normalizeNick(aAccount._nickname) + ) { + params.outgoing = true; + } else { + params.incoming = true; + } if (aIsNotification) { params.notification = true; } diff --git a/chat/protocols/irc/ircEchoMessage.jsm b/chat/protocols/irc/ircEchoMessage.jsm new file mode 100644 index 0000000000..696535571e --- /dev/null +++ b/chat/protocols/irc/ircEchoMessage.jsm @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * This implements the echo-message capability for IRC. + * https://ircv3.net/specs/extensions/echo-message-3.2 + * + * When enabled, displaying of a sent messages is disabled (until it is received + * by the server and sent back to the sender). This helps to ensure the ordering + * of messages is consistent for all participants in a channel and also helps + * signify whether a message was properly sent to a channel during disconnect. + */ + +this.EXPORTED_SYMBOLS = ["capEchoMessage"]; + +const { ircHandlers } = ChromeUtils.import( + "resource:///modules/ircHandlers.jsm" +); + +var capEchoMessage = { + name: "echo-message CAP", + priority: ircHandlers.DEFAULT_PRIORITY, + isEnabled: () => true, + + commands: { + "echo-message": function(aMessage) { + if ( + aMessage.cap.subcommand === "LS" || + aMessage.cap.subcommand === "NEW" + ) { + this.addCAP("echo-message"); + this.sendMessage("CAP", ["REQ", "echo-message"]); + } else if ( + aMessage.cap.subcommand === "ACK" || + aMessage.cap.subcommand === "NAK" + ) { + this.removeCAP("echo-message"); + } else { + return false; + } + return true; + }, + }, +}; diff --git a/chat/protocols/irc/ircMultiPrefix.jsm b/chat/protocols/irc/ircMultiPrefix.jsm index 30bf4a1932..61f83a8f4a 100644 --- a/chat/protocols/irc/ircMultiPrefix.jsm +++ b/chat/protocols/irc/ircMultiPrefix.jsm @@ -51,7 +51,7 @@ var capMultiPrefix = { this.addCAP("multi-prefix"); this.sendMessage("CAP", ["REQ", "multi-prefix"]); } else if ( - aMessage.cap.subcommand == "ACK" || + aMessage.cap.subcommand === "ACK" || aMessage.cap.subcommand === "NAK" ) { this.removeCAP("multi-prefix"); diff --git a/chat/protocols/irc/ircSASL.jsm b/chat/protocols/irc/ircSASL.jsm index 4e7d258a4b..1d74a58415 100644 --- a/chat/protocols/irc/ircSASL.jsm +++ b/chat/protocols/irc/ircSASL.jsm @@ -169,11 +169,11 @@ var capSASL = { // If it supports SASL, let the server know we're requiring SASL. this.addCAP("sasl"); this.sendMessage("CAP", ["REQ", "sasl"]); - } else if (aMessage.cap.subcommand == "ACK") { + } else if (aMessage.cap.subcommand === "ACK") { // The server acknowledges our choice to use SASL, send the first // message. this.sendMessage("AUTHENTICATE", "PLAIN"); - } else if (aMessage.cap.subcommand == "NAK") { + } else if (aMessage.cap.subcommand === "NAK") { this.removeCAP("sasl"); } diff --git a/chat/protocols/irc/ircServerTime.jsm b/chat/protocols/irc/ircServerTime.jsm index 177bd9d2bc..28df39d37e 100644 --- a/chat/protocols/irc/ircServerTime.jsm +++ b/chat/protocols/irc/ircServerTime.jsm @@ -4,7 +4,7 @@ /* * This implements server-time for IRC. - * http://ircv3.net/specs/extensions/server-time-3.2.html + * https://ircv3.net/specs/extensions/server-time-3.2.html */ this.EXPORTED_SYMBOLS = ["capServerTime", "tagServerTime"]; @@ -52,7 +52,7 @@ var capServerTime = { this.addCAP("server-time"); this.sendMessage("CAP", ["REQ", "server-time"]); } else if ( - aMessage.cap.subcommand == "ACK" || + aMessage.cap.subcommand === "ACK" || aMessage.cap.subcommand === "NAK" ) { this.removeCAP("server-time"); @@ -71,7 +71,7 @@ var capServerTime = { this.addCAP("znc.in/server-time-iso"); this.sendMessage("CAP", ["REQ", "znc.in/server-time-iso"]); } else if ( - aMessage.cap.subcommand == "ACK" || + aMessage.cap.subcommand === "ACK" || aMessage.cap.subcommand === "NAK" ) { this.removeCAP("znc.in/server-time-iso"); diff --git a/chat/protocols/irc/moz.build b/chat/protocols/irc/moz.build index f614fb76c5..9ac655fab9 100644 --- a/chat/protocols/irc/moz.build +++ b/chat/protocols/irc/moz.build @@ -16,6 +16,7 @@ EXTRA_JS_MODULES += [ 'ircCommands.jsm', 'ircCTCP.jsm', 'ircDCC.jsm', + 'ircEchoMessage.jsm', 'ircHandlers.jsm', 'ircISUPPORT.jsm', 'ircMultiPrefix.jsm',