<commit_before>/**
  * @overview OAuth2 library for Emberjs that stores tokens in the browsers localStorage
  * @license   Licensed under MIT license
  *            See https://raw.github.com/amkirwan/ember-oauth2/master/LICENSE
  * @version   0.2.4
  */
(function() {
/**
 * @module ember.oauth2
 */

  if (Ember.OAuth2 === undefined) {
    /**
     * @namespace Ember
     * @class Oauth2
     * @extends Ember.Object
     * @uses Ember.Evented
     * @static
     */
    Ember.OAuth2 = Ember.Object.extend(Ember.Evented, {

      /**
       * Initializes the Ember.OAuth2 object when using Ember.OAuth2.create({providerId: 'providerId'}). The following options are available for the configuring a provider: clientId, authBaseUri, redirectUri, scope, statePrefix and tokenPrefix. The clientId, authBaseUri and redirectUri are required. The statePrefix has a default value of 'state' and the tokenPrefix has a default value of 'token'.
       *
       * @method init
       */
      init: function() {
        this._super();
        /**
         * The configuration object for the given provider id.
         *  @property {Object} providerConfig
         *  @property {Object} providerConfig.providerId **Required**
         *  @property {String} providerConfig.providerId.clientId **Required**
         *  @property {String} providerConfig.providerId.authBaseUri **Required**
         *  @property {String} providerConfig.providerId.redirectUri **Required**
         *  @property {String} providerConfig.providerId.scope **Optional**
         *  @property {String} providerConfig.providerId.statePrefix **Default:** "state", **Optional**
         *  @property {String} providerConfig.providerId.tokenPrefix **Default:** "prefix", **Optional**
         *  @example
         *    App.oauth = Ember.OAuth2.create({providerId: 'google'});
         */
        this.providerConfig = Ember.OAuth2.config[this.get('providerId')];
        /**
         * The prefix name for the state key stored in the localStorage.
         *
         * @property statePrefix
         * @type String
         * @default "state"
         */
        this.set('statePrefix', 'state');
        /**
         * The prefix name for the token key stored in the localStorage.
         *
         * @property tokenPrefix
         * @type String
         * @default "token"
         */
        this.set('tokenPrefix', 'token');

        /**
         * @property {String} clientId
         */
        /**
         * @property {String} authBaseUri
         */
        /**
         * @property {String} redirectUri
         */
        /**
         * @property {String} scope
         */
        // sets the properties from the providerConfig and overrides any default settings.
        this.setProperties(this.providerConfig);

        // Bind deprecated event handlers
        /**
         * @event redirect
         * @param {function} The function that handles the redirect.
         */
        this.on('redirect', this.handleRedirect);

        /**
         * @event success
         * @param {function} The function that handles the success callback.
         */
        this.on('success', this._onSuccess);

        /**
         * @event error
         * @param {function} The function that handles the error callback.
         */
        this.on('error', this._onError);
      },

      /**
       * @method version
       * @return {String} The current version number of Ember.OAuth2
       */
      version: function() {
        return Ember.OAuth2.version;
      },

      /**
       * @method uuid
       * @return {String} A pseudo random uuid
       */
      uuid: function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
              var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
                  return v.toString(16);
        });
      },

      /**
       * @method now
       * @return {Number} The current time in seconds rounded
       */
      now: function() {
        return Math.round(new Date().getTime()/1000.0);
      },

      /**
       * Creates and returns the request object.
       *
       * @method requestObj
       * @return {Object} request object
       */
      requestObj: function() {
        var request = { 'response_type': 'token' };
        request.providerId = this.providerId;
        request.state = this.get('state');
        request.client_id = this.clientId;
        request.state = this.get('state');
        if (this.scope) request.scope = this.scope;
        return request;
      },

      /**
       * @method authUri
       * @return {String} Authorization uri for generating an OAuth2 token
       */
      authUri: function() {
        if (this.get('state') === null) this.set('state', this.uuid());
        var uri = this.authBaseUri;
        uri += '?response_type=token' +
            '&redirect_uri=' + encodeURIComponent(this.redirectUri) +
            '&client_id=' + encodeURIComponent(this.clientId) +
            '&state=' + encodeURIComponent(this.get('state'));
        if (this.scope) uri += '&scope=' + encodeURIComponent(this.scope).replace('%20', '+');
        return uri;
      },

      /**
       * Open authorize window if the configuration object is valid.
       *
       * @method authorize
       */
      authorize: function() {
        if (!this.providerId) throw new Error('No provider id given.');
        if (!this.clientId) throw new Error('No client id given.');
        if (!this.authBaseUri) throw new Error('No auth base uri given.');
        if (!this.redirectUri) throw new Error('No redirect uri given.');
        var authorizeUri = this.authUri();
        this.clearStates();
        this.saveState(this.get('state'), this.requestObj());
        var dialog = window.open(authorizeUri, 'Authorize', 'height=600, width=450');
        if (window.focus) dialog.focus();
      },

      /**
        @method authSuccess
        @param {Object} The params returned from the OAuth2 callback
        @return {String} the access_token from the params
      */
      authSuccess: function(params) {
        return params.access_token;
      },

      /**
       * Token properties
       * providerId
       * expiresIn
       * scope
       * token

        @method generateToken
        @return {Object} The access_token object with info about the token
       */
      generateToken: function(params) {
        var token = {};
        token.provider_id = this.providerId;
        token.expires_in = this.expiresIn(params.expires_in);
        token.scope = this.scope;
        token.access_token = params.access_token;
        return token;
      },

      /**
        @method expiresIn
        @return {Number} When the token expires in seconds.
      */
      expiresIn: function(expires) {
        return this.now() + parseInt(expires, 10);
      },

      /**
       * call on redirect from OAuth2 provider response
        @method onRedirect
        @deprecated Use `.trigger('redirect')` instead.
       */
      onRedirect: function(hash, callback) {
        Ember.Logger.warn("Ember.OAuth2.onRedirect is deprecated. Please use .trigger('redirect') instead.");
        this.trigger('redirect', hash, callback);
      },

      /*
       * proxy functions for old event handlers
       *
       * Check if the token returned is valid and if so trigger `success` event else trigger `error`
       *
       * @method handleRedirect
       */
      handleRedirect: function(hash, callback) {
        var params = this.parseCallback(hash);
        if (this.authSuccess(params)) {
          var stateObj = this.getState(params.state);
          this.checkState(stateObj);
          this.saveToken(this.generateToken(params));
          this.trigger('success', stateObj);
        } else {
          this.trigger('error', params);
        }
        if (callback && typeof(callback) === "function") {
          callback();
        }
      },

      /**
       * This method will call the old onSuccess callback when using the old API: Ember.OAuth2.reopen({ onSuccess: function() { return 'hello, onSuccess' } });
       *
       * The old onSuccess method will only be called when onSuccess is defined as a function on the Ember.OAuth2 instance
       *
       * @method _onSuccess
       * @param {Object} stateObj
       * @private
       */
      _onSuccess: function(stateObj) {
        if (typeof(this.onSuccess) !== 'function')
          return;

        Ember.Logger.warn("Ember.OAuth2.onSuccess is deprecated. Bind your callbacks using .on('success', fn) instead.");
        this.onSuccess(stateObj);
      },

      /**
       * This method will call the old onError callback when using the old API: Ember.OAuth2.reopen({ onError: function() { return 'hello, onError' } });
       *
       * The old onSuccess method will only be called when onError is defined as a function on the Ember.OAuth2 instance
       *
       * @method _onError
       * @param {Object} err object
       * @private
       */
      _onError: function(err) {
        if (typeof(this.onError) !== 'function')
          return;

        Ember.Logger.warn("Ember.OAuth2.onError is deprecated. Bind your callbacks using .on('error', fn) instead.");
        this.onError(err);
      },

      /**
       * Checks if the State returned from the server matches the state that was generated in the original request and saved in the browsers localStorage.
       *
       * @method checkState
       * @param {Object} stateObj The object returned from localStorage
       */
      checkState: function(stateObj) {
        if (!stateObj) throw new Error("Could not find state.");
        if (stateObj.state !== this.get('state')) throw new Error("State returned from the server did not match the local saved state.");
      },

      /**
       * Parse the callback function from the OAuth2 provider
       *
       * callback should have the following params if authentication is successful
       * state
       * access_token
       * token_type
       * expires_in
       *
       * @method parseCalback
       * @param {String} locationHash
       * @return {Object} The params returned from the OAuth2 provider
       */
      parseCallback: function(locationHash) {
        var oauthParams = {};
        var queryString = locationHash.substring(1);
        var regex = /([^#?&=]+)=([^&]*)/g;
        var match;
        while ((match = regex.exec(queryString)) !== null) {
          oauthParams[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        }
        return oauthParams;
      },

      /**
       * @method saveState
       * @param {String} state The state uuid
       * @param {Object} requestObj Properties of the request state to save in localStorage
       */
      saveState: function(state, requestObj) {
        window.localStorage.setItem(this.statePrefix + '-' + state, JSON.stringify(requestObj));
      },

      /**
       * Return the saved state and remove it from the localStoage.
       *
       * @method getState
       * @param {String} state The state uuid to retreive from localStorage
       * @return {Object} Properties of the request state
       */
      getState: function(state) {
        var obj = JSON.parse(window.localStorage.getItem(this.statePrefix + '-'  + state));
        window.localStorage.removeItem(this.statePrefix + '-' + state);

        return obj;
      },

      /**
        * Remove any states from localStorage if they exist
        * @method clearStates
        */
      clearStates: function() {
        var regex = new RegExp( '^' + this.statePrefix + '-.*', 'g');

        for(var i = 0; i < window.localStorage.length; i++) {
          var name = window.localStorage.key(i);
          while (regex.exec(name)) {
            window.localStorage.removeItem(name);
          }
        }
      },

      /**
       * saveToken stores the token by the tokenPrefix and the providerId
       * access_token
       * expires : time that the token expires
       * providerId: the providerId
       * scopes: array of scopes
       *
       * @method saveToken
       * @param {Object} token Saves the params in the response from the OAuth2 server to localStorage with the key 'tokenPrefix-providerId
       */
      saveToken: function(token) {
        window.localStorage.setItem(this.tokenPrefix + '-' + this.providerId, JSON.stringify(token));
      },

      /**
       * @method getToken
       * @return {Object} The params from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
       */
      getToken: function() {
        var token = JSON.parse(window.localStorage.getItem( this.tokenPrefix + '-' + this.providerId));
        if (!token) return null;
        if (!token.access_token) return null;
        return token;
      },

      /**
       * @method getAccessToken
       * @return {Object} The access_token param from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
       */
      getAccessToken: function() {
        var token = this.getToken();
        if (!token) return null;
        return token.access_token;
      },

      /**
       * @method accessTokenIsExpired
       * @return {Boolean} Check if the access_token is expired.
       */
      accessTokenIsExpired: function() {
        var token = this.getToken();
        if (!token) return true;
        if (this.now() >= token.expires_in) {
          return true;
        } else {
          return false;
        }
      },

      /**
       * Sets the access token expires_in time to 0 and saves the token to localStorage
       * @method expireAccessToken
       */
      expireAccessToken: function() {
        var token = this.getToken();
        if (!token) return null;
        token.expires_in = 0;
        this.saveToken(token);
      },
    });
  }

  /**
   * @property {String} VERSION
   * @final
  */
  var VERSION = "0.2.4";
  /**
   * @method version
   * @static
   */
  Ember.OAuth2.version = VERSION;
  /**
   * @method config
   * @static
  */
  Ember.OAuth2.config = {};

})(this);
<commit_msg>use get to retreive properties<commit_after>/**
  * @overview OAuth2 library for Emberjs that stores tokens in the browsers localStorage
  * @license   Licensed under MIT license
  *            See https://raw.github.com/amkirwan/ember-oauth2/master/LICENSE
  * @version   0.2.4
  */
