Created
September 13, 2016 20:04
-
-
Save freaktechnik/ac12d95b408ac74c127fc8ad4aba50ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Martin Giger <martin@humanoids.be> | |
# Parent b9cd88a0878f441423c99b7335ee393f4c7d1df1 | |
Bug 1302447 - Add tag handling infrastructure r=clokep | |
diff --git a/chat/protocols/irc/irc.js b/chat/protocols/irc/irc.js | |
--- a/chat/protocols/irc/irc.js | |
+++ b/chat/protocols/irc/irc.js | |
@@ -148,16 +148,22 @@ function _setMode(aAddNewMode, aNewModes | |
if (hasMode && !aAddNewMode) | |
this._modes.delete(newMode); | |
// If the mode is not in the list of modes and we want to add it. | |
else if (!hasMode && aAddNewMode) | |
this._modes.add(newMode); | |
} | |
} | |
+function TagMessage(aMessage, aTagName) { | |
+ this.message = aMessage; | |
+ this.tagName = aTagName; | |
+ this.tagValue = aMessage.tags.get(aTagName); | |
+} | |
+ | |
// Properties / methods shared by both ircChannel and ircConversation. | |
var GenericIRCConversation = { | |
_observedNicks: [], | |
// This is set to true after a message is sent to notify the 401 | |
// ERR_NOSUCHNICK handler to write an error message to the conversation. | |
_pendingMessage: false, | |
_waitingForNick: false, | |
@@ -172,16 +178,25 @@ var GenericIRCConversation = { | |
" " + this._account.buildMessage("PRIVMSG", this.name) + | |
" :\r\n"; | |
return this._account.maxMessageLength - | |
this._account.countBytes(baseMessage); | |
}, | |
// Apply CTCP formatting before displaying. | |
prepareForDisplaying: function(aMsg) { | |
aMsg.displayMessage = ctcpFormatToHTML(aMsg.displayMessage); | |
+ | |
+ if("tags" in aMsg && ircHandlers.hasTagHandlers) { | |
+ for (let tag in aMsg.tags) { | |
+ // Unhandled tags may be common, since a tag does not have to be handled | |
+ // with a tag handler, it may also be handled by a message command handler. | |
+ ircHandlers.handleTag(this._account, new TagMessage(aMessage, tag)); | |
+ } | |
+ } | |
+ | |
GenericConversationPrototype.prepareForDisplaying.apply(this, arguments); | |
}, | |
prepareForSending: function(aOutgoingMessage, aCount) { | |
// Split the message by line breaks and send each one individually. | |
let messages = aOutgoingMessage.message.split(/[\r\n]+/); | |
let maxLength = this.getMaxMessageLength(); | |
diff --git a/chat/protocols/irc/ircBase.jsm b/chat/protocols/irc/ircBase.jsm | |
--- a/chat/protocols/irc/ircBase.jsm | |
+++ b/chat/protocols/irc/ircBase.jsm | |
@@ -23,17 +23,17 @@ var {interfaces: Ci, utils: Cu} = Compon | |
Cu.import("resource:///modules/imXPCOMUtils.jsm"); | |
Cu.import("resource:///modules/imServices.jsm"); | |
Cu.import("resource:///modules/ircHandlers.jsm"); | |
Cu.import("resource:///modules/ircUtils.jsm"); | |
Cu.import("resource:///modules/jsProtoHelper.jsm"); | |
function privmsg(aAccount, aMessage, aIsNotification) { | |
- let params = {incoming: true}; | |
+ let params = {incoming: true, tags: aMessage.tags}; | |
if (aIsNotification) | |
params.notification = true; | |
aAccount.getConversation(aAccount.isMUCName(aMessage.params[0]) ? | |
aMessage.params[0] : aMessage.origin) | |
.writeMessage(aMessage.origin, aMessage.params[1], params); | |
return true; | |
} | |
@@ -74,16 +74,17 @@ function leftRoom(aAccount, aNicks, aCha | |
} | |
} | |
return true; | |
} | |
function writeMessage(aAccount, aMessage, aString, aType) { | |
let type = {}; | |
type[aType] = true; | |
+ type.tags = aMessage.tags; | |
aAccount.getConversation(aMessage.origin) | |
.writeMessage(aMessage.origin, aString, type); | |
return true; | |
} | |
// If aNoLastParam is true, the last parameter is not printed out. | |
function serverMessage(aAccount, aMsg, aNoLastParam) { | |
// If we don't want to show messages from the server, just mark it as handled. | |
diff --git a/chat/protocols/irc/ircCTCP.jsm b/chat/protocols/irc/ircCTCP.jsm | |
--- a/chat/protocols/irc/ircCTCP.jsm | |
+++ b/chat/protocols/irc/ircCTCP.jsm | |
@@ -118,17 +118,17 @@ var ctcpBase = { | |
// These represent CTCP commands. | |
commands: { | |
"ACTION": function(aMessage) { | |
// ACTION <text> | |
// Display message in conversation | |
this.getConversation(this.isMUCName(aMessage.params[0]) ? | |
aMessage.params[0] : aMessage.origin) | |
.writeMessage(aMessage.origin, "/me " + aMessage.ctcp.param, | |
- {incoming: true}); | |
+ {incoming: true, tags: aMessage.tags}); | |
return true; | |
}, | |
// Used when an error needs to be replied with. | |
"ERRMSG": function(aMessage) { | |
this.WARN(aMessage.origin + " failed to handle CTCP message: " + | |
aMessage.ctcp.param); | |
return true; | |
@@ -203,17 +203,17 @@ var ctcpBase = { | |
else { | |
// TIME :<human-readable-time-string> | |
// Received a TIME reply, display it. | |
// Remove the : prefix, if it exists and display the result. | |
let time = aMessage.ctcp.param.slice(aMessage.ctcp.param[0] == ":"); | |
this.getConversation(aMessage.origin) | |
.writeMessage(aMessage.origin, | |
_("ctcp.time", aMessage.origin, time), | |
- {system: true}); | |
+ {system: true, tags: aMessage.tags}); | |
} | |
return true; | |
}, | |
// This is commented out since CLIENTINFO automatically returns the | |
// supported CTCP parameters and this is not supported. | |
// A string set by the user (never the client coder) | |
@@ -230,14 +230,15 @@ var ctcpBase = { | |
this.sendCTCPMessage(aMessage.origin, true, "VERSION", version); | |
} | |
else if (aMessage.command == "NOTICE" && aMessage.ctcp.param.length) { | |
// VERSION #:#:# | |
// Received VERSION response, display to the user. | |
let response = _("ctcp.version", aMessage.origin, | |
aMessage.ctcp.param); | |
this.getConversation(aMessage.origin) | |
- .writeMessage(aMessage.origin, response, {system: true}); | |
+ .writeMessage(aMessage.origin, response, | |
+ {system: true, tags: aMessage.tags}); | |
} | |
return true; | |
} | |
} | |
}; | |
diff --git a/chat/protocols/irc/ircHandlers.jsm b/chat/protocols/irc/ircHandlers.jsm | |
--- a/chat/protocols/irc/ircHandlers.jsm | |
+++ b/chat/protocols/irc/ircHandlers.jsm | |
@@ -31,16 +31,19 @@ var ircHandlers = { | |
_capHandlers: [], | |
// Object to hold the CTCP handlers, expects the same fields as _ircHandlers. | |
_ctcpHandlers: [], | |
// Object to hold the DCC handlers, expects the same fields as _ircHandlers. | |
_dccHandlers: [], | |
// Object to hold the Services handlers, expects the same fields as | |
// _ircHandlers. | |
_servicesHandlers: [], | |
+ // Object to hold irc message tag handlers, expects the same fields as | |
+ // _ircHandlers. | |
+ _tagHandlers: [], | |
_registerHandler: function(aArray, aHandler) { | |
// Protect ourselves from adding broken handlers. | |
if (!("commands" in aHandler)) { | |
Cu.reportError(new Error("IRC handlers must have a \"commands\" " + | |
"property: " + aHandler.name)); | |
return false; | |
} | |
@@ -98,26 +101,32 @@ var ircHandlers = { | |
registerServicesHandler: function(aHandler) { | |
return this._registerHandler(this._servicesHandlers, aHandler); | |
}, | |
unregisterServicesHandler: function(aHandler) { | |
this._servicesHandlers = this._unregisterHandler(this._servicesHandlers, | |
aHandler); | |
}, | |
+ registerTagHandler: function(aHandler) { | |
+ return this._registerHandler(this._tagHandlers, aHandler); | |
+ }, | |
+ unregisterTagHandler: function(aHandler) { | |
+ this._tagHandlers = this._unregisterHandler(this._tagHandlers, aHandler); | |
+ }, | |
+ | |
// Handle a message based on a set of handlers. | |
_handleMessage: function(aHandlers, aAccount, aMessage, aCommand) { | |
// Loop over each handler and run the command until one handles the message. | |
for (let handler of aHandlers) { | |
try { | |
// Attempt to execute the command, by checking if the handler has the | |
// command. | |
// Parse the command with the JavaScript account object as "this". | |
- if (handler.isEnabled.call(aAccount) && | |
- Object.prototype.hasOwnProperty.call(handler.commands, aCommand) && | |
+ if (handler.isEnabled.call(aAccount) && aCommand in handler.commands && | |
handler.commands[aCommand].call(aAccount, aMessage)) | |
return true; | |
} catch (e) { | |
// We want to catch an error here because one of our handlers are | |
// broken, if we don't catch the error, the whole IRC plug-in will die. | |
aAccount.ERROR("Error running command " + aCommand + " with handler " + | |
handler.name + ":\n" + JSON.stringify(aMessage), e); | |
} | |
@@ -154,21 +163,28 @@ var ircHandlers = { | |
}, | |
// aMessage is a Services Message. | |
handleServicesMessage: function(aAccount, aMessage) { | |
return this._handleMessage(this._servicesHandlers, aAccount, aMessage, | |
aMessage.serviceName); | |
}, | |
+ // aMessage is a Tag Message. | |
+ handleTag: function(aAccount, aMessage) { | |
+ return this._handleMessage(this._tagHandlers, aAccount, aMessage, | |
+ aMessage.tagName); | |
+ }, | |
+ | |
// Checking if handlers exist. | |
get hasHandlers() { return this._ircHandlers.length > 0; }, | |
get hasISUPPORTHandlers() { return this._isupportHandlers.length > 0; }, | |
get hasCAPHandlers() { return this._capHandlers.length > 0; }, | |
get hasCTCPHandlers() { return this._ctcpHandlers.length > 0; }, | |
get hasDCCHandlers() { return this._dccHandlers.length > 0; }, | |
get hasServicesHandlers() { return this._servicesHandlers.length > 0; }, | |
+ get hasTagHandlers() { return this._tagHandlers.length > 0 }, | |
// Some constant priorities. | |
get LOW_PRIORITY() { return -100; }, | |
get DEFAULT_PRIORITY() { return 0; }, | |
get HIGH_PRIORITY() { return 100; } | |
}; | |
diff --git a/chat/protocols/irc/ircNonStandard.jsm b/chat/protocols/irc/ircNonStandard.jsm | |
--- a/chat/protocols/irc/ircNonStandard.jsm | |
+++ b/chat/protocols/irc/ircNonStandard.jsm | |
@@ -75,17 +75,17 @@ var ircNonStandard = { | |
// message, which falls through to normal NOTICE processing. | |
// Note that if the user's nick is auth this COULD be a notice directed at | |
// them. For reference: moznet sends Auth (previously sent AUTH), freenode | |
// sends *. | |
let isAuth = target == "auth" && this._nickname.toLowerCase() != "auth"; | |
if (!aMessage.params[1].startsWith("***") && !isAuth) { | |
this.getConversation(aMessage.origin) | |
.writeMessage(aMessage.origin, aMessage.params[1], | |
- {incoming: true}); | |
+ {incoming: true, tags: aMessage.tags}); | |
return true; | |
} | |
return false; | |
}, | |
"042": function(aMessage) { // RPL_YOURID (IRCnet) | |
// <nick> <id> :your unique ID |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment