DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (65567743280f)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
/* 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.EXPORTED_SYMBOLS = ["ircHandlers"];

var Cu = Components.utils;

Cu.import("resource:///modules/ircUtils.jsm");

var ircHandlers = {
  /*
   * Object to hold the IRC handlers, each handler is an object that implements:
   *   name        The display name of the handler.
   *   priority    The priority of the handler (0 is default, positive is
   *               higher priority)
   *   isEnabled   A function where 'this' is bound to the account object. This
   *               should reflect whether this handler should be used for this
   *               account.
   *   commands    An object of commands, each command is a function which
   *               accepts a message object and has 'this' bound to the account
   *               object. It should return whether the message was successfully
   *               handler or not.
   */
  _ircHandlers: [],
  // Object to hold the ISUPPORT handlers, expects the same fields as
  // _ircHandlers.
  _isupportHandlers: [],
  // Object to hold the Client Capabilities handlers, expects the same fields as
  // _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;
    }
    if (!("isEnabled" in aHandler)) {
      Cu.reportError(new Error("IRC handlers must have a \"isEnabled\" " +
                               "property: " + aHandler.name));
      return false;
    }

    aArray.push(aHandler);
    aArray.sort((a, b) => b.priority - a.priority);
    return true;
  },

  _unregisterHandler: function(aArray, aHandler) {
    return aArray.filter(h => h.name != aHandler.name);
  },

  registerHandler: function(aHandler) {
    return this._registerHandler(this._ircHandlers, aHandler);
  },
  unregisterHandler: function(aHandler) {
    this._ircHandlers = this._unregisterHandler(this._ircHandlers, aHandler);
  },

  registerISUPPORTHandler: function(aHandler) {
    return this._registerHandler(this._isupportHandlers, aHandler);
  },
  unregisterISUPPORTHandler: function(aHandler) {
    this._isupportHandlers = this._unregisterHandler(this._isupportHandlers,
                                                     aHandler);
  },

  registerCAPHandler: function(aHandler) {
    return this._registerHandler(this._capHandlers, aHandler);
  },
  unregisterCAPHandler: function(aHandler) {
    this._capHandlers = this._unregisterHandler(this._capHandlers, aHandler);
  },

  registerCTCPHandler: function(aHandler) {
    return this._registerHandler(this._ctcpHandlers, aHandler);
  },
  unregisterCTCPHandler: function(aHandler) {
    this._ctcpHandlers = this._unregisterHandler(this._ctcpHandlers, aHandler);
  },

  registerDCCHandler: function(aHandler) {
    return this._registerHandler(this._dccHandlers, aHandler);
  },
  unregisterDCCHandler: function(aHandler) {
    this._dccHandlers = this._unregisterHandler(this._dccHandlers, aHandler);
  },

  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) && 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);
      }
    }

    return false;
  },

  handleMessage: function(aAccount, aMessage) {
    return this._handleMessage(this._ircHandlers, aAccount, aMessage,
                               aMessage.command.toUpperCase());
  },

  handleISUPPORTMessage: function(aAccount, aMessage) {
    return this._handleMessage(this._isupportHandlers, aAccount, aMessage,
                               aMessage.isupport.parameter);
  },

  handleCAPMessage: function(aAccount, aMessage) {
    return this._handleMessage(this._capHandlers, aAccount, aMessage,
                               aMessage.cap.parameter);
  },

  // aMessage is a CTCP Message, which inherits from an IRC Message.
  handleCTCPMessage: function(aAccount, aMessage) {
    return this._handleMessage(this._ctcpHandlers, aAccount, aMessage,
                               aMessage.ctcp.command);
  },

  // aMessage is a DCC Message, which inherits from a CTCP Message.
  handleDCCMessage: function(aAccount, aMessage) {
    return this._handleMessage(this._dccHandlers, aAccount, aMessage,
                               aMessage.ctcp.dcc.type);
  },

  // 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; }
};