(function() {
/**
 * @module ember.oauth2
 */

  if (Ember.OAuth2 === undefined) {
    /**
     * @namespace Ember
     * @class Oauth2
     * @extends Ember.Object
     * @uses Ember.Evented
     * @static
     */
    Ember.OAuth2 = Ember.Object.extend(Ember.Evented, {

      /**
       * Initializes the Ember.OAuth2 object when using Ember.OAuth2.create({providerId: 'providerId'}). The following options are available for the configuring a provider: clientId, authBaseUri, redirectUri, scope, statePrefix and tokenPrefix. The clientId, authBaseUri and redirectUri are required. The statePrefix has a default value of 'state' and the tokenPrefix has a default value of 'token'.
       *
       * @method init
       */
      init: function() {
        this._super();
        /**
         * The configuration object for the given provider id.
         *  @property {Object} providerConfig
         *  @property {Object} providerConfig.providerId **Required**
         *  @property {String} providerConfig.providerId.clientId **Required**
         *  @property {String} providerConfig.providerId.authBaseUri **Required**
         *  @property {String} providerConfig.providerId.redirectUri **Required**
         *  @property {String} providerConfig.providerId.scope **Optional**
         *  @property {String} providerConfig.providerId.statePrefix **Default:** "state", **Optional**
         *  @property {String} providerConfig.providerId.tokenPrefix **Default:** "prefix", **Optional**
         *  @example
         *    App.oauth = Ember.OAuth2.create({providerId: 'google'});
         */
        this.providerConfig = Ember.OAuth2.config[this.get('providerId')];
        /**
         * The prefix name for the state key stored in the localStorage.
         *
         * @property statePrefix
         * @type String
         * @default "state"
         */
        this.set('statePrefix', 'state');
        /**
         * The prefix name for the token key stored in the localStorage.
         *
         * @property tokenPrefix
         * @type String
         * @default "token"
         */
        this.set('tokenPrefix', 'token');

        /**
         * @property {String} clientId
         */
        /**
         * @property {String} authBaseUri
         */
        /**
         * @property {String} redirectUri
         */
        /**
         * @property {String} scope
         */
        // sets the properties from the providerConfig and overrides any default settings.
        this.setProperties(this.providerConfig);

        // Bind deprecated event handlers
        /**
         * @event redirect
         * @param {function} The function that handles the redirect.
         */
        this.on('redirect', this.handleRedirect);

        /**
         * @event success
         * @param {function} The function that handles the success callback.
         */
        this.on('success', this._onSuccess);

        /**
         * @event error
         * @param {function} The function that handles the error callback.
         */
        this.on('error', this._onError);
      },

      /**
       * @method version
       * @return {String} The current version number of Ember.OAuth2
       */
      version: function() {
        return Ember.OAuth2.version;
      },

      /**
       * @method uuid
       * @return {String} A pseudo random uuid
       */
      uuid: function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
              var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
                  return v.toString(16);
        });
      },

      /**
       * @method now
       * @return {Number} The current time in seconds rounded
       */
      now: function() {
        return Math.round(new Date().getTime()/1000.0);
      },

      /**
       * Creates and returns the request object.
       *
       * @method requestObj
       * @return {Object} request object
       */
      requestObj: function() {
        var request = { 'response_type': 'token' };
        request.providerId = this.get('providerId');
        request.state = this.get('state');
        request.client_id = this.get('clientId');
        request.state = this.get('state');
        if (this.get('scope')) request.scope = this.get('scope');
        return request;
      },

      /**
       * @method authUri
       * @return {String} Authorization uri for generating an OAuth2 token
       */
      authUri: function() {
        if (this.get('state') === null) this.set('state', this.uuid());
        var uri = this.get('authBaseUri');
        uri += '?response_type=token' +
            '&redirect_uri=' + encodeURIComponent(this.get('redirectUri')) +
            '&client_id=' + encodeURIComponent(this.get('clientId')) +
            '&state=' + encodeURIComponent(this.get('state'));
        if (this.get('scope')) uri += '&scope=' + encodeURIComponent(this.get('.scope')).replace('%20', '+');
        return uri;
      },

      /**
       * Open authorize window if the configuration object is valid.
       *
       * @method authorize
       */
      authorize: function() {
        if (!this.get('providerId')) throw new Error('No provider id given.');
        if (!this.get('clientId')) throw new Error('No client id given.');
        if (!this.get('authBaseUri')) throw new Error('No auth base uri given.');
        if (!this.get('redirectUri')) throw new Error('No redirect uri given.');
        var authorizeUri = this.authUri();
        this.clearStates();
        this.saveState(this.get('state'), this.requestObj());
        var dialog = window.open(authorizeUri, 'Authorize', 'height=600, width=450');
        if (window.focus) dialog.focus();
      },

      /**
        @method authSuccess
        @param {Object} The params returned from the OAuth2 callback
        @return {String} the access_token from the params
      */
      authSuccess: function(params) {
        return params.access_token;
      },

      /**
       * Token properties
       * providerId
       * expiresIn
       * scope
       * token

        @method generateToken
        @return {Object} The access_token object with info about the token
       */
      generateToken: function(params) {
        var token = {};
        token.provider_id = this.get('providerId');
        token.expires_in = this.expiresIn(params.expires_in);
        token.scope = this.get('scope');
        token.access_token = params.access_token;
        return token;
      },

      /**
        @method expiresIn
        @return {Number} When the token expires in seconds.
      */
      expiresIn: function(expires) {
        return this.now() + parseInt(expires, 10);
      },

      /**
       * call on redirect from OAuth2 provider response
        @method onRedirect
        @deprecated Use `.trigger('redirect')` instead.
       */
      onRedirect: function(hash, callback) {
        Ember.Logger.warn("Ember.OAuth2.onRedirect is deprecated. Please use .trigger('redirect') instead.");
        this.trigger('redirect', hash, callback);
      },

      /*
       * proxy functions for old event handlers
       *
       * Check if the token returned is valid and if so trigger `success` event else trigger `error`
       *
       * @method handleRedirect
       */
      handleRedirect: function(hash, callback) {
        var params = this.parseCallback(hash);
        if (this.authSuccess(params)) {
          var stateObj = this.getState(params.state);
          this.checkState(stateObj);
          this.saveToken(this.generateToken(params));
          this.trigger('success', stateObj);
        } else {
          this.trigger('error', params);
        }
        if (callback && typeof(callback) === "function") {
          callback();
        }
      },

      /**
       * This method will call the old onSuccess callback when using the old API: Ember.OAuth2.reopen({ onSuccess: function() { return 'hello, onSuccess' } });
       *
       * The old onSuccess method will only be called when onSuccess is defined as a function on the Ember.OAuth2 instance
       *
       * @method _onSuccess
       * @param {Object} stateObj
       * @private
       */
      _onSuccess: function(stateObj) {
        if (typeof(this.onSuccess) !== 'function')
          return;

        Ember.Logger.warn("Ember.OAuth2.onSuccess is deprecated. Bind your callbacks using .on('success', fn) instead.");
        this.onSuccess(stateObj);
      },

      /**
       * This method will call the old onError callback when using the old API: Ember.OAuth2.reopen({ onError: function() { return 'hello, onError' } });
       *
       * The old onSuccess method will only be called when onError is defined as a function on the Ember.OAuth2 instance
       *
       * @method _onError
       * @param {Object} err object
       * @private
       */
      _onError: function(err) {
        if (typeof(this.onError) !== 'function')
          return;

        Ember.Logger.warn("Ember.OAuth2.onError is deprecated. Bind your callbacks using .on('error', fn) instead.");
        this.onError(err);
      },

      /**
       * Checks if the State returned from the server matches the state that was generated in the original request and saved in the browsers localStorage.
       *
       * @method checkState
       * @param {Object} stateObj The object returned from localStorage
       */
      checkState: function(stateObj) {
        if (!stateObj) throw new Error("Could not find state.");
        if (stateObj.state !== this.get('state')) throw new Error("State returned from the server did not match the local saved state.");
      },

      /**
       * Parse the callback function from the OAuth2 provider
       *
       * callback should have the following params if authentication is successful
       * state
       * access_token
       * token_type
       * expires_in
       *
       * @method parseCalback
       * @param {String} locationHash
       * @return {Object} The params returned from the OAuth2 provider
       */
      parseCallback: function(locationHash) {
        var oauthParams = {};
        var queryString = locationHash.substring(1);
        var regex = /([^#?&=]+)=([^&]*)/g;
        var match;
        while ((match = regex.exec(queryString)) !== null) {
          oauthParams[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        }
        return oauthParams;
      },

      /**
       * @method saveState
       * @param {String} state The state uuid
       * @param {Object} requestObj Properties of the request state to save in localStorage
       */
      saveState: function(state, requestObj) {
        window.localStorage.setItem(this.get('statePrefix') + '-' + state, JSON.stringify(requestObj));
      },

      /**
       * Return the saved state and remove it from the localStoage.
       *
       * @method getState
       * @param {String} state The state uuid to retreive from localStorage
       * @return {Object} Properties of the request state
       */
      getState: function(state) {
        var obj = JSON.parse(window.localStorage.getItem(this.get('statePrefix') + '-'  + state));
        window.localStorage.removeItem(this.get('statePrefix') + '-' + state);

        return obj;
      },

      /**
        * Remove any states from localStorage if they exist
        * @method clearStates
        */
      clearStates: function() {
        var regex = new RegExp( '^' + this.get('statePrefix') + '-.*', 'g');

        for(var i = 0; i < window.localStorage.length; i++) {
          var name = window.localStorage.key(i);
          while (regex.exec(name)) {
            window.localStorage.removeItem(name);
          }
        }
      },

      /**
       * saveToken stores the token by the tokenPrefix and the providerId
       * access_token
       * expires : time that the token expires
       * providerId: the providerId
       * scopes: array of scopes
       *
       * @method saveToken
       * @param {Object} token Saves the params in the response from the OAuth2 server to localStorage with the key 'tokenPrefix-providerId
       */
      saveToken: function(token) {
        window.localStorage.setItem(this.get('tokenPrefix') + '-' + this.get('providerId'), JSON.stringify(token));
      },

      /**
       * @method getToken
       * @return {Object} The params from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
       */
      getToken: function() {
        var token = JSON.parse(window.localStorage.getItem( this.get('tokenPrefix') + '-' + this.get('providerId')));
        if (!token) return null;
        if (!token.access_token) return null;
        return token;
      },

      /**
       * @method getAccessToken
       * @return {Object} The access_token param from the OAuth2 response from localStorage with the key 'tokenPrefix-providerId'.
       */
      getAccessToken: function() {
        var token = this.getToken();
        if (!token) return null;
        return token.access_token;
      },

      /**
       * @method accessTokenIsExpired
       * @return {Boolean} Check if the access_token is expired.
       */
      accessTokenIsExpired: function() {
        var token = this.getToken();
        if (!token) return true;
        if (this.now() >= token.expires_in) {
          return true;
        } else {
          return false;
        }
      },

      /**
       * Sets the access token expires_in time to 0 and saves the token to localStorage
       * @method expireAccessToken
       */
      expireAccessToken: function() {
        var token = this.getToken();
        if (!token) return null;
        token.expires_in = 0;
        this.saveToken(token);
      },
    });
  }

  /**
   * @property {String} VERSION
   * @final
  */
  var VERSION = "0.2.4";
  /**
   * @method version
   * @static
   */
  Ember.OAuth2.version = VERSION;
  /**
   * @method config
   * @static
  */
  Ember.OAuth2.config = {};

})(this);
<|endoftext|>


<commit_before>/**
 * @file Ready event that handles loading commands, locales, and the database tables if need be.
 * @author Capuccino
 * @author Ovyerus
 */

const fs = require('fs');
const path = require('path');

module.exports = bot => {
    bot.on('ready', async () => {
        if (bot.loadCommands) {
            try {
                bot.prefixes = bot.prefixes.concat([`<@${bot.user.id}> `, `<@!${bot.user.id}> `]);

                await bot.localeManager.loadLocales(bot);
                logger.info(`Loaded ${Object.keys(bot.localeManager.locales).length} locales.`);

                require(path.resolve(__dirname, '../modules', 'loader'))(bot);
                logger.info(`Loaded ${bot.commands.length} ${bot.commands.length === 1 ? 'command' : 'commands'}.`);

                bot.loadCommands = false;
                bot.allowCommandUse = true;

                let altPrefixes = JSON.parse(fs.readFileSync(path.resolve(`${__dirname}`, '../', '../', './data/prefixes.json')));

                logger.info(`${bot.user.username} is connected to Discord and is ready to use.`);
                logger.info(`Main prefix is '${bot.config.mainPrefix}', you can also use @mention.`);
                logger.info(altPrefixes.length > 0 ? `Alternative prefixes: '${altPrefixes.join("', ")}'`: 'No alternative prefixes.');
            } catch(err) {
                logger.error(`Error while starting up:\n${err.stack}`);
            }
        } else {
            logger.info('Reconnected to Discord from disconnection.');
        }
        if (!bot.config.gameURL) {
            await bot.editStatus('online', {
                name: `${bot.config.gameName || `${bot.config.mainPrefix}help for commands!`} | ${bot.guilds.size} ${bot.guilds.size === 1 ? 'server' : 'servers'}`,
                type: 0,
                url: null
           });
        } else {
            await bot.editStatus('online', {
                name: `${bot.config.gameName}` || `${bot.config.mainPrefix} for commands! | ${bot.guilds.size} ${bot.guilds.size === 1 ? 'server' : 'servers'}`,
                type: 1,
                url: bot.config.gameURL
            });
        }
        await bot.postGuildCount();
    });
};
<commit_msg>ESLint<commit_after>/**
 * @file Ready event that handles loading commands, locales, and the database tables if need be.
 * @author Capuccino
 * @author Ovyerus
 */

const fs = require('fs');
const path = require('path');

module.exports = bot => {
    bot.on('ready', async () => {
        if (bot.loadCommands) {
            try {
                bot.prefixes = bot.prefixes.concat([`<@${bot.user.id}> `, `<@!${bot.user.id}> `]);

                await bot.localeManager.loadLocales(bot);
                logger.info(`Loaded ${Object.keys(bot.localeManager.locales).length} locales.`);

                require(path.resolve(__dirname, '../modules', 'loader'))(bot);
                logger.info(`Loaded ${bot.commands.length} ${bot.commands.length === 1 ? 'command' : 'commands'}.`);

                bot.loadCommands = false;
                bot.allowCommandUse = true;

                let altPrefixes = JSON.parse(fs.readFileSync(path.resolve(`${__dirname}`, '../', '../', './data/prefixes.json')));

                logger.info(`${bot.user.username} is connected to Discord and is ready to use.`);
                logger.info(`Main prefix is '${bot.config.mainPrefix}', you can also use @mention.`);
                logger.info(altPrefixes.length > 0 ? `Alternative prefixes: '${altPrefixes.join("', ")}'`: 'No alternative prefixes.');
            } catch(err) {
                logger.error(`Error while starting up:\n${err.stack}`);
            }
        } else {
            logger.info('Reconnected to Discord from disconnection.');
        }
        if (!bot.config.gameURL) {
            await bot.editStatus('online', {
                name: `${bot.config.gameName || `${bot.config.mainPrefix}help for commands!`} | ${bot.guilds.size} ${bot.guilds.size === 1 ? 'server' : 'servers'}`,
                type: 0,
                url: null
          });
        } else {
            await bot.editStatus('online', {
                name: `${bot.config.gameName}` || `${bot.config.mainPrefix} for commands! | ${bot.guilds.size} ${bot.guilds.size === 1 ? 'server' : 'servers'}`,
                type: 1,
                url: bot.config.gameURL
            });
        }
        await bot.postGuildCount();
    });
};
<|endoftext|>


<commit_before>var logger = require('./logger')
var transport = require('./transport')
var utils = require('./utils')

module.exports = {
  normalizeFrame: function normalizeFrame (frame, options) {
    options = options || {}

    if (!frame.url) return

    // normalize the frames data
    var normalized = {
      'filename': frame.url,
      'lineno': frame.line,
      'colno': frame.column,
      'function': frame.func || '[anonymous]'
    }

    return normalized
  },

  traceKitStackToOpbeatException: function (stackInfo, options) {
    options = options || {}
    stackInfo.frames = []

    if (stackInfo.stack && stackInfo.stack.length) {
      stackInfo.stack.forEach(function (stack, i) {
        var frame = this.normalizeFrame(stack)
        if (frame) {
          stackInfo.frames.push(frame)
        }
      }.bind(this))
    }

    return stackInfo

  },

  processException: function processException (exception, options) {
    options = options || {}

    var stacktrace, label, i

    var type = exception.type
    var message = exception.message
    var fileurl = exception.fileurl
    var lineno = exception.lineno
    var frames = exception.frames

    // In some instances message is not actually a string, no idea why,
    // so we want to always coerce it to one.
    message += ''

    // Sometimes an exception is getting logged in Opbeat.com as
    // <no message value>
    // This can only mean that the message was falsey since this value
    // is hardcoded into Opbeat.com itself.
    // At this point, if the message is falsey, we bail since it's useless
    if (type === 'Error' && !message) return

    if (frames && frames.length) {
      fileurl = frames[0].filename || fileurl
      // Opbeat.com expects frames oldest to newest
      // and JS sends them as newest to oldest
      frames.reverse()
      stacktrace = {frames: frames}
    } else if (fileurl) {
      stacktrace = {
        frames: [{
          filename: fileurl,
          lineno: lineno,
          in_app: true
        }]
      }
    }

    label = lineno ? message + ' at ' + lineno : message

    var data = {
      exception: {
        type: type,
        value: message
      },
      stacktrace: stacktrace,
      culprit: fileurl,
      message: label
    }

    var viewportInfo = utils.getViewPortInfo()
    var extra = {
      'environment': {
        'utcOffset': new Date().getTimezoneOffset() / - 60.0,
        'browserWidth': viewportInfo.width,
        'browserHeight': viewportInfo.height,
        'screenWidth': screen.width,
        'screenHeight': screen.height,
        'userLanguage': navigator.userLanguage,
        'userAgent': navigator.userAgent,
        'platform': navigator.platform
      },
      'page': {
        'referer': document.referrer,
        'host': document.domain,
        'location': location.href
      }
    }
    data.extra = extra

    logger.log('opbeat.exceptionst.processException', data)

    transport.sendToOpbeat(data, options)

  }

}
<commit_msg>Use navigator.language <commit_after>var logger = require('./logger')
var transport = require('./transport')
var utils = require('./utils')

module.exports = {
  normalizeFrame: function normalizeFrame (frame, options) {
    options = options || {}

    if (!frame.url) return

    // normalize the frames data
    var normalized = {
      'filename': frame.url,
      'lineno': frame.line,
      'colno': frame.column,
      'function': frame.func || '[anonymous]'
    }

    return normalized
  },

  traceKitStackToOpbeatException: function (stackInfo, options) {
    options = options || {}
    stackInfo.frames = []

    if (stackInfo.stack && stackInfo.stack.length) {
      stackInfo.stack.forEach(function (stack, i) {
        var frame = this.normalizeFrame(stack)
        if (frame) {
          stackInfo.frames.push(frame)
        }
      }.bind(this))
    }

    return stackInfo

  },

  processException: function processException (exception, options) {
    options = options || {}

    var stacktrace, label, i

    var type = exception.type
    var message = exception.message
    var fileurl = exception.fileurl
    var lineno = exception.lineno
    var frames = exception.frames

    // In some instances message is not actually a string, no idea why,
    // so we want to always coerce it to one.
    message += ''

    // Sometimes an exception is getting logged in Opbeat.com as
    // <no message value>
    // This can only mean that the message was falsey since this value
    // is hardcoded into Opbeat.com itself.
    // At this point, if the message is falsey, we bail since it's useless
    if (type === 'Error' && !message) return

    if (frames && frames.length) {
      fileurl = frames[0].filename || fileurl
      // Opbeat.com expects frames oldest to newest
      // and JS sends them as newest to oldest
      frames.reverse()
      stacktrace = {frames: frames}
    } else if (fileurl) {
      stacktrace = {
        frames: [{
          filename: fileurl,
          lineno: lineno,
          in_app: true
        }]
      }
    }

    label = lineno ? message + ' at ' + lineno : message

    var data = {
      exception: {
        type: type,
        value: message
      },
      stacktrace: stacktrace,
      culprit: fileurl,
      message: label
    }

    var viewportInfo = utils.getViewPortInfo()
    var extra = {
      'environment': {
        'utcOffset': new Date().getTimezoneOffset() / - 60.0,
        'browserWidth': viewportInfo.width,
        'browserHeight': viewportInfo.height,
        'screenWidth': screen.width,
        'screenHeight': screen.height,
        'language': navigator.language,
        'userAgent': navigator.userAgent,
        'platform': navigator.platform,
      },
      'page': {
        'referer': document.referrer,
        'host': document.domain,
        'location': location.href,
      }
    }
    data.extra = extra

    logger.log('opbeat.exceptionst.processException', data)

    transport.sendToOpbeat(data, options)

  }

}
<|endoftext|>


<commit_before>import urljoin from "url-join"
import {
  mergeSchemas as _mergeSchemas,
  introspectSchema,
  makeRemoteExecutableSchema,
} from "graphql-tools"
import { ApolloLink } from "apollo-link"
import { createHttpLink } from "apollo-link-http"
import { setContext } from "apollo-link-context"
import fetch from "node-fetch"

import localSchema from "../schema"
import { headers as requestIDHeaders } from "./requestIDs"

import config from "config"

const { CONVECTION_API_BASE } = config

export function createConvectionLink() {
  const httpLink = createHttpLink({
    fetch,
    uri: urljoin(CONVECTION_API_BASE, "graphql"),
  })

  const middlewareLink = new ApolloLink((operation, forward) =>
    forward(operation)
  )

  const authMiddleware = setContext((_request, context) => {
    const locals = context.graphqlContext && context.graphqlContext.res.locals
    const tokenLoader = locals && locals.dataLoaders.convectionTokenLoader
    const headers = { ...(locals && requestIDHeaders(locals.requestIDs)) }
    // If a token loader exists for Convection (i.e. this is an authenticated request), use that token to make
    // authenticated requests to Convection.
    if (tokenLoader) {
      return tokenLoader().then(({ token }) => ({
        headers: Object.assign(headers, { Authorization: `Bearer ${token}` }),
      }))
    }
    // Otherwise use no authentication, which is also meant for fetching the service’s (public) schema.
    return { headers }
  })

  return middlewareLink.concat(authMiddleware).concat(httpLink)
}

export async function mergeSchemas() {
  const convectionLink = createConvectionLink()

  const convectionSchema = await makeRemoteExecutableSchema({
    schema: await introspectSchema(convectionLink),
    link: convectionLink,
  })

  const linkTypeDefs = `
    extend type Submission {
      artist: Artist
    }
  `

  const mergedSchema = _mergeSchemas({
    schemas: [localSchema, convectionSchema, linkTypeDefs],
    // Prefer others over the local MP schema.
    onTypeConflict: (_leftType, rightType) => {
      console.warn(`[!] Type collision ${rightType}`) // eslint-disable-line no-console
      return rightType
    },
    resolvers: {
      Submission: {
        artist: {
          fragment: `fragment SubmissionArtist on Submission { artist_id }`,
          resolve: (parent, args, context, info) => {
            const id = parent.artist_id
            return info.mergeInfo.delegateToSchema(
              localSchema,
              "query",
              "artist",
              { id },
              context,
              info
            )
          },
        },
      },
    },
  })
  mergedSchema.__allowedLegacyNames = ["__id"]
  return mergedSchema
}
<commit_msg>Correct mergeSchemas signature<commit_after>import urljoin from "url-join"
import {
  mergeSchemas as _mergeSchemas,
  introspectSchema,
  makeRemoteExecutableSchema,
} from "graphql-tools"
import { ApolloLink } from "apollo-link"
import { createHttpLink } from "apollo-link-http"
import { setContext } from "apollo-link-context"
import fetch from "node-fetch"

import localSchema from "../schema"
import { headers as requestIDHeaders } from "./requestIDs"

import config from "config"

const { CONVECTION_API_BASE } = config

export function createConvectionLink() {
  const httpLink = createHttpLink({
    fetch,
    uri: urljoin(CONVECTION_API_BASE, "graphql"),
  })

  const middlewareLink = new ApolloLink((operation, forward) =>
    forward(operation)
  )

  const authMiddleware = setContext((_request, context) => {
    const locals = context.graphqlContext && context.graphqlContext.res.locals
    const tokenLoader = locals && locals.dataLoaders.convectionTokenLoader
    const headers = { ...(locals && requestIDHeaders(locals.requestIDs)) }
    // If a token loader exists for Convection (i.e. this is an authenticated request), use that token to make
    // authenticated requests to Convection.
    if (tokenLoader) {
      return tokenLoader().then(({ token }) => ({
        headers: Object.assign(headers, { Authorization: `Bearer ${token}` }),
      }))
    }
    // Otherwise use no authentication, which is also meant for fetching the service’s (public) schema.
    return { headers }
  })

  return middlewareLink.concat(authMiddleware).concat(httpLink)
}

export async function mergeSchemas() {
  const convectionLink = createConvectionLink()

  const convectionSchema = await makeRemoteExecutableSchema({
    schema: await introspectSchema(convectionLink),
    link: convectionLink,
  })

  const linkTypeDefs = `
    extend type Submission {
      artist: Artist
    }
  `

  const mergedSchema = _mergeSchemas({
    schemas: [
      { name: "local", schema: localSchema },
      { name: "convection", schema: convectionSchema },
      { name: "links", schema: linkTypeDefs },
    ],
    // Prefer others over the local MP schema.
    onTypeConflict: (_leftType, rightType) => {
      console.warn(`[!] Type collision ${rightType}`) // eslint-disable-line no-console
      return rightType
    },
    resolvers: {
      Submission: {
        artist: {
          fragment: `fragment SubmissionArtist on Submission { artist_id }`,
          resolve: (parent, args, context, info) => {
            const id = parent.artist_id
            return info.mergeInfo.delegateToSchema(
              localSchema,
              "query",
              "artist",
              { id },
              context,
              info
            )
          },
        },
      },
    },
  })
  mergedSchema.__allowedLegacyNames = ["__id"]
  return mergedSchema
}
<|endoftext|>


<commit_before>import { resolve, reject } from 'redux-simple-promise';
import * as fetchConstants from './fetchConstants';
import { addNotice } from '../actions/appActions';
import { LEVEL_ERROR } from '../components/common/Notice';
import { logout } from '../lib/auth';

// TODO: replace this with normalizr? https://github.com/gaearon/normalizr
export function arrayToDict(arr, keyPropertyName) {
  const dict = {};
  arr.forEach((item) => {
    dict[item[keyPropertyName]] = item;
  });
  return dict;
}

// if all rows should be selected, or only page rows, or none, checked will tell us
// arr contains only a chunk of rows at a time... TODO
export function selectItemInArray(arr, idArr, idField, checked) {
  const updateWithNewlySelected = [];
  arr.forEach((item) => {
    const newItem = item;
    idArr.forEach((id) => {
      if (item[idField] === id) {
        if (checked) {
          newItem.selected = true;
        } else {
          newItem.selected = false;
        }
      }
    });
    updateWithNewlySelected.push(newItem);
  });
  return updateWithNewlySelected;
}

/**
 * Helper for generating async actions (these are promise-based).  Provide two params:
 * - `type`: the action type constant
 * - `fetcher`: the function object to run (args will be relayed automatically)
 * This returns an action function you can use.
 */
export function createAsyncAction(type, fetcher) {
  return (...args) => ({
    type,
    payload: {
      promise: fetcher(...args),
      args,  // tack on arguments pass in so we can access them directly in a reducer
      uid: Math.random(), // track this request with a random id, to avoid race conditions in reducer
    },
  });
}

/**
 * Helper to create a generic reducer.  Pass in an object with the following properties:
 * - `intialState`: the intial state to use for this recuder (default to empty object)
 * - `[OTHER_CONSTANTS]`: any other constants will be added as extra checks (this lets you include other actions in this reducer)
 */
export function createReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  // set up a lookup table for any things the user passed in
  const actionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['initialState'].includes(key)) {
      actionLookup[key] = handlers[key];
    }
  });
  // and now set up the reducer method
  return (state = desiredInitialState, action) => {
    if (action.type in actionLookup) {
      return Object.assign({}, state, {
        ...state,
        ...actionLookup[action.type](action.payload, state),
      });
    }
    return state;
  };
}

/**
 * Helper for generating generic async reducers.  Pass in an object with the following properties
 * (each is optional):
 * - `initialState`: the initial state for this reducer (defaults to empty object)
 * - `handleFetch`: any state to set when the action is first dispatched (defaults to empty)
 * - `handleSuccess`: any state to set when the async call returns successfully (defaults to `{...payload}`)
 * - `handleFailure`: any state to set when the action is first dispatched (defaults to empty)
 * - `[OTHER_CONSTANTS]`: any other constants will be added as extra checks (this lets you include other actions in this reducer)
 * This handles setting the fetchState to the appropriate item from `fetchConstants` for you. So you can
 * write reducers like this and they will act like you'd expect:
 * ```es6
 * const topWords = createAsyncReducer({
 *  initialState: {
 *    list: [],
 *  },
 *  action: FETCH_TOPIC_TOP_WORDS,
 * });
 * ```
 */
export function createAsyncReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  const initialState = {
    fetchStatus: fetchConstants.FETCH_INVALID,  // invalid, succeeded, or failed
    lastFetchSuccess: null, // null or a Date object of the last successful fetch
    fetchUid: null, // set this to a random id so we know which request is returning async, to avoid race conditions
    ...desiredInitialState,
  };
  // set up any async reducer handlers the user passed in
  const reducers = {  // set up some smart defaults for normal behaviour
    handleFetch: () => ({}),
    handleSuccess: payload => ({ ...payload }),
    handleFailure: () => ({}),
  };
  Object.keys(reducers).forEach((key) => {   // override defaults with custom methods passed in
    if (key in handlers) {
      reducers[key] = handlers[key];
    }
  });
  // set up a lookup table for any other things the user passed in
  const extraActionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['action', 'initialState', 'handleFetch', 'handleSuccess', 'handleFailure'].includes(key)) {
      extraActionLookup[key] = handlers[key];
    }
  });
  // now alter the state appropriately
  return (state = initialState, action) => {
    // only do something if this hasn't been superceeded by another aysnc request before this one returned
    let isValid = true;
    if (action.meta) {
      isValid = action.meta.uid === state.fetchUid;
    }
    switch (action.type) {
      case handlers.action:
        return Object.assign({}, state, {
          ...state,
          fetchStatus: fetchConstants.FETCH_ONGOING,
          lastFetchSuccess: null,
          fetchUid: action.payload.uid,
          ...reducers.handleFetch(action.payload, state, action.meta),
        });
      case resolve(handlers.action):
        if (isValid) {
          return Object.assign({}, state, {
            ...state,
            fetchStatus: fetchConstants.FETCH_SUCCEEDED,
            lastFetchSuccess: new Date(),
            ...reducers.handleSuccess(action.payload, state, action.meta),
          });
        }
        // another request happened after this one, so don't do anything!
        return state;
      case reject(handlers.action):
        if (isValid) {
          return Object.assign({}, state, {
            ...state,
            fetchStatus: fetchConstants.FETCH_FAILED,
            lastFetchSuccess: null,
            ...reducers.handleFailure(action.payload, state, action.meta),
          });
        }
        // another request happened after this one, so don't do anything!
        return state;
      default:
        if (action.type in extraActionLookup) {
          return Object.assign({}, state, {
            ...state,
            ...extraActionLookup[action.type](action.payload, state, action.meta),
          });
        }
        return state;
    }
  };
}

/**
 * Report failures to user via app-level feedback mechanism.
 */
export function errorReportingMiddleware({ dispatch }) {
  return next => (action) => {
    let message = null;
    if (action.type.endsWith('_RESOLVED') || action.type.endsWith('_REJECTED')) {
      if ('status' in action.payload) {
        if (action.payload.status === 401) {
          // unauthorized - ie. needs to login so delete cookies by going to logout
          if ((action.type !== 'LOGIN_WITH_PASSWORD_RESOLVED') && (action.type !== 'LOGIN_WITH_COOKIE_RESOLVED')) { // unless they are trying to login (cause that would be dumb)
            message = action.payload.message;
            logout();
          }
        } else if (action.payload.status !== 200) {
          if ((action.type !== 'LOGIN_WITH_PASSWORD_RESOLVED') && (action.type !== 'LOGIN_WITH_COOKIE_RESOLVED')) { // unless they are trying to login (cause that would be dumb)
            message = 'Sorry, we had an error';
            if ('message' in action.payload) {
              message = action.payload.message;
            }
          }
        }
      }
    }
    if (message) {
      dispatch(addNotice({ level: LEVEL_ERROR, message }));
    }
    return next(action);  // Call the next dispatch method in the middleware chain.
  };
}

/**
 * For any anyc reducers that query N of the same action in parallel, and want to hold the results
 * in an array of results.  This REQUIRES you to have a "index" parameter in the action, so it knows
 * where to put the payload in the results array it holds.
 */
export function createIndexedAsyncReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  const initialState = {
    results: [],
    fetchStatus: fetchConstants.FETCH_INVALID,
    fetchStatuses: [], // array of fetchStatus
    fetchUids: [],  // array of unique ids for each fetch in the list
    ...desiredInitialState,
  };
  // set up any async reducer handlers the user passed in
  const reducers = {  // set up some smart defaults for normal behaviour
    handleFetch: (payload, state, args) => {
      const index = args[0].index;
      if (index === undefined) {
        const error = { error: 'You need to pass the indexedAsyncReducer an index to use!' };
        throw error;
      }
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_ONGOING;
      const updatedFetchUids = [...state.fetchUids];
      updatedFetchUids[index] = payload.uid;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
        fetchUids: updatedFetchUids,
      });
    },
    handleSuccess: (payload, state, args) => {
      const index = args[0].index;
      const updatedResults = [...state.results];
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_SUCCEEDED;
      updatedResults[index] = payload;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
        results: updatedResults,
      });
    },
    handleFailure: (payload, state, args) => {
      const index = args[0].index;
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_FAILED;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
      });
    },
  };
  Object.keys(reducers).forEach((key) => {   // override defaults with custom methods passed in
    if (key in handlers) {
      reducers[key] = handlers[key];
    }
  });
  // set up a lookup table for any other things the user passed in
  const extraActionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['action', 'initialState', 'handleFetch', 'handleSuccess', 'handleFailure'].includes(key)) {
      extraActionLookup[key] = handlers[key];
    }
  });
  // now alter the state appropriately
  return (state = initialState, action) => {
    switch (action.type) {
      case handlers.action:
        return reducers.handleFetch(action.payload, state, action.payload.args);
      case resolve(handlers.action):
        const index = action.meta.args ? action.meta.args[0].index : 0;
        const isValid = state.fetchStatuses.length > index;
        if (!isValid) { // don't honor resolves that are for indexes we aren't tracking anymore
          return state;
        }
        return reducers.handleSuccess(action.payload, state, action.meta.args);
      case reject(handlers.action):
        return reducers.handleFailure(action.payload, state, action.meta.args);
      default:
        if (action.type in extraActionLookup) {
          return Object.assign({}, state, {
            ...state,
            ...extraActionLookup[action.type](action.payload, state, action.args),
          });
        }
        return state;
    }
  };
}
<commit_msg>Safer check for status in payload of actions<commit_after>import { resolve, reject } from 'redux-simple-promise';
import * as fetchConstants from './fetchConstants';
import { addNotice } from '../actions/appActions';
import { LEVEL_ERROR } from '../components/common/Notice';
import { logout } from '../lib/auth';

// TODO: replace this with normalizr? https://github.com/gaearon/normalizr
export function arrayToDict(arr, keyPropertyName) {
  const dict = {};
  arr.forEach((item) => {
    dict[item[keyPropertyName]] = item;
  });
  return dict;
}

// if all rows should be selected, or only page rows, or none, checked will tell us
// arr contains only a chunk of rows at a time... TODO
export function selectItemInArray(arr, idArr, idField, checked) {
  const updateWithNewlySelected = [];
  arr.forEach((item) => {
    const newItem = item;
    idArr.forEach((id) => {
      if (item[idField] === id) {
        if (checked) {
          newItem.selected = true;
        } else {
          newItem.selected = false;
        }
      }
    });
    updateWithNewlySelected.push(newItem);
  });
  return updateWithNewlySelected;
}

/**
 * Helper for generating async actions (these are promise-based).  Provide two params:
 * - `type`: the action type constant
 * - `fetcher`: the function object to run (args will be relayed automatically)
 * This returns an action function you can use.
 */
export function createAsyncAction(type, fetcher) {
  return (...args) => ({
    type,
    payload: {
      promise: fetcher(...args),
      args,  // tack on arguments pass in so we can access them directly in a reducer
      uid: Math.random(), // track this request with a random id, to avoid race conditions in reducer
    },
  });
}

/**
 * Helper to create a generic reducer.  Pass in an object with the following properties:
 * - `intialState`: the intial state to use for this recuder (default to empty object)
 * - `[OTHER_CONSTANTS]`: any other constants will be added as extra checks (this lets you include other actions in this reducer)
 */
export function createReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  // set up a lookup table for any things the user passed in
  const actionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['initialState'].includes(key)) {
      actionLookup[key] = handlers[key];
    }
  });
  // and now set up the reducer method
  return (state = desiredInitialState, action) => {
    if (action.type in actionLookup) {
      return Object.assign({}, state, {
        ...state,
        ...actionLookup[action.type](action.payload, state),
      });
    }
    return state;
  };
}

/**
 * Helper for generating generic async reducers.  Pass in an object with the following properties
 * (each is optional):
 * - `initialState`: the initial state for this reducer (defaults to empty object)
 * - `handleFetch`: any state to set when the action is first dispatched (defaults to empty)
 * - `handleSuccess`: any state to set when the async call returns successfully (defaults to `{...payload}`)
 * - `handleFailure`: any state to set when the action is first dispatched (defaults to empty)
 * - `[OTHER_CONSTANTS]`: any other constants will be added as extra checks (this lets you include other actions in this reducer)
 * This handles setting the fetchState to the appropriate item from `fetchConstants` for you. So you can
 * write reducers like this and they will act like you'd expect:
 * ```es6
 * const topWords = createAsyncReducer({
 *  initialState: {
 *    list: [],
 *  },
 *  action: FETCH_TOPIC_TOP_WORDS,
 * });
 * ```
 */
export function createAsyncReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  const initialState = {
    fetchStatus: fetchConstants.FETCH_INVALID,  // invalid, succeeded, or failed
    lastFetchSuccess: null, // null or a Date object of the last successful fetch
    fetchUid: null, // set this to a random id so we know which request is returning async, to avoid race conditions
    ...desiredInitialState,
  };
  // set up any async reducer handlers the user passed in
  const reducers = {  // set up some smart defaults for normal behaviour
    handleFetch: () => ({}),
    handleSuccess: payload => ({ ...payload }),
    handleFailure: () => ({}),
  };
  Object.keys(reducers).forEach((key) => {   // override defaults with custom methods passed in
    if (key in handlers) {
      reducers[key] = handlers[key];
    }
  });
  // set up a lookup table for any other things the user passed in
  const extraActionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['action', 'initialState', 'handleFetch', 'handleSuccess', 'handleFailure'].includes(key)) {
      extraActionLookup[key] = handlers[key];
    }
  });
  // now alter the state appropriately
  return (state = initialState, action) => {
    // only do something if this hasn't been superceeded by another aysnc request before this one returned
    let isValid = true;
    if (action.meta) {
      isValid = action.meta.uid === state.fetchUid;
    }
    switch (action.type) {
      case handlers.action:
        return Object.assign({}, state, {
          ...state,
          fetchStatus: fetchConstants.FETCH_ONGOING,
          lastFetchSuccess: null,
          fetchUid: action.payload.uid,
          ...reducers.handleFetch(action.payload, state, action.meta),
        });
      case resolve(handlers.action):
        if (isValid) {
          return Object.assign({}, state, {
            ...state,
            fetchStatus: fetchConstants.FETCH_SUCCEEDED,
            lastFetchSuccess: new Date(),
            ...reducers.handleSuccess(action.payload, state, action.meta),
          });
        }
        // another request happened after this one, so don't do anything!
        return state;
      case reject(handlers.action):
        if (isValid) {
          return Object.assign({}, state, {
            ...state,
            fetchStatus: fetchConstants.FETCH_FAILED,
            lastFetchSuccess: null,
            ...reducers.handleFailure(action.payload, state, action.meta),
          });
        }
        // another request happened after this one, so don't do anything!
        return state;
      default:
        if (action.type in extraActionLookup) {
          return Object.assign({}, state, {
            ...state,
            ...extraActionLookup[action.type](action.payload, state, action.meta),
          });
        }
        return state;
    }
  };
}

/**
 * Report failures to user via app-level feedback mechanism.
 */
export function errorReportingMiddleware({ dispatch }) {
  return next => (action) => {
    let message = null;
    if (action.type.endsWith('_RESOLVED') || action.type.endsWith('_REJECTED')) {
      if ((typeof action.payload === 'object') && ('status' in action.payload)) {
        if (action.payload.status === 401) {
          // unauthorized - ie. needs to login so delete cookies by going to logout
          if ((action.type !== 'LOGIN_WITH_PASSWORD_RESOLVED') && (action.type !== 'LOGIN_WITH_COOKIE_RESOLVED')) { // unless they are trying to login (cause that would be dumb)
            message = action.payload.message;
            logout();
          }
        } else if (action.payload.status !== 200) {
          if ((action.type !== 'LOGIN_WITH_PASSWORD_RESOLVED') && (action.type !== 'LOGIN_WITH_COOKIE_RESOLVED')) { // unless they are trying to login (cause that would be dumb)
            message = 'Sorry, we had an error';
            if ('message' in action.payload) {
              message = action.payload.message;
            }
          }
        }
      }
    }
    if (message) {
      dispatch(addNotice({ level: LEVEL_ERROR, message }));
    }
    return next(action);  // Call the next dispatch method in the middleware chain.
  };
}

/**
 * For any anyc reducers that query N of the same action in parallel, and want to hold the results
 * in an array of results.  This REQUIRES you to have a "index" parameter in the action, so it knows
 * where to put the payload in the results array it holds.
 */
export function createIndexedAsyncReducer(handlers) {
  // there might be intial state we need to set up
  let desiredInitialState = {};
  if ('initialState' in handlers) {
    desiredInitialState = handlers.initialState;
  }
  const initialState = {
    results: [],
    fetchStatus: fetchConstants.FETCH_INVALID,
    fetchStatuses: [], // array of fetchStatus
    fetchUids: [],  // array of unique ids for each fetch in the list
    ...desiredInitialState,
  };
  // set up any async reducer handlers the user passed in
  const reducers = {  // set up some smart defaults for normal behaviour
    handleFetch: (payload, state, args) => {
      const index = args[0].index;
      if (index === undefined) {
        const error = { error: 'You need to pass the indexedAsyncReducer an index to use!' };
        throw error;
      }
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_ONGOING;
      const updatedFetchUids = [...state.fetchUids];
      updatedFetchUids[index] = payload.uid;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
        fetchUids: updatedFetchUids,
      });
    },
    handleSuccess: (payload, state, args) => {
      const index = args[0].index;
      const updatedResults = [...state.results];
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_SUCCEEDED;
      updatedResults[index] = payload;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
        results: updatedResults,
      });
    },
    handleFailure: (payload, state, args) => {
      const index = args[0].index;
      const updatedFetchStatuses = [...state.fetchStatuses];
      updatedFetchStatuses[index] = fetchConstants.FETCH_FAILED;
      return Object.assign({}, state, {
        fetchStatus: fetchConstants.combineFetchStatuses(updatedFetchStatuses),
        fetchStatuses: updatedFetchStatuses,
      });
    },
  };
  Object.keys(reducers).forEach((key) => {   // override defaults with custom methods passed in
    if (key in handlers) {
      reducers[key] = handlers[key];
    }
  });
  // set up a lookup table for any other things the user passed in
  const extraActionLookup = {};
  Object.keys(handlers).forEach((key) => {
    if (!['action', 'initialState', 'handleFetch', 'handleSuccess', 'handleFailure'].includes(key)) {
      extraActionLookup[key] = handlers[key];
    }
  });
  // now alter the state appropriately
  return (state = initialState, action) => {
    switch (action.type) {
      case handlers.action:
        return reducers.handleFetch(action.payload, state, action.payload.args);
      case resolve(handlers.action):
        const index = action.meta.args ? action.meta.args[0].index : 0;
        const isValid = state.fetchStatuses.length > index;
        if (!isValid) { // don't honor resolves that are for indexes we aren't tracking anymore
          return state;
        }
        return reducers.handleSuccess(action.payload, state, action.meta.args);
      case reject(handlers.action):
        return reducers.handleFailure(action.payload, state, action.meta.args);
      default:
        if (action.type in extraActionLookup) {
          return Object.assign({}, state, {
            ...state,
            ...extraActionLookup[action.type](action.payload, state, action.args),
          });
        }
        return state;
    }
  };
}
<|endoftext|>


<commit_before>import React, { createElement as r } from 'react';

import resetCss from '../styles/reset-css.js';

export default function renderFront ({ image, size, isPreview = false, scale = 100, ...props }) {
  const img = image;
  const { width, height } = size;
  const d = v => (v * scale).toFixed(6);

  const rotate = width < height;

  var trimSides, degrees, scaled, translate;
  if (rotate) {
    trimSides = (img.width / img.height) < (height / width);
    degrees = [90, img.height / 2, img.height / 2];
    scaled = trimSides ? (d(height) / img.width) : (d(width) / img.height);
    translate = trimSides ? [-((scaled * img.height - d(width)) / 2), 0] : [0, -((scaled * img.width - d(height)) / 2)];
  }
  else {
    trimSides = (img.width / img.height) > (width / height);
    degrees = [0];
    scaled = trimSides ? (d(height) / img.height) : (d(width) / img.width);
    translate = trimSides ? [-((scaled * img.width - d(width)) / 2), 0] : [0, -((scaled * img.height - d(height)) / 2)];
  }

  return (

      <svg
        xmlns="http://www.w3.org/2000/svg"
        width={d(width)}
        height={d(height)}
        viewBox={`0 0 ${d(width)} ${d(height)}`}
        {...props}>

        <image
          width={img.width}
          height={img.height}
          transform={`translate(${translate.join(' ')}) scale(${scaled}) rotate(${degrees.join(' ')})`}
          xlinkHref={img.data}>
        </image>

      </svg>

  );
}
<commit_msg>hopefully fixed little visual bug where preview sometimes had some extra space below it<commit_after>import React, { createElement as r } from 'react';

import resetCss from '../styles/reset-css.js';

export default function renderFront ({ image, size, isPreview = false, scale = 100, ...props }) {
  const img = image;
  const { width, height } = size;
  const d = v => (v * scale).toFixed(6);

  const rotate = width < height;

  var trimSides, degrees, scaled, translate;
  if (rotate) {
    trimSides = (img.width / img.height) < (height / width);
    degrees = [90, img.height / 2, img.height / 2];
    scaled = trimSides ? (d(height) / img.width) : (d(width) / img.height);
    translate = trimSides ? [-((scaled * img.height - d(width)) / 2), 0] : [0, -((scaled * img.width - d(height)) / 2)];
  }
  else {
    trimSides = (img.width / img.height) > (width / height);
    degrees = [0];
    scaled = trimSides ? (d(height) / img.height) : (d(width) / img.width);
    translate = trimSides ? [-((scaled * img.width - d(width)) / 2), 0] : [0, -((scaled * img.height - d(height)) / 2)];
  }

  return (

      <svg
        xmlns="http://www.w3.org/2000/svg"
        width={d(width)}
        height={d(height)}
        viewBox={`0 0 ${d(width)} ${d(height)}`}
        {...props}>

        <image
          width={img.width}
          height={img.height}
          transform={`translate(${translate.join(' ')}) scale(${scaled}) rotate(${degrees.join(' ')})`}
          xlinkHref={img.data}>
        </image>

      </svg>

  );
}
<|endoftext|>


<commit_before>var projectIds = null;
var representatives = null;
var currentProject = null;
var currentVotes = null;

function shuffle(array) {
    var counter = array.length, temp, index;

    // While there are elements in the array
    while (counter > 0) {
        // Pick a random index
        index = (Math.random() * counter--) | 0;

        // And swap the last element with it
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

function reset() {
	currentProject = null;
	currentVotes = {};
	$('#link').click(function () {
		if (!currentProject) return;
		window.open(currentProject.url, '_blank');
	});
	$.getJSON('data/curated-index.json', function (data) {
		projectIds = shuffle(data);
	});
	$.getJSON('data/legisladores.json', function (data) {
		representatives = data;
	});
	$('#intro').css('display', 'block');
	$('#about').css('display', 'none');
	$('#voting').css('display', 'none');
	$('#results').css('display', 'none');
}

function loadRandomProject() {
	currentProject = null;
	if (projectIds.length == 0) {
		finish();
		return;
	}
	var id = projectIds.pop();
	$.getJSON('data/proyectos/' + id + '.json', function (data) {
		currentProject = data;
		$('#project').text(data.nombre);
		$('#summary').text(data.sumario);
		$('#date').text(data.asunto + ' - ' + data.fecha);
		$('#voting').fadeIn(100);
	});
}

function match(reps) {
	if (!reps) return;
	for (var i = 0; i < reps.length; i++) {
		var r = reps[i];
		if (currentVotes[r]) {
			currentVotes[r] += 1;
		} else {
			currentVotes[r] = 1;
		}
	}
}

function finish() {
	var results = new Array();
	for (var i in currentVotes) {
		var n = currentVotes[i];
		if (!(results[n])) {
			results[n] = new Array();
		}
		results[n].push(representatives[i]);
	}
	var count = 0;
	$('#reps').empty();
	for (var i = results.length - 1; i >= 0; i--) {
		var a = results[i];
		for (var j = 0; j < a.length; j++) {
			var e = document.createElement('li');
			$(e).text(a[j].nombre + ' ('
				+ a[j].bloque + ') '
				+ a[j].distrito + ' [' + i + ']');
			$('#reps').append(e);
			count++;
		}
		if (count >= 8) break; // only show top matches
	}
	$('#voting').stop(true);
	$('#voting').fadeOut(200, function () {
		$('#results').fadeIn(100);
	});
}

$('#vote-aye').click(function () {
	if (!currentProject) return;
	match(currentProject.votacion.AFIRMATIVO);
	$('#voting').fadeOut(200, loadRandomProject);
});
$('#vote-nay').click(function () {
	if (!currentProject) return;
	match(currentProject.votacion.NEGATIVO);
	$('#voting').fadeOut(200, loadRandomProject);
});
$('#vote-abs').click(function () {
	if (!currentProject) return;
	$('#voting').fadeOut(200, loadRandomProject);
});

//$('#finish').click(finish);

$('#start').click(function () { $('#intro').fadeOut(200, loadRandomProject); });
$('#info').click(function () { $('#about').slideToggle(500); });
$('#back').click(function () { $('#about').slideToggle(500); });
//$('#resume').click(function () { ('#voting').css('display', 'block'); });
$('#reset').click(reset);
$(document).ready(reset);
<commit_msg>Fixed event handlers initialization<commit_after>var projectIds = null;
var representatives = null;
var currentProject = null;
var currentVotes = null;

function shuffle(array) {
    var counter = array.length, temp, index;

    // While there are elements in the array
    while (counter > 0) {
        // Pick a random index
        index = (Math.random() * counter--) | 0;

        // And swap the last element with it
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

function reset() {
	currentProject = null;
	currentVotes = {};
	$.getJSON('data/curated-index.json', function (data) {
		projectIds = shuffle(data);
	});
	$.getJSON('data/legisladores.json', function (data) {
		representatives = data;
	});
	$('#intro').css('display', 'block');
	$('#about').css('display', 'none');
	$('#voting').css('display', 'none');
	$('#results').css('display', 'none');
}

function loadRandomProject() {
	currentProject = null;
	if (projectIds.length == 0) {
		finish();
		return;
	}
	var id = projectIds.pop();
	$.getJSON('data/proyectos/' + id + '.json', function (data) {
		currentProject = data;
		$('#project').text(data.nombre);
		$('#summary').text(data.sumario);
		$('#date').text(data.asunto + ' \u2014 ' + data.fecha);
		$('#voting').fadeIn(100);
	});
}

function match(reps) {
	if (!reps) return;
	for (var i = 0; i < reps.length; i++) {
		var r = reps[i];
		if (currentVotes[r]) {
			currentVotes[r] += 1;
		} else {
			currentVotes[r] = 1;
		}
	}
}

function finish() {
	var results = new Array();
	for (var i in currentVotes) {
		var n = currentVotes[i];
		if (!(results[n])) {
			results[n] = new Array();
		}
		results[n].push(representatives[i]);
	}
	var count = 0;
	$('#reps').empty();
	for (var i = results.length - 1; i >= 0; i--) {
		var a = results[i];
		for (var j = 0; j < a.length; j++) {
			var e = document.createElement('li');
			$(e).text(a[j].nombre + ' ('
				+ a[j].bloque + ') '
				+ a[j].distrito + ' [' + i + ']');
			$('#reps').append(e);
			count++;
		}
		if (count >= 8) break; // only show top matches
	}
	$('#voting').stop(true);
	$('#voting').fadeOut(200, function () {
		$('#results').fadeIn(100);
	});
}

$(document).ready(function () {
	$('#vote-aye').click(function () {
		if (!currentProject) return;
		match(currentProject.votacion.AFIRMATIVO);
		$('#voting').fadeOut(200, loadRandomProject);
	});
	$('#vote-nay').click(function () {
		if (!currentProject) return;
		match(currentProject.votacion.NEGATIVO);
		$('#voting').fadeOut(200, loadRandomProject);
	});
	$('#vote-abs').click(function () {
		if (!currentProject) return;
		$('#voting').fadeOut(200, loadRandomProject);
	});

	$('#link').click(function () {
		if (!currentProject) return;
		window.open(currentProject.url, '_blank');
	});
	$('#start').click(function () {
		$('#intro').fadeOut(200, loadRandomProject);
	});
	$('#info').click(function () { $('#about').slideToggle(500); });
	$('#back').click(function () { $('#about').slideToggle(500); });
	$('#reset').click(reset);
	reset();
});
<|endoftext|>


<commit_before>const fs = require('fs'),
      JSDOM = require('jsdom');

/**
 *
 */
class JavascriptDetector {
    /**
     *
     */
    isEncoded(html) {
        return 0 > html.indexOf('Incident Id');
    }

    /**
     *
     */
    getID(html) {
        return this._parse(html);
    }

    /**
     *
     */
    _getEncoded(html) {
        let encodedBits = html.match(/cc='(.*)';.*cc='(.*);.*Pid\(\) {return (.*); }/);

        return {
            html: this._normalizeInput(encodedBits[1]),
            functions: this._normalizeInput(encodedBits[2]),
            callback: this._normalizeInput(encodedBits[3])
        };
    }

    /**
     *
     */
    _normalizeInput(str) {
        return unescape(decodeURIComponent(str))
            .replace(/^<\!\-\-\s*|\s*\-\->$/g, '')
            .replace(/'/g, '"')
            .replace(/finalStr=""/g, 'var finalStr=""')
            .replace(/sbbObj = /g, 'var sbbObj=')
            .replace(/sbbFrm=/g, 'var sbbFrm=')
            .replace(/i=0/g, 'var i=0')
            .replace(/document\./g, 'window\.document\.')

            .replace(/onclick="return "(.*?)""/g, 'value="$1"')
            .replace(/\.onclick\(\)/g, '\.getAttribute\(\'value\'\)')
            ;
    }

    /**
     *
     */
    _customReplaces(str) {
        let wrongRef = str.match(/} var (.*)=.*getElementsByName.*x=.*?\((.*?)\)/, '');
        if (null !== wrongRef)
            str = str.replace(wrongRef[2], wrongRef[1]);

        return str;
    }

    /**
     *
     */
    _parse(jsDetectionHTML) {
        return new Promise((resolve, reject) => {
            let markup = this._getEncoded(jsDetectionHTML);
            markup.functions = this._customReplaces(markup.functions);

            return JSDOM.env({
                html: markup.html,
                done: (err, window) => {
                    let getID = new Function('window', [
                            markup.functions,
                            'return',
                            markup.callback
                        ].join(' '));
                    try {
                        let ID = getID(window);
                        resolve({value: ID});
                    } catch(e) {
                        reject({error: e});
                    }
                }

            });
        });
    }

}

module.exports = JavascriptDetector;<commit_msg>removed cookie domain<commit_after>const fs = require('fs'),
      JSDOM = require('jsdom');

/**
 *
 */
class JavascriptDetector {
    /**
     *
     */
    isEncoded(html) {
        return 0 > html.indexOf('Incident Id');
    }

    /**
     *
     */
    getID(html) {
        return this._parse(html);
    }

    /**
     *
     */
    _getEncoded(html) {
        let encodedBits = html.match(/cc='(.*)';.*cc='(.*);.*Pid\(\) {return (.*); }/);

        return {
            html: this._normalizeInput(encodedBits[1]),
            functions: this._normalizeInput(encodedBits[2]),
            callback: this._normalizeInput(encodedBits[3])
        };
    }

    /**
     *
     */
    _normalizeInput(str) {
        return unescape(decodeURIComponent(str))
            .replace(/^<\!\-\-\s*|\s*\-\->$/g, '')
            .replace(/'/g, '"')
            .replace(/finalStr=""/g, 'var finalStr=""')
            .replace(/sbbObj = /g, 'var sbbObj=')
            .replace(/sbbFrm=/g, 'var sbbFrm=')
            .replace(/i=0/g, 'var i=0')
            .replace(/document\./g, 'window\.document\.')

            .replace(/onclick="return "(.*?)""/g, 'value="$1"')
            .replace(/\.onclick\(\)/g, '\.getAttribute\(\'value\'\)')
            ;
    }

    /**
     *
     */
    _customReplaces(str) {
        let wrongRef = str.match(/} var (.*)=.*getElementsByName.*x=.*?\((.*?)\)/);
        if (null !== wrongRef)
            str = str.replace(wrongRef[2], wrongRef[1]);

        return str;
    }

    /**
     *
     */
    _parse(jsDetectionHTML) {
        return new Promise((resolve, reject) => {
            let markup = this._getEncoded(jsDetectionHTML);

            markup.functions = this._customReplaces(markup.functions);

            return JSDOM.env({
                html: markup.html,
                done: (err, window) => {
                    let getID = new Function('window', [
                            markup.functions,
                            'return',
                            markup.callback
                        ].join(' ')),
                        sessionKey = jsDetectionHTML.match(/document\.cookie="(.*?)=(.*?);/);

                    try {
                        let genPid = getID(window);
                        resolve({
                            key: sessionKey[1],
                            value: (0 < sessionKey[2].indexOf('genPid')) ? 'genPid' : sessionKey[2],
                            genPid: genPid
                        });
                    } catch(e) {
                        reject({error: e});
                    }
                }

            });
        });
    }

}

module.exports = JavascriptDetector;<|endoftext|>