<commit_before>import {
  name as LIB_NAME,
  version as LIB_VERSION
} from '../../package.json';

const {
  toString
} = Object.prototype;

function _isBasicObject(val) {
  return typeof val === 'object' &&
    val !== null &&
    val.__proto__ === undefined;
}

function _argsStr(count, name = 'arg') {
  let names = [];

  for (let i = 0; i < count; i++) {
    names.push(`${name}${i + 1}`);
  }

  return names.join(', ');
}

function typeStr(val, k = undefined) {
  let t = (_isBasicObject(val)) ?
    'BasicObject' :
    toString.call(val).match(/^\[object ([^\]]*)\]$/)[1];

  if (t === 'Object') {
    if (val.constructor && (
      (val.constructor.name && val.constructor.name !== t)
    )) {
      t = val.constructor.name;
    }
  }

  if (val instanceof Error) {
    // name might be a getter that throws
    try {
      let name = val.name;

      if (name && name !== t) {
        t = name;
      }
    } catch (err) {}
  }

  if (val instanceof Function) {
    if (val.name && val.name !== t && (
      val.name.match(/^[A-Z]/) ||
      (k &&
        ['__apivis__chain_link',
          'constructor',
          'prototype',
          '__proto__'
        ].includes(k)
      )
    )) {
      t = val.name;
    }

    t = `${t}(${_argsStr(val.length)})`;
  }

  if (val && (
    (val.hasOwnProperty && val.hasOwnProperty('constructor'))
  )) {
    if (!t.endsWith('Prototype') && (
      (t !== 'Object' || val === Object.prototype)
    )) {
      t = `${t}.prototype`;
    }
  }

  return t;
}

function descStr(val, k) {
  if (val === undefined || val === null) {
    return 'n/a';
  }

  let desc = Object.getOwnPropertyDescriptor(val, k);
  let d1 = '';
  let d2 = '';

  if (desc === undefined) {
    return 'n/a';
  }

  if (desc.hasOwnProperty('value')) { d1 += 'v'; }
  if (desc.writable) { d1 += 'w'; }
  if (desc.get) { d1 += 'g'; }
  if (desc.set) { d1 += 's'; }
  if (desc.enumerable) { d2 += 'e'; }
  if (desc.configurable) { d2 += 'c'; }

  return (d2) ? `${d1} ${d2}` : d1;
}

const _compare = (a, b) => {
  let sa = String(a);
  let sb = String(b);
  let na;
  let nb;

  if (Number.isNaN(na = Number(sa)) || Number.isNaN(nb = Number(sb))) {
    return (sa < sb) ? -1 : (sa > sb) ? 1 : 0;
  }

  return na - nb;
};

const _keys = (val, kind) =>
  (val === undefined || val === null) ?
    [] :
    Object[`getOwnProperty${kind}`](val).sort(_compare);

const _symbols = val => _keys(val, 'Symbols');
const _names = val => _keys(val, 'Names');

const members = val => _symbols(val).concat(_names(val));

function membersStr(val, indent = '  ', level = 0, leaf = val) {
  return members(val).
    map(k => {
      // Do not attempt to resolve these
      let skip = [
        'arguments',
        'callee',
        'caller'
      ];
      // Only resolve these in the context of leaf
      let leafOnly = [
        '__proto__'
      ];
      let v;
      let sv = '';

      // First resolve k in the context of leaf (like it would be normally)
      try {
        if (!skip.includes(k)) {
          v = leaf[k];
        }
      } catch (err) {
        v = err; // Make the error visible in the dump
      }

      // Then try resolving k in the context of val (reached through
      // following __proto__) to eventually get a shadowed value (some
      // props only make sense when resolved in the context of leaf
      // and an exception will be thrown upon trying to access them through val)
      try {
        if ( !(val === leaf || leafOnly.includes(k) || skip.includes(k)) ) {
          let shv = val[k];

          if (shv !== undefined && shv !== null) {
            v = shv;
          }
        }
      } catch (err) {
        // Leave v as set by trying to resolve k in the context of leaf
      }

      // Show select values
      switch (typeof v) {
      case 'boolean':
      case 'number':
        sv = `:${v}`;

        break;
      case 'string':
        sv = `:${JSON.stringify(v)}`;

        break;
      case 'object':
        if (Array.isArray(v) && v !== Array.prototype) {
          sv = `:${v.length}`;
        } else if (v instanceof Date) {
          sv = `:${JSON.stringify(v)}`;
        } else if (v instanceof Error) {
          // message might be a getter that throws
          try {
            let msg = v.message;

            if (msg) {
              sv = `:${JSON.stringify(msg)}`;
            }
          } catch (err) {}
        }

        break;
      }

      return `${indent.repeat(level)}${String(k)}{${descStr(val, k)}}: ${typeStr(v, k)}${sv}`;
    }).
    join('\n');
}

function chain(val) {
  let links = [val];

  for (let link = Object.getPrototypeOf(val);
    link;
    link = Object.getPrototypeOf(link)
  ) {
    links.push(link);
  }

  return links;
}

function chainStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]`).
    join('\n');
}

function apiStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]\n${membersStr(v, indent, i + 1, val)}`).
    join('\n');
}

// peek42 plugin
function peek42(fnOutput, fnComment) {
  return {
    type(val, comment = undefined, opts = undefined) {
      fnOutput(
        typeStr(val),
        fnComment(comment, val, 'type'),
        opts
      );
    },
    desc(val, k, comment = undefined, opts = undefined) {
      fnOutput(
        descStr(val, k),
        fnComment(comment, `${String(k)} in ${typeStr(val)}`, 'desc'),
        opts
      );
    },
    members(val, comment = undefined, opts = undefined) {
      fnOutput(
        membersStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined,
          (opts && typeof opts.indentLevel === 'number') ?
            opts.indentLevel :
            undefined
        ),
        fnComment(comment, typeStr(val), 'members'),
        opts
      );
    },
    chain(val, comment = undefined, opts = undefined) {
      fnOutput(
        chainStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'chain'),
        opts
      );
    },
    api(val, comment = undefined, opts = undefined) {
      fnOutput(
        apiStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'api'),
        opts
      );
    }
  };
}

const apivis = {
  get [Symbol.toStringTag]() {
    return LIB_NAME;
  },
  version: LIB_VERSION,
  typeStr,
  descStr,
  members,
  membersStr,
  chain,
  chainStr,
  apiStr,
  peek42
};

export {typeStr, descStr, members, membersStr, chain, chainStr, apiStr};
export default apivis;
<commit_msg>Swallow potential unhandled promise rejections on prop access<commit_after>import {
  name as LIB_NAME,
  version as LIB_VERSION
} from '../../package.json';

const {
  toString
} = Object.prototype;

function _isBasicObject(val) {
  return typeof val === 'object' &&
    val !== null &&
    val.__proto__ === undefined;
}

function _argsStr(count, name = 'arg') {
  let names = [];

  for (let i = 0; i < count; i++) {
    names.push(`${name}${i + 1}`);
  }

  return names.join(', ');
}

function typeStr(val, k = undefined) {
  let t = (_isBasicObject(val)) ?
    'BasicObject' :
    toString.call(val).match(/^\[object ([^\]]*)\]$/)[1];

  if (t === 'Object') {
    if (val.constructor && (
      (val.constructor.name && val.constructor.name !== t)
    )) {
      t = val.constructor.name;
    }
  }

  if (val instanceof Error) {
    // name might be a getter that throws
    try {
      let name = val.name;

      if (name && name !== t) {
        t = name;
      }
    } catch (err) {}
  }

  if (val instanceof Function) {
    if (val.name && val.name !== t && (
      val.name.match(/^[A-Z]/) ||
      (k &&
        ['__apivis__chain_link',
          'constructor',
          'prototype',
          '__proto__'
        ].includes(k)
      )
    )) {
      t = val.name;
    }

    t = `${t}(${_argsStr(val.length)})`;
  }

  if (val && (
    (val.hasOwnProperty && val.hasOwnProperty('constructor'))
  )) {
    if (!t.endsWith('Prototype') && (
      (t !== 'Object' || val === Object.prototype)
    )) {
      t = `${t}.prototype`;
    }
  }

  return t;
}

function descStr(val, k) {
  if (val === undefined || val === null) {
    return 'n/a';
  }

  let desc = Object.getOwnPropertyDescriptor(val, k);
  let d1 = '';
  let d2 = '';

  if (desc === undefined) {
    return 'n/a';
  }

  if (desc.hasOwnProperty('value')) { d1 += 'v'; }
  if (desc.writable) { d1 += 'w'; }
  if (desc.get) { d1 += 'g'; }
  if (desc.set) { d1 += 's'; }
  if (desc.enumerable) { d2 += 'e'; }
  if (desc.configurable) { d2 += 'c'; }

  return (d2) ? `${d1} ${d2}` : d1;
}

const _compare = (a, b) => {
  let sa = String(a);
  let sb = String(b);
  let na;
  let nb;

  if (Number.isNaN(na = Number(sa)) || Number.isNaN(nb = Number(sb))) {
    return (sa < sb) ? -1 : (sa > sb) ? 1 : 0;
  }

  return na - nb;
};

const _keys = (val, kind) =>
  (val === undefined || val === null) ?
    [] :
    Object[`getOwnProperty${kind}`](val).sort(_compare);

const _symbols = val => _keys(val, 'Symbols');
const _names = val => _keys(val, 'Names');

const members = val => _symbols(val).concat(_names(val));

const _swallowPromiseRejection = v => (
  (typeof v === 'object' && v !== null &&
    typeof v.catch === 'function' &&
      v.catch(err => {})),
  v
);

function membersStr(val, indent = '  ', level = 0, leaf = val) {
  return members(val).
    map(k => {
      // Do not attempt to resolve these
      let skip = [
        'arguments',
        'callee',
        'caller'
      ];
      // Only resolve these in the context of leaf
      let leafOnly = [
        '__proto__'
      ];
      let v;
      let sv = '';

      // First resolve k in the context of leaf (like it would be normally)
      try {
        if (!skip.includes(k)) {
          v = _swallowPromiseRejection(leaf[k]);
        }
      } catch (err) {
        v = err; // Make the error visible in the dump
      }

      // Then try resolving k in the context of val (reached through
      // following __proto__) to eventually get a shadowed value (some
      // props only make sense when resolved in the context of leaf
      // and an exception will be thrown upon trying to access them through val)
      try {
        if ( !(val === leaf || leafOnly.includes(k) || skip.includes(k)) ) {
          let shv = _swallowPromiseRejection(val[k]);

          if (shv !== undefined && shv !== null) {
            v = shv;
          }
        }
      } catch (err) {
        // Leave v as set by trying to resolve k in the context of leaf
      }

      // Show select values
      switch (typeof v) {
      case 'boolean':
      case 'number':
        sv = `:${v}`;

        break;
      case 'string':
        sv = `:${JSON.stringify(v)}`;

        break;
      case 'object':
        if (Array.isArray(v) && v !== Array.prototype) {
          sv = `:${v.length}`;
        } else if (v instanceof Date) {
          sv = `:${JSON.stringify(v)}`;
        } else if (v instanceof Error) {
          // message might be a getter that throws
          try {
            let msg = v.message;

            if (msg) {
              sv = `:${JSON.stringify(msg)}`;
            }
          } catch (err) {}
        }

        break;
      }

      return `${indent.repeat(level)}${String(k)}{${descStr(val, k)}}: ${typeStr(v, k)}${sv}`;
    }).
    join('\n');
}

function chain(val) {
  let links = [val];

  for (let link = Object.getPrototypeOf(val);
    link;
    link = Object.getPrototypeOf(link)
  ) {
    links.push(link);
  }

  return links;
}

function chainStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]`).
    join('\n');
}

function apiStr(val, indent = '  ') {
  return chain(val).
    reverse().
    map((v, i) => `${indent.repeat(i)}[${typeStr(v, '__apivis__chain_link')}]\n${membersStr(v, indent, i + 1, val)}`).
    join('\n');
}

// peek42 plugin
function peek42(fnOutput, fnComment) {
  return {
    type(val, comment = undefined, opts = undefined) {
      fnOutput(
        typeStr(val),
        fnComment(comment, val, 'type'),
        opts
      );
    },
    desc(val, k, comment = undefined, opts = undefined) {
      fnOutput(
        descStr(val, k),
        fnComment(comment, `${String(k)} in ${typeStr(val)}`, 'desc'),
        opts
      );
    },
    members(val, comment = undefined, opts = undefined) {
      fnOutput(
        membersStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined,
          (opts && typeof opts.indentLevel === 'number') ?
            opts.indentLevel :
            undefined
        ),
        fnComment(comment, typeStr(val), 'members'),
        opts
      );
    },
    chain(val, comment = undefined, opts = undefined) {
      fnOutput(
        chainStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'chain'),
        opts
      );
    },
    api(val, comment = undefined, opts = undefined) {
      fnOutput(
        apiStr(val,
          (opts && typeof opts.indent === 'string') ?
            opts.indent :
            undefined
        ),
        fnComment(comment, typeStr(val), 'api'),
        opts
      );
    }
  };
}

const apivis = {
  get [Symbol.toStringTag]() {
    return LIB_NAME;
  },
  version: LIB_VERSION,
  typeStr,
  descStr,
  members,
  membersStr,
  chain,
  chainStr,
  apiStr,
  peek42
};

export {typeStr, descStr, members, membersStr, chain, chainStr, apiStr};
export default apivis;
<|endoftext|>


<commit_before>/*jslint browser: true, undef: true*//*global Ext*/

/**
 * @abstract
 * An abstract class for singletons that facilitates communication with backend services
 *
 * TODO:
 * - add events for all lifecycle events: beforerequest, request, beforexception, exception, unauthorized
 * - does the touch version use Ext.Ajax or parent.request?
 * - pass through request options like touch version does
 */
Ext.define('Jarvus.util.AbstractAPI', {
    extend: 'Ext.data.Connection',
    requires: ['Ext.util.Cookies', 'Ext.Ajax',
               'Ext.Array'
    ],
    uses: [
        'Jarvus.util.APIDomain'
    ],

    config: {
        /**
         * @cfg {String/null}
         * A host to prefix URLs with, or null to leave paths domain-relative
         */
        host: null,

        /**
         * @cfg {Boolean}
         * True to use HTTPS when prefixing host. Only used if {@link #cfg-host} is set
         */
        useSSL: false,

        // @inheritdoc
        withCredentials: true
    },

    //@private
    buildUrl: function(path) {
        var host = this.getHost();
        return host ? (this.getUseSSL() ? 'https://' : 'http://')+host+path : path;
    },

    //@private
    buildHeaders: function(headers) {
        return headers;
    },

    //@private
    buildParams: function(params) {
        return params || null;
    },

    /**
     * Override {@link Ext.data.Connection#method-request} to implement auto-decoding and retry handler
     * @inheritdoc
     */
    request: function(options) {
        var me = this;

        return me.callParent([Ext.applyIf({
            url: me.buildUrl(options.url),
            withCredentials: true,
            params: me.buildParams(options.params),
            headers: me.buildHeaders(options.headers),
            timeout: options.timeout || 30000,
            success: function(response) {

                if (options.autoDecode !== false && response.getResponseHeader('Content-Type') == 'application/json') {
                    response.data = Ext.decode(response.responseText, true);
                }

                //Calling the callback function sending the decoded data
                Ext.callback(options.success, options.scope, [response]);

            },
            failure: function(response) {

                if (options.autoDecode !== false && response.getResponseHeader('Content-Type') == 'application/json') {
                    response.data = Ext.decode(response.responseText, true);
                }

                if (options.failure && options.failureStatusCodes && Ext.Array.contains(options.failureStatusCodes, response.status)) {
                    Ext.callback(options.failure, options.scope, [response]);
                } else if (options.exception) {
                    Ext.callback(options.exception, options.scope, [response]);
                } else if (response.aborted === true) {
                    Ext.callback(options.abort, options.scope, [response]);
                } else if (response.status == 401 || response.statusText.indexOf('Unauthorized') !== -1) {

                    /*
                    We seem to always get the same session id, so we can't automatically try again once the user logs in
                    var oldSessionID = Ext.util.Cookies.get('s');
                     */

                    Ext.override(Ext.Msg, {
                        hide: function () {
                            var me = this,
                                hideManually = me.cfg ? me.cfg.hideManually : false;

                            if (!hideManually) {
                                me.callParent(arguments);
                            }
                        }
                    });

                    var msg = Ext.Msg.show({
                        hideManually: true,
                        title: 'Login Required',
                        msg: "You've either logged out or your has session expired. Please login and try again.",
                        buttonText: {
                            'yes': 'Login',
                            'no': 'Try Again',
                            'cancel': 'Cancel'
                        },
                        scope: msg,
                        fn: function (btn) {
                            if (btn === 'yes') {
                                // login
                                var loginWindow = window.open(me.buildUrl('/login'), 'emergence-login');
                                loginWindow.focus();
                                return;
                            } else if (btn === 'no') {
                                // try again
                                me.request(options);
                            }

                            msg.cfg.hideManually = false;
                            msg.hide();
                        }
                    });

                    /*
                    if (oldSessionID !== null) {
                        var cookieCheckInterval = window.setInterval(function() {
                            console.log(oldSessionID);
                            console.warn(Ext.util.Cookies.get('s'));
                            if (Ext.util.Cookies.get('s') != oldSessionID) {
                                alert('new login');
                                debugger;
                                window.clearInterval(cookieCheckInterval);
                            }
                        }, 100);
                    }
                    */
                } else {
                    Ext.Msg.confirm('An error occurred', 'There was an error trying to reach the server. Do you want to try again?', function (btn) {
                        if (btn === 'yes') {
                            me.request(options);
                        }
                    });
                }

            },
            scope: options.scope
        }, options)]);
    },

    // @deprecated
    setHostname: function(hostname) {
        //<debug>
        Ext.Logger.deprecate('hostname config is deprecated, use host instead');
        //</debug>

        this.setHost(hostname);
    },

    // @deprecated
    getHostname: function() {
        //<debug>
        Ext.Logger.deprecate('hostname config is deprecated, use host instead');
        //</debug>

        return this.getHost();
    }
});
<commit_msg>don't set withCredentials on request, connection config value will be used now<commit_after>/*jslint browser: true, undef: true*//*global Ext*/

/**
 * @abstract
 * An abstract class for singletons that facilitates communication with backend services
 *
 * TODO:
 * - add events for all lifecycle events: beforerequest, request, beforexception, exception, unauthorized
 * - does the touch version use Ext.Ajax or parent.request?
 * - pass through request options like touch version does
 */
Ext.define('Jarvus.util.AbstractAPI', {
    extend: 'Ext.data.Connection',
    requires: ['Ext.util.Cookies', 'Ext.Ajax',
               'Ext.Array'
    ],
    uses: [
        'Jarvus.util.APIDomain'
    ],

    config: {
        /**
         * @cfg {String/null}
         * A host to prefix URLs with, or null to leave paths domain-relative
         */
        host: null,

        /**
         * @cfg {Boolean}
         * True to use HTTPS when prefixing host. Only used if {@link #cfg-host} is set
         */
        useSSL: false,

        // @inheritdoc
        withCredentials: true
    },

    //@private
    buildUrl: function(path) {
        var host = this.getHost();
        return host ? (this.getUseSSL() ? 'https://' : 'http://')+host+path : path;
    },

    //@private
    buildHeaders: function(headers) {
        return headers;
    },

    //@private
    buildParams: function(params) {
        return params || null;
    },

    /**
     * Override {@link Ext.data.Connection#method-request} to implement auto-decoding and retry handler
     * @inheritdoc
     */
    request: function(options) {
        var me = this;

        return me.callParent([Ext.applyIf({
            url: me.buildUrl(options.url),
            params: me.buildParams(options.params),
            headers: me.buildHeaders(options.headers),
            timeout: options.timeout || 30000,
            success: function(response) {

                if (options.autoDecode !== false && response.getResponseHeader('Content-Type') == 'application/json') {
                    response.data = Ext.decode(response.responseText, true);
                }

                //Calling the callback function sending the decoded data
                Ext.callback(options.success, options.scope, [response]);

            },
            failure: function(response) {

                if (options.autoDecode !== false && response.getResponseHeader('Content-Type') == 'application/json') {
                    response.data = Ext.decode(response.responseText, true);
                }

                if (options.failure && options.failureStatusCodes && Ext.Array.contains(options.failureStatusCodes, response.status)) {
                    Ext.callback(options.failure, options.scope, [response]);
                } else if (options.exception) {
                    Ext.callback(options.exception, options.scope, [response]);
                } else if (response.aborted === true) {
                    Ext.callback(options.abort, options.scope, [response]);
                } else if (response.status == 401 || response.statusText.indexOf('Unauthorized') !== -1) {

                    /*
                    We seem to always get the same session id, so we can't automatically try again once the user logs in
                    var oldSessionID = Ext.util.Cookies.get('s');
                     */

                    Ext.override(Ext.Msg, {
                        hide: function () {
                            var me = this,
                                hideManually = me.cfg ? me.cfg.hideManually : false;

                            if (!hideManually) {
                                me.callParent(arguments);
                            }
                        }
                    });

                    var msg = Ext.Msg.show({
                        hideManually: true,
                        title: 'Login Required',
                        msg: "You've either logged out or your has session expired. Please login and try again.",
                        buttonText: {
                            'yes': 'Login',
                            'no': 'Try Again',
                            'cancel': 'Cancel'
                        },
                        scope: msg,
                        fn: function (btn) {
                            if (btn === 'yes') {
                                // login
                                var loginWindow = window.open(me.buildUrl('/login'), 'emergence-login');
                                loginWindow.focus();
                                return;
                            } else if (btn === 'no') {
                                // try again
                                me.request(options);
                            }

                            msg.cfg.hideManually = false;
                            msg.hide();
                        }
                    });

                    /*
                    if (oldSessionID !== null) {
                        var cookieCheckInterval = window.setInterval(function() {
                            console.log(oldSessionID);
                            console.warn(Ext.util.Cookies.get('s'));
                            if (Ext.util.Cookies.get('s') != oldSessionID) {
                                alert('new login');
                                debugger;
                                window.clearInterval(cookieCheckInterval);
                            }
                        }, 100);
                    }
                    */
                } else {
                    Ext.Msg.confirm('An error occurred', 'There was an error trying to reach the server. Do you want to try again?', function (btn) {
                        if (btn === 'yes') {
                            me.request(options);
                        }
                    });
                }

            },
            scope: options.scope
        }, options)]);
    },

    // @deprecated
    setHostname: function(hostname) {
        //<debug>
        Ext.Logger.deprecate('hostname config is deprecated, use host instead');
        //</debug>

        this.setHost(hostname);
    },

    // @deprecated
    getHostname: function() {
        //<debug>
        Ext.Logger.deprecate('hostname config is deprecated, use host instead');
        //</debug>

        return this.getHost();
    }
});
<|endoftext|>


<commit_before>/**
 * Extra properties applied to the Discord.js message object.
 * @typedef {Object} Message
 * @prop {?CommandUtil} util - Utilities for command responding.
 * Only available in command-related functions as a parameter.
 * Not available in regex/conditional commands as those can be ran at the same time.
 */

class CommandUtil {
    /**
     * Command utilies.
     * @param {AkairoClient} client - The Akairo client.
     * @param {Message} message - Message that triggered the command.
     * @param {Command} command - Command triggered.
     * @param {string} prefix - Prefix used to trigger.
     * @param {string} alias - Alias used to trigger.
     */
    constructor(client, message, command, prefix, alias) {
        /**
         * The Akairo client.
         * @readonly
         * @name CommandUtil#client
         * @type {AkairoClient}
         */
        Object.defineProperties(this, {
            client: {
                value: client
            }
        });

        /**
         * Message that triggered the command.
         * @type {Message}
         */
        this.message = message;

        /**
         * Command used.
         * @type {Command}
         */
        this.command = command;

        /**
         * The prefix used.
         * @type {string}
         */
        this.prefix = prefix;

        /**
         * The alias used.
         * @type {string}
         */
        this.alias = alias;

        /**
         * Whether or not the last response should be edited.
         * @type {boolean}
         */
        this.shouldEdit = false;

         /**
          * The last response sent.
          * @type {?Message}
         */
        this.lastResponse = null;
    }

    /**
     * Sets the last repsonse.
     * @param {Message|Message[]} message - Message to set.
     * @returns {void}
     */
    setLastResponse(message) {
        if (!this.handler.handleEdits || !this.command.editable) return;

        if (Array.isArray(message)) {
            this.lastResponse = message.slice(-1)[0];
        } else {
            this.lastResponse = message;
        }
    }

    /**
     * Sends a response or edits an old response if available.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Promise<Message|Message[]>}
     */
    send(content, options) {
        [content, options] = this.constructor.swapOptions(content, options);

        if (this.shouldEdit && (this.command ? this.command.editable : true) && (!options.file || this.lastResponse.attachments.size)) {
            return this.lastResponse.edit(content, options);
        }

        return this.message.channel.send(content, options).then(sent => {
            if (options.file) return sent;
            if (this.lastResponse && this.lastResponse.attachments.size) return sent;

            this.shouldEdit = true;
            this.setLastResponse(sent);
            return sent;
        });
    }

    /**
     * Sends a response with a mention concantenated to it.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Promise<Message|Message[]>}
     */
    reply(content, options) {
        if (this.message.channel.type !== 'dm') content = `${this.message.author}, ${content}`;
        return this.send(content, options);
    }

    /**
     * Swaps and cleans up content and options.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Array}
     */
    static swapOptions(content, options) {
        if (!options && typeof content === 'object' && !(content instanceof Array)) {
            options = content;
            content = '';
        } else if (!options) {
            options = {};
        }

        if (!options.embed) options.embed = null;
        return [content, options];
    }
}

module.exports = CommandUtil;
<commit_msg>Fix setLastResponse<commit_after>/**
 * Extra properties applied to the Discord.js message object.
 * @typedef {Object} Message
 * @prop {?CommandUtil} util - Utilities for command responding.
 * Only available in command-related functions as a parameter.
 * Not available in regex/conditional commands as those can be ran at the same time.
 */

class CommandUtil {
    /**
     * Command utilies.
     * @param {AkairoClient} client - The Akairo client.
     * @param {Message} message - Message that triggered the command.
     * @param {Command} command - Command triggered.
     * @param {string} prefix - Prefix used to trigger.
     * @param {string} alias - Alias used to trigger.
     */
    constructor(client, message, command, prefix, alias) {
        /**
         * The Akairo client.
         * @readonly
         * @name CommandUtil#client
         * @type {AkairoClient}
         */
        Object.defineProperties(this, {
            client: {
                value: client
            }
        });

        /**
         * Message that triggered the command.
         * @type {Message}
         */
        this.message = message;

        /**
         * Command used.
         * @type {Command}
         */
        this.command = command;

        /**
         * The prefix used.
         * @type {string}
         */
        this.prefix = prefix;

        /**
         * The alias used.
         * @type {string}
         */
        this.alias = alias;

        /**
         * Whether or not the last response should be edited.
         * @type {boolean}
         */
        this.shouldEdit = false;

         /**
          * The last response sent.
          * @type {?Message}
         */
        this.lastResponse = null;
    }

    /**
     * Sets the last repsonse.
     * @param {Message|Message[]} message - Message to set.
     * @returns {void}
     */
    setLastResponse(message) {
        if (!this.command.handler.handleEdits || !this.command.editable) return;

        if (Array.isArray(message)) {
            this.lastResponse = message.slice(-1)[0];
        } else {
            this.lastResponse = message;
        }
    }

    /**
     * Sends a response or edits an old response if available.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Promise<Message|Message[]>}
     */
    send(content, options) {
        [content, options] = this.constructor.swapOptions(content, options);

        if (this.shouldEdit && (this.command ? this.command.editable : true) && (!options.file || this.lastResponse.attachments.size)) {
            return this.lastResponse.edit(content, options);
        }

        return this.message.channel.send(content, options).then(sent => {
            if (options.file) return sent;
            if (this.lastResponse && this.lastResponse.attachments.size) return sent;

            this.shouldEdit = true;
            this.setLastResponse(sent);
            return sent;
        });
    }

    /**
     * Sends a response with a mention concantenated to it.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Promise<Message|Message[]>}
     */
    reply(content, options) {
        if (this.message.channel.type !== 'dm') content = `${this.message.author}, ${content}`;
        return this.send(content, options);
    }

    /**
     * Swaps and cleans up content and options.
     * @param {string|MessageOptions} content - Content to send.
     * @param {MessageOptions} [options] - Options to use.
     * @returns {Array}
     */
    static swapOptions(content, options) {
        if (!options && typeof content === 'object' && !(content instanceof Array)) {
            options = content;
            content = '';
        } else if (!options) {
            options = {};
        }

        if (!options.embed) options.embed = null;
        return [content, options];
    }
}

module.exports = CommandUtil;
<|endoftext|>


<commit_before>/*
 * ------------------------------------------
 * 自定义事件实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
/** @module util/event/event */
NEJ.define([
    'base/global',
    'base/klass',
    'base/element',
    'base/event',
    'base/util',
    'util/event'
],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){
    var _pro;
    /**
     * 自定义事件封装对象，封装的事件支持通过事件相关接口进行添加、删除等操作
     *
     * 脚本举例
     * ```javascript
     * NEJ.define([
     *     'base/event'
     *     'util/event'
     * ],function(_v,_t){
     *     // 支持自定义事件
     *     _t._$$CustomEvent._$allocate({
     *         element:window,
     *         event:'ok'
     *     });
     *
     *     // 添加自定义事件
     *     _v._$addEvent(window,'ok',function(){alert(0);});
     *     _v._$addEvent(window,'ok',function(){alert(1);});
     *
     *     // 删除自定义事件
     *     _v._$delEvent(window,'ok',function(){alert(0);});
     *     _v._$clearEvent(window,'ok');
     *
     *     // 触发自定义事件
     *     window.onok({a:'aaaaa'});
     *     _v._$dispatchEvent(window,'ok',{a:'aaaaa'});
     * });
     * ```
     *
     * @class    module:util/event/event._$$CustomEvent
     * @extends  module:util/event._$$EventTarget
     *
     * @param    {Object}       config  - 可选配置参数
     * @property {String|Node}  element - 事件关联节点ID或者对象，默认为window对象
     * @property {String|Array} event   - 事件名称或者名称列表
     */
    /**
     * 初始化时触发事件
     *
     * @event module:util/event/event._$$CustomEvent#oninit
     * @param {Object} event - 事件信息
     */
    /**
     * 事件调度前触发事件
     *
     * @event    module:util/event/event._$$CustomEvent#ondispatch
     * @param    {Object} event - 事件信息
     * @property {String} type  - 事件类型
     */
    /**
     * 添加事件时触发事件
     *
     * @event    module:util/event/event._$$CustomEvent#oneventadd
     * @param    {Object}   event    - 事件信息
     * @property {String}   type     - 事件类型
     * @property {Function} listener - 事件执行函数
     */
    _p._$$CustomEvent = _k._$klass();
    _pro = _p._$$CustomEvent._$extend(_t._$$EventTarget);
    /**
     * 控件初始化
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__init
     * @return {Void}
     */
    _pro.__init = function(){
        // onxxx - event entry handler
        //   xxx - event callback handler list
        this.__cache = {};
        this.__super();
    };
    /**
     * 控件重置
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__reset
     * @param  {Object} arg0 - 可选配置参数
     * @return {Void}
     */
    _pro.__reset = function(_options){
        this.__super(_options);
        this.__element = _e._$get(_options.element)||window;
        // init event
        this.__doEventInit(_options.event);
        this.__doEventAPIEnhance();
        this._$dispatchEvent('oninit');
    };
    /**
     * 销毁控件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__destroy
     * @return {Void}
     */
    _pro.__destroy = (function(){
        var _doClear = function(_value,_key,_map){
            if (!_u._$isArray(_value)){
                _u._$safeDelete(this.__element,_key);
            }
            delete _map[_key];
        };
        return function(){
            this.__super();
            // clear cache
            _u._$loop(
                this.__cache,_doClear,this
            );
            delete this.__element;
        };
    })();
    /**
     * 判断是否需要代理事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__isDelegate
     * @param  {String|Node} arg0 - 节点
     * @param  {String}      arg1 - 事件
     * @return {Boolean}            是否需要代理事件
     */
    _pro.__isDelegate = function(_element,_type){
        _element = _e._$get(_element);
        return _element===this.__element&&
               (!_type||!!this.__cache['on'+_type]);
    };
    /**
     * 初始化事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__doEventInit
     * @param  {String} arg0 - 事件名称
     * @return {Void}
     */
    _pro.__doEventInit = function(_event){
        if (_u._$isString(_event)){
            var _name = 'on'+_event;
            if (!this.__cache[_name]){
                this.__cache[_name] =
                    this.__doEventDispatch.
                        _$bind(this,_event);
            }
            this.__doEventBind(_event);
            return;
        }
        if (_u._$isArray(_event)){
            _u._$forEach(
                _event,this.__doEventInit,this
            );
        }
    };
    /**
     * 绑定事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__doEventBind
     * @param  {String} arg0 - 事件名称
     * @return {Void}
     */
    _pro.__doEventBind = function(_type){
        var _event = 'on'+_type,
            _handler = this.__element[_event],
            _handler1 = this.__cache[_event];
        if (_handler!=_handler1){
            this.__doEventDelete(_type);
            if (!!_handler&&_handler!=_f){
                this.__doEventAdd(_type,_handler);
            }
            this.__element[_event] = _handler1;
        }
    };
    /**
     * 添加事件
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventAdd
     * @param  {String}   arg0 - 事件名称
     * @param  {Function} arg1 - 事件回调
     * @return {Void}
     */
    _pro.__doEventAdd = function(_type,_handler,_front){
        var _list = this.__cache[_type];
        if (!_list){
            _list = [];
            this.__cache[_type] = _list;
        }
        if (_u._$isFunction(_handler)){
            !_front ? _list.push(_handler)
                    : _list.unshift(_handler);
        }
    };
    /**
     * 删除事件
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventDelete
     * @param  {String}   arg0 - 事件名称
     * @param  {Function} arg1 - 事件回调
     * @return {Void}
     */
    _pro.__doEventDelete = function(_type,_handler){
        var _list = this.__cache[_type];
        if (!_list||!_list.length) return;
        // clear all event handler
        if (!_handler){
            delete this.__cache[_type];
            return;
        }
        // delete one event handler
        _u._$reverseEach(
            _list,function(_value,_index,_xlist){
                if (_handler===_value){
                    _xlist.splice(_index,1);
                    return !0;
                }
            }
        );
    };
    /**
     * 事件调度
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventDispatch
     * @param  {String} arg0 - 事件名称
     * @param  {Object} arg1 - 事件对象
     * @return {Void}
     */
    _pro.__doEventDispatch = function(_type,_event){
        _event = _event||{noargs:!0};
        if (_event==_o){
            _event = {};
        }
        _event.type = _type;
        this._$dispatchEvent('ondispatch',_event);
        if (!!_event.stopped) return;
        _u._$forEach(
            this.__cache[_type],function(_handler){
                try{
                    _handler(_event);
                }catch(ex){
                    // ignore
                    console.error(ex.message);
                    console.error(ex.stack);
                }
            }
        );
    };
    /**
     * 增强事件操作API
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventAPIEnhance
     * @return {Void}
     */
    _pro.__doEventAPIEnhance = (function(){
        var _doAddEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                this.__doEventBind(_type);
                this.__doEventAdd(_type,_args[2],_args[3]);
                this._$dispatchEvent('oneventadd',{
                    type:_type,
                    listener:_args[2]
                });
            }
        };
        var _doDelEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                this.__doEventDelete(_type,_args[2]);
            }
        };
        var _doClearEvent = function(_event){
            var _args = _event.args,
                _type = (_args[1]||'').toLowerCase();
            if (this.__isDelegate(_args[0])){
                if (!!_type){
                    this.__doEventDelete(_type);
                    return;
                }
                _u._$loop(
                    this.__cache,function(_value,_key){
                        if (_u._$isArray(_value)){
                            this.__doEventDelete(_key);
                        }
                    },this
                );
            }
        };
        var _doDispatchEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                _args[0]['on'+_type].apply(_args[0],_args.slice(2));
            }
        };
        return function(){
            // void multi-enhance
            if (!!this.__enhanced){
                return;
            }
            // enhance event api
            this.__enhanced = true;
            _v._$addEvent = _v._$addEvent._$aop(_doAddEvent._$bind(this));
            _v._$delEvent = _v._$delEvent._$aop(_doDelEvent._$bind(this));
            _v._$clearEvent = _v._$clearEvent._$aop(_doClearEvent._$bind(this));
            _v._$dispatchEvent = _v._$dispatchEvent._$aop(_doDispatchEvent._$bind(this));

            if (CMPT){
                NEJ.copy(NEJ.P('nej.v'),_v);
            }
        };
    })();

    if (CMPT){
        NEJ.copy(NEJ.P('nej.ut'),_p);
    }

    return _p;
});
<commit_msg>no catch for event.js in debug mode<commit_after>/*
 * ------------------------------------------
 * 自定义事件实现文件
 * @version  1.0
 * @author   genify(caijf@corp.netease.com)
 * ------------------------------------------
 */
/** @module util/event/event */
NEJ.define([
    'base/global',
    'base/klass',
    'base/element',
    'base/event',
    'base/util',
    'util/event'
],function(NEJ,_k,_e,_v,_u,_t,_p,_o,_f,_r){
    var _pro;
    /**
     * 自定义事件封装对象，封装的事件支持通过事件相关接口进行添加、删除等操作
     *
     * 脚本举例
     * ```javascript
     * NEJ.define([
     *     'base/event'
     *     'util/event'
     * ],function(_v,_t){
     *     // 支持自定义事件
     *     _t._$$CustomEvent._$allocate({
     *         element:window,
     *         event:'ok'
     *     });
     *
     *     // 添加自定义事件
     *     _v._$addEvent(window,'ok',function(){alert(0);});
     *     _v._$addEvent(window,'ok',function(){alert(1);});
     *
     *     // 删除自定义事件
     *     _v._$delEvent(window,'ok',function(){alert(0);});
     *     _v._$clearEvent(window,'ok');
     *
     *     // 触发自定义事件
     *     window.onok({a:'aaaaa'});
     *     _v._$dispatchEvent(window,'ok',{a:'aaaaa'});
     * });
     * ```
     *
     * @class    module:util/event/event._$$CustomEvent
     * @extends  module:util/event._$$EventTarget
     *
     * @param    {Object}       config  - 可选配置参数
     * @property {String|Node}  element - 事件关联节点ID或者对象，默认为window对象
     * @property {String|Array} event   - 事件名称或者名称列表
     */
    /**
     * 初始化时触发事件
     *
     * @event module:util/event/event._$$CustomEvent#oninit
     * @param {Object} event - 事件信息
     */
    /**
     * 事件调度前触发事件
     *
     * @event    module:util/event/event._$$CustomEvent#ondispatch
     * @param    {Object} event - 事件信息
     * @property {String} type  - 事件类型
     */
    /**
     * 添加事件时触发事件
     *
     * @event    module:util/event/event._$$CustomEvent#oneventadd
     * @param    {Object}   event    - 事件信息
     * @property {String}   type     - 事件类型
     * @property {Function} listener - 事件执行函数
     */
    _p._$$CustomEvent = _k._$klass();
    _pro = _p._$$CustomEvent._$extend(_t._$$EventTarget);
    /**
     * 控件初始化
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__init
     * @return {Void}
     */
    _pro.__init = function(){
        // onxxx - event entry handler
        //   xxx - event callback handler list
        this.__cache = {};
        this.__super();
    };
    /**
     * 控件重置
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__reset
     * @param  {Object} arg0 - 可选配置参数
     * @return {Void}
     */
    _pro.__reset = function(_options){
        this.__super(_options);
        this.__element = _e._$get(_options.element)||window;
        // init event
        this.__doEventInit(_options.event);
        this.__doEventAPIEnhance();
        this._$dispatchEvent('oninit');
    };
    /**
     * 销毁控件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__destroy
     * @return {Void}
     */
    _pro.__destroy = (function(){
        var _doClear = function(_value,_key,_map){
            if (!_u._$isArray(_value)){
                _u._$safeDelete(this.__element,_key);
            }
            delete _map[_key];
        };
        return function(){
            this.__super();
            // clear cache
            _u._$loop(
                this.__cache,_doClear,this
            );
            delete this.__element;
        };
    })();
    /**
     * 判断是否需要代理事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__isDelegate
     * @param  {String|Node} arg0 - 节点
     * @param  {String}      arg1 - 事件
     * @return {Boolean}            是否需要代理事件
     */
    _pro.__isDelegate = function(_element,_type){
        _element = _e._$get(_element);
        return _element===this.__element&&
               (!_type||!!this.__cache['on'+_type]);
    };
    /**
     * 初始化事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__doEventInit
     * @param  {String} arg0 - 事件名称
     * @return {Void}
     */
    _pro.__doEventInit = function(_event){
        if (_u._$isString(_event)){
            var _name = 'on'+_event;
            if (!this.__cache[_name]){
                this.__cache[_name] =
                    this.__doEventDispatch.
                        _$bind(this,_event);
            }
            this.__doEventBind(_event);
            return;
        }
        if (_u._$isArray(_event)){
            _u._$forEach(
                _event,this.__doEventInit,this
            );
        }
    };
    /**
     * 绑定事件
     *
     * @protected
     * @method module:util/event/event._$$CustomEvent#__doEventBind
     * @param  {String} arg0 - 事件名称
     * @return {Void}
     */
    _pro.__doEventBind = function(_type){
        var _event = 'on'+_type,
            _handler = this.__element[_event],
            _handler1 = this.__cache[_event];
        if (_handler!=_handler1){
            this.__doEventDelete(_type);
            if (!!_handler&&_handler!=_f){
                this.__doEventAdd(_type,_handler);
            }
            this.__element[_event] = _handler1;
        }
    };
    /**
     * 添加事件
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventAdd
     * @param  {String}   arg0 - 事件名称
     * @param  {Function} arg1 - 事件回调
     * @return {Void}
     */
    _pro.__doEventAdd = function(_type,_handler,_front){
        var _list = this.__cache[_type];
        if (!_list){
            _list = [];
            this.__cache[_type] = _list;
        }
        if (_u._$isFunction(_handler)){
            !_front ? _list.push(_handler)
                    : _list.unshift(_handler);
        }
    };
    /**
     * 删除事件
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventDelete
     * @param  {String}   arg0 - 事件名称
     * @param  {Function} arg1 - 事件回调
     * @return {Void}
     */
    _pro.__doEventDelete = function(_type,_handler){
        var _list = this.__cache[_type];
        if (!_list||!_list.length) return;
        // clear all event handler
        if (!_handler){
            delete this.__cache[_type];
            return;
        }
        // delete one event handler
        _u._$reverseEach(
            _list,function(_value,_index,_xlist){
                if (_handler===_value){
                    _xlist.splice(_index,1);
                    return !0;
                }
            }
        );
    };
    /**
     * 事件调度
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventDispatch
     * @param  {String} arg0 - 事件名称
     * @param  {Object} arg1 - 事件对象
     * @return {Void}
     */
    _pro.__doEventDispatch = function(_type,_event){
        _event = _event||{noargs:!0};
        if (_event==_o){
            _event = {};
        }
        _event.type = _type;
        this._$dispatchEvent('ondispatch',_event);
        if (!!_event.stopped) return;
        _u._$forEach(
            this.__cache[_type],function(_handler){
                if (DEBUG){
                    _handler(_event);
                }else{
                    try{
                        _handler(_event);
                    }catch(ex){
                        // ignore
                        console.error(ex.message);
                        console.error(ex.stack);
                    }
                }
            }
        );
    };
    /**
     * 增强事件操作API
     *
     * protected
     * @method module:util/event/event._$$CustomEvent#__doEventAPIEnhance
     * @return {Void}
     */
    _pro.__doEventAPIEnhance = (function(){
        var _doAddEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                this.__doEventBind(_type);
                this.__doEventAdd(_type,_args[2],_args[3]);
                this._$dispatchEvent('oneventadd',{
                    type:_type,
                    listener:_args[2]
                });
            }
        };
        var _doDelEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                this.__doEventDelete(_type,_args[2]);
            }
        };
        var _doClearEvent = function(_event){
            var _args = _event.args,
                _type = (_args[1]||'').toLowerCase();
            if (this.__isDelegate(_args[0])){
                if (!!_type){
                    this.__doEventDelete(_type);
                    return;
                }
                _u._$loop(
                    this.__cache,function(_value,_key){
                        if (_u._$isArray(_value)){
                            this.__doEventDelete(_key);
                        }
                    },this
                );
            }
        };
        var _doDispatchEvent = function(_event){
            var _args = _event.args,
                _type = _args[1].toLowerCase();
            if (this.__isDelegate(_args[0],_type)){
                _event.stopped = !0;
                _args[0]['on'+_type].apply(_args[0],_args.slice(2));
            }
        };
        return function(){
            // void multi-enhance
            if (!!this.__enhanced){
                return;
            }
            // enhance event api
            this.__enhanced = true;
            _v._$addEvent = _v._$addEvent._$aop(_doAddEvent._$bind(this));
            _v._$delEvent = _v._$delEvent._$aop(_doDelEvent._$bind(this));
            _v._$clearEvent = _v._$clearEvent._$aop(_doClearEvent._$bind(this));
            _v._$dispatchEvent = _v._$dispatchEvent._$aop(_doDispatchEvent._$bind(this));

            if (CMPT){
                NEJ.copy(NEJ.P('nej.v'),_v);
            }
        };
    })();

    if (CMPT){
        NEJ.copy(NEJ.P('nej.ut'),_p);
    }

    return _p;
});
<|endoftext|>


<commit_before>import { warningNotification } from "../actions/notifications";
import { charonAPIAddress } from "./globals";
import { NEW_NARRATIVE, NEW_POST } from "../actions/types";

// eslint-disable-next-line
export const getNarrative = (dispatch, datapath) => {
  const errorHandler = (e) => {
    // dispatch(warningNotification({message: "Failed to get narrative from server"}));
    console.error("Failed to get narrative from server");
    console.error(e);
  };
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.onload = () => {
    if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
      dispatch({
        type: NEW_NARRATIVE,
        blocks: JSON.parse(xmlHttp.responseText)
      });
    } else {
      errorHandler(xmlHttp);
    }
  };
  xmlHttp.onerror = errorHandler;
  const name = datapath.replace(/^\//, '').replace(/\//, '_');
  xmlHttp.open("get", `${charonAPIAddress}request=narrative&name=${name}`, true);
  xmlHttp.send(null);
};

export const getPost = (name) => (dispatch) => {
  console.log("fetching", name)
  const errorHandler = (e) => {
    dispatch(warningNotification({
      message: "Failed to get post from server",
      details: name
    }));
    console.error(e);
  };
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.onload = () => {
    if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
      dispatch({
        type: NEW_POST,
        html: xmlHttp.responseText,
        name: name
      });
    } else {
      errorHandler(xmlHttp);
    }
  };
  xmlHttp.onerror = errorHandler;
  xmlHttp.open("get", `${charonAPIAddress}request=post&path=${name}`, true);
  xmlHttp.send(null);
}
<commit_msg>posts use URL pushState<commit_after>import { warningNotification } from "../actions/notifications";
import { charonAPIAddress } from "./globals";
import { NEW_NARRATIVE, NEW_POST } from "../actions/types";

// eslint-disable-next-line
export const getNarrative = (dispatch, datapath) => {
  const errorHandler = (e) => {
    // dispatch(warningNotification({message: "Failed to get narrative from server"}));
    console.error("Failed to get narrative from server");
    console.error(e);
  };
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.onload = () => {
    if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
      dispatch({
        type: NEW_NARRATIVE,
        blocks: JSON.parse(xmlHttp.responseText)
      });
    } else {
      errorHandler(xmlHttp);
    }
  };
  xmlHttp.onerror = errorHandler;
  const name = datapath.replace(/^\//, '').replace(/\//, '_');
  xmlHttp.open("get", `${charonAPIAddress}request=narrative&name=${name}`, true);
  xmlHttp.send(null);
};

export const getPost = (name) => (dispatch) => {
  console.log("fetching", name)
  const errorHandler = (e) => {
    dispatch(warningNotification({
      message: "Failed to get post from server",
      details: name
    }));
    console.error(e);
  };
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.onload = () => {
    if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
      dispatch({
        type: NEW_POST,
        html: xmlHttp.responseText,
        name: name,
        pushState: true
      });
    } else {
      errorHandler(xmlHttp);
    }
  };
  xmlHttp.onerror = errorHandler;
  xmlHttp.open("get", `${charonAPIAddress}request=post&path=${name}`, true);
  xmlHttp.send(null);
}
<|endoftext|>


<commit_before>'use strict'

const { preparePrice, prepareAmount } = require('bfx-api-node-util')
const runExample = require('../util/run_example')

module.exports = runExample({
  name: 'rest-get-tickers',
  rest: { transform: true },
  params: {
    filterByMarket: null
  }
}, async ({ rest, debug, debugTable, params }) => {
  const { filterByMarket } = params

  debug('fetching symbol list...')

  const rawSymbols = await rest.symbols()

  debug('read %d symbols', rawSymbols.length)

  const symbols = rawSymbols
    .map(s => `t${s.toUpperCase()}`)
    .filter(s => (
      !filterByMarket || (s === filterByMarket)
    ))

  if (symbols.length === 0) {
    return debug('no tickers match provided filters')
  }

  debug('fetching %d tickers...', symbols.length)

  const tickers = await rest.tickers(symbols)

  debugTable({
    colWidths: [10, 14, 14, 14, 14, 14, 14, 18, 18],
    headers: [
      'Symbol', 'Last', 'High', 'Low', 'Daily Change', 'Bid', 'Ask', 'Bid Size',
      'Ask Size'
    ],

    rows: tickers.map(t => ([
      t.symbol, preparePrice(t.lastPrice), preparePrice(t.high),
      preparePrice(t.low), (t.dailyChange * 100).toFixed(2), preparePrice(t.bid),
      preparePrice(t.ask), prepareAmount(t.bidSize), prepareAmount(t.askSize)
    ]))
  })
})
<commit_msg>update 'tickers' example<commit_after>'use strict'

const { preparePrice, prepareAmount } = require('bfx-api-node-util')
const { RESTv2 } = require('bfx-api-node-rest')
const { args: { apiKey, apiSecret }, debug, debugTable } = require('../util/setup')

async function execute () {
  const rest = new RESTv2({
    apiKey,
    apiSecret,
    transform: true
  })
  const filterByMarket = null

  debug('fetching symbol list...')

  const rawSymbols = await rest.symbols()

  debug('read %d symbols', rawSymbols.length)

  const symbols = rawSymbols
    .map(s => `t${s.toUpperCase()}`)
    .filter(s => (
      !filterByMarket || (s === filterByMarket)
    ))

  if (symbols.length === 0) {
    return debug('no tickers match provided filters')
  }

  debug('fetching %d tickers...', symbols.length)

  const tickers = await rest.tickers(symbols)

  debugTable({
    colWidths: [10, 14, 14, 14, 14, 14, 14, 18, 18],
    headers: [
      'Symbol', 'Last', 'High', 'Low', 'Daily Change', 'Bid', 'Ask', 'Bid Size',
      'Ask Size'
    ],

    rows: tickers.map(t => ([
      t.symbol, preparePrice(t.lastPrice), preparePrice(t.high),
      preparePrice(t.low), (t.dailyChange * 100).toFixed(2), preparePrice(t.bid),
      preparePrice(t.ask), prepareAmount(t.bidSize), prepareAmount(t.askSize)
    ]))
  })
}

execute()
<|endoftext|>


<commit_before>(function() {

    /**
     * Tracks the active view of the given xml3d tag for changes and applies
     * the changed pose to the given transform node.
     *
     * @param {!Object} _targetTransform the transform element to which the view
     *      changes are propagated.
     */
    var ViewTracker = function(_targetTransform)
    {
        this.targetTransform = _targetTransform;
        if(!this.targetTransform)
            throw "ViewTracker: no target transformation specified.";

        this.xml3d = XMOT.util.getXml3dRoot(_targetTransform);
        if(!this.xml3d)
            throw "ViewTracker: given node is not a child of an xml3d element.";

        this.targetNode = null; // the current view element that is tracked
        this._xfmObs = null; // the TransformTracker used to track changes in the active view element

        this._attached = false;

        this.attach();
    };

    var p = ViewTracker.prototype;

    /** Event handler to be overriden by the user
     *
     * @param targetNode the node this observer tracks
     * @param evt the original DOM event that caused the change
     */
    p.xfmChanged = function(targetNode, evt) { };

    p.attach = function()
    {
        if(!this._attached)
        {
            this.xml3d.addEventListener("DOMAttrModified",
                XMOT.util.wrapCallback(this, _onXml3DAttrModified), false);

            this.targetNode = XMOT.util.getOrCreateActiveView(this.xml3d);

            if(this._xfmObs)
                this._xfmObs.detach();
            this._xfmObs = new XMOT.TransformTracker(this.targetNode);
            this._xfmObs.xfmChanged = XMOT.util.wrapCallback(this, _onXfmChanged);

            _onXfmChanged.apply(this, this.targetNode);

            this._attached = true;
        }
    };

    p.detach = function()
    {
        if(this._attached)
        {
            this._xfmObs.detach();
            this.xml3d.removeEventListener("DOMAttrModified",
                XMOT.util.wrapCallback(this, _onXml3DAttrModified), false);

            this._attached = false;
        }
    };

    function _onXml3DAttrModified(evt)
    {
        if(evt.attrName !== "activeView")
            return;

        this.detach();
        this.attach();
    };

    function _onXfmChanged(targetNode, evt)
    {
        var mat = this.targetNode.getWorldMatrix();

        var transl = new window.XML3DVec3(mat.m41, mat.m42, mat.m43);
        var rot = window.XML3DRotation.fromMatrix(mat);

        this.targetTransform.setAttribute("translation", transl.str());
        this.targetTransform.setAttribute("rotation", rot.str());

        this.xfmChanged(this.targetNode, evt);
    };

    // export
    XMOT.ViewTracker = ViewTracker;
}());
<commit_msg>viewtracker: fixed namespace bug<commit_after>(function() {

    /**
     * Tracks the active view of the given xml3d tag for changes and applies
     * the changed pose to the given transform node.
     *
     * @param {!Object} _targetTransform the transform element to which the view
     *      changes are propagated.
     */
    var ViewTracker = function(_targetTransform)
    {
        this.targetTransform = _targetTransform;
        if(!this.targetTransform)
            throw "ViewTracker: no target transformation specified.";

        this.xml3d = XMOT.util.getXml3dRoot(_targetTransform);
        if(!this.xml3d)
            throw "ViewTracker: given node is not a child of an xml3d element.";

        this.targetNode = null; // the current view element that is tracked
        this._xfmObs = null; // the TransformTracker used to track changes in the active view element

        this._attached = false;

        this.attach();
    };

    var p = ViewTracker.prototype;

    /** Event handler to be overriden by the user
     *
     * @param targetNode the node this observer tracks
     * @param evt the original DOM event that caused the change
     */
    p.xfmChanged = function(targetNode, evt) { };

    p.attach = function()
    {
        if(!this._attached)
        {
            this.xml3d.addEventListener("DOMAttrModified",
                XMOT.util.wrapCallback(this, _onXml3DAttrModified), false);

            this.targetNode = XML3D.util.getOrCreateActiveView(this.xml3d);

            if(this._xfmObs)
                this._xfmObs.detach();
            this._xfmObs = new XMOT.TransformTracker(this.targetNode);
            this._xfmObs.xfmChanged = XMOT.util.wrapCallback(this, _onXfmChanged);

            _onXfmChanged.apply(this, this.targetNode);

            this._attached = true;
        }
    };

    p.detach = function()
    {
        if(this._attached)
        {
            this._xfmObs.detach();
            this.xml3d.removeEventListener("DOMAttrModified",
                XMOT.util.wrapCallback(this, _onXml3DAttrModified), false);

            this._attached = false;
        }
    };

    function _onXml3DAttrModified(evt)
    {
        if(evt.attrName !== "activeView")
            return;

        this.detach();
        this.attach();
    };

    function _onXfmChanged(targetNode, evt)
    {
        var mat = this.targetNode.getWorldMatrix();

        var transl = new window.XML3DVec3(mat.m41, mat.m42, mat.m43);
        var rot = window.XML3DRotation.fromMatrix(mat);

        this.targetTransform.setAttribute("translation", transl.str());
        this.targetTransform.setAttribute("rotation", rot.str());

        this.xfmChanged(this.targetNode, evt);
    };

    // export
    XMOT.ViewTracker = ViewTracker;
}());
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, CodeMirror */

/**
 * Functions for iterating through tokens in the current editor buffer. Useful for doing
 * light parsing that can rely purely on information gathered by the code coloring mechanism.
 */

define(function (require, exports, module) {
    "use strict";

   /**
     * Creates a context object for the given editor and position, suitable for passing to the
     * move functions.
     * @param {CodeMirror} editor
     * @param {{ch:{string}, line:{number}} pos
     * @return {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}
     */
    function getInitialContext(editor, pos) {
        return {
            "editor": editor,
            "pos": pos,
            "token": editor.getTokenAt(pos)
        };
    }

    /**
     * Moves the given context backwards by one token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function movePrevToken(ctx) {
        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {
            //move up a line
            if (ctx.pos.line <= 0) {
                return false; //at the top already
            }
            ctx.pos.line--;
            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;
        } else {
            ctx.pos.ch = ctx.token.start;
        }
        ctx.token = ctx.editor.getTokenAt(ctx.pos);
        return true;
    }

    /**
     * Moves the given context forward by one token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function moveNextToken(ctx) {
        var eol = ctx.editor.getLine(ctx.pos.line).length;
        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {
            //move down a line
            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {
                return false; //at the bottom
            }
            ctx.pos.line++;
            ctx.pos.ch = 0;
        } else {
            ctx.pos.ch = ctx.token.end + 1;
        }
        ctx.token = ctx.editor.getTokenAt(ctx.pos);
        return true;
    }

   /**
     * Moves the given context in the given direction, skipping any whitespace it hits.
     * @param {function} moveFxn the funciton to move the context
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function moveSkippingWhitespace(moveFxn, ctx) {
        if (!moveFxn(ctx)) {
            return false;
        }
        while (!ctx.token.className && ctx.token.string.trim().length === 0) {
            if (!moveFxn(ctx)) {
                return false;
            }
        }
        return true;
    }

    /**
     * In the given context, get the character offset of pos from the start of the token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context
     * @return {number}
     */
    function offsetInToken(ctx) {
        var offset = ctx.pos.ch - ctx.token.start;
        if (offset < 0) {
            console.log("CodeHintUtils: _offsetInToken - Invalid context: pos not in the current token!");
        }
        return offset;
    }

    /**
     * Returns the mode object and mode name string at a given position
     * @param {CodeMirror} cm CodeMirror instance
     * @param {line:{number}, ch:{number}} pos Position to query for mode
     * @return {mode:{Object}, name:string}
     */
    function getModeAt(cm, pos) {
        var outerMode = cm.getMode(),
            modeData = CodeMirror.innerMode(outerMode, cm.getTokenAt(pos).state),
            name;

        name = (modeData.mode.name === "xml") ?
                modeData.mode.configuration : modeData.mode.name;

        return {mode: modeData.mode, name: name};
    }

    exports.movePrevToken           = movePrevToken;
    exports.moveNextToken           = moveNextToken;
    exports.moveSkippingWhitespace  = moveSkippingWhitespace;
    exports.getInitialContext       = getInitialContext;
    exports.offsetInToken           = offsetInToken;
    exports.getModeAt               = getModeAt;
});
<commit_msg>Fixed a typo<commit_after>/*
 * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, CodeMirror */

/**
 * Functions for iterating through tokens in the current editor buffer. Useful for doing
 * light parsing that can rely purely on information gathered by the code coloring mechanism.
 */

define(function (require, exports, module) {
    "use strict";

   /**
     * Creates a context object for the given editor and position, suitable for passing to the
     * move functions.
     * @param {CodeMirror} editor
     * @param {{ch:{string}, line:{number}} pos
     * @return {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}}
     */
    function getInitialContext(editor, pos) {
        return {
            "editor": editor,
            "pos": pos,
            "token": editor.getTokenAt(pos)
        };
    }

    /**
     * Moves the given context backwards by one token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function movePrevToken(ctx) {
        if (ctx.pos.ch <= 0 || ctx.token.start <= 0) {
            //move up a line
            if (ctx.pos.line <= 0) {
                return false; //at the top already
            }
            ctx.pos.line--;
            ctx.pos.ch = ctx.editor.getLine(ctx.pos.line).length;
        } else {
            ctx.pos.ch = ctx.token.start;
        }
        ctx.token = ctx.editor.getTokenAt(ctx.pos);
        return true;
    }

    /**
     * Moves the given context forward by one token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function moveNextToken(ctx) {
        var eol = ctx.editor.getLine(ctx.pos.line).length;
        if (ctx.pos.ch >= eol || ctx.token.end >= eol) {
            //move down a line
            if (ctx.pos.line >= ctx.editor.lineCount() - 1) {
                return false; //at the bottom
            }
            ctx.pos.line++;
            ctx.pos.ch = 0;
        } else {
            ctx.pos.ch = ctx.token.end + 1;
        }
        ctx.token = ctx.editor.getTokenAt(ctx.pos);
        return true;
    }

   /**
     * Moves the given context in the given direction, skipping any whitespace it hits.
     * @param {function} moveFxn the function to move the context
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} ctx
     * @return {boolean} whether the context changed
     */
    function moveSkippingWhitespace(moveFxn, ctx) {
        if (!moveFxn(ctx)) {
            return false;
        }
        while (!ctx.token.className && ctx.token.string.trim().length === 0) {
            if (!moveFxn(ctx)) {
                return false;
            }
        }
        return true;
    }

    /**
     * In the given context, get the character offset of pos from the start of the token.
     * @param {editor:{CodeMirror}, pos:{ch:{string}, line:{number}}, token:{object}} context
     * @return {number}
     */
    function offsetInToken(ctx) {
        var offset = ctx.pos.ch - ctx.token.start;
        if (offset < 0) {
            console.log("CodeHintUtils: _offsetInToken - Invalid context: pos not in the current token!");
        }
        return offset;
    }

    /**
     * Returns the mode object and mode name string at a given position
     * @param {CodeMirror} cm CodeMirror instance
     * @param {line:{number}, ch:{number}} pos Position to query for mode
     * @return {mode:{Object}, name:string}
     */
    function getModeAt(cm, pos) {
        var outerMode = cm.getMode(),
            modeData = CodeMirror.innerMode(outerMode, cm.getTokenAt(pos).state),
            name;

        name = (modeData.mode.name === "xml") ?
                modeData.mode.configuration : modeData.mode.name;

        return {mode: modeData.mode, name: name};
    }

    exports.movePrevToken           = movePrevToken;
    exports.moveNextToken           = moveNextToken;
    exports.moveSkippingWhitespace  = moveSkippingWhitespace;
    exports.getInitialContext       = getInitialContext;
    exports.offsetInToken           = offsetInToken;
    exports.getModeAt               = getModeAt;
});
<|endoftext|>


<commit_before>/*
 * Deep merge objects
 */

/**
 * Simple is object check.
 * @param x the object to check
 * @return true if x is an object, otherwise false
 * @see  http://reactivex.io/rxjs/file/es6/util/isObject.js.html
 */
const isObject = x => x != null && typeof x === 'object';

/**
 * Deep merge objects
 * Both Object.assign and Object spread only do a shallow merge.
 * @param {Object} target
 * @param {...Object} sources the objects to merge into terget
 * @return {Object} the merged object
 * @see http://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge
 *
 * @example
 * // Given
 * const x = { a: { a: 1 } }
 * const y = { a: { b: 1 } }
 * const z = { ...x, ...y }
 * // Returns a shallow merge { a: { b: 1 } }
 * const m = deepMerge(x, y)
 * // Rerurns a deep merge { a: { a: 1, b: 1 } }
 */

const deepMerge = (target, ...sources) => {

  const result = Object.assign({}, target);

  if(sources.length > 0) {
    const source = sources.shift();

    // TODO: Rewite for-of loop
    //eslint-disable-next-line no-restricted-syntax
    for (const key of Object.keys(source)) {
      if (isObject(source[key])) {
        if (!(key in result)) {
          Object.assign(result, {[key]: source[key]});
        }
        else {
          result[key] = deepMerge(result[key], source[key]);
        }
      }
      else {
        Object.assign(result, {[key]: source[key]});
      }
    }
    return deepMerge(result, ...sources);
  }
  return result;
};

export default deepMerge;
<commit_msg>Replaced for (const key of Object.keys(source)) with Object.keys(source).forEach(key =><commit_after>/*
 * Deep merge objects
 */

/**
 * Simple is object check.
 * @param x the object to check
 * @return true if x is an object, otherwise false
 * @see  http://reactivex.io/rxjs/file/es6/util/isObject.js.html
 */
const isObject = x => x != null && typeof x === 'object';

/**
 * Deep merge objects
 * Both Object.assign and Object spread only do a shallow merge.
 * @param {Object} target
 * @param {...Object} sources the objects to merge into terget
 * @return {Object} the merged object
 * @see http://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge
 *
 * @example
 * // Given
 * const x = { a: { a: 1 } }
 * const y = { a: { b: 1 } }
 * const z = { ...x, ...y }
 * // Returns a shallow merge { a: { b: 1 } }
 * const m = deepMerge(x, y)
 * // Rerurns a deep merge { a: { a: 1, b: 1 } }
 */

const deepMerge = (target, ...sources) => {

  const result = Object.assign({}, target);

  for (let i = 0; i < sources.length; i++) {

    const source = sources[i];

    Object.keys(source).forEach(key => {

      if (isObject(source[key])) {

        if (!(key in result)) {
          Object.assign(result, { [key]: source[key] });
        }
        else {
          result[key] = deepMerge(result[key], source[key]);
        }
      }
      else {
        Object.assign(result, { [key]: source[key] });
      }
    });
  }
  return result;
};

export default deepMerge;
<|endoftext|>


<commit_before>import Rx from 'rx'
import THREE from 'three'
const GCodeInterpreter = require('gcode-interpreter').GCodeInterpreter
//import GCodeInterpreter from 'gcode-interpreter'
//const interpreter = GCodeInterpreter.GCodeInterpreter
import { GCodeToolpath } from 'gcode-toolpath'

/*var GCodeRunner = function () {
  var handlers = {
    'G0': (args) => {
      console.log('G0', args)
      return 'foo'
    },
    'G1': (args) => {
      console.log('G1', args)
      return 'bar'
    }
  }
  return new GCodeInterpreter({ handlers: handlers })
}*/

export default function parse(str){
  const obs = new Rx.ReplaySubject(1)

  const defaultColor = new THREE.Color(0xFF0000)
  const motionColor = {
    'G0': new THREE.Color(0xFF0000),//0x07a9ff
    'G1': new THREE.Color(0x17a9f5),//0x17a9f5
    'G2': new THREE.Color(0xF0FF00),
    'G3': new THREE.Color(0xF0FF0F)
  }

  let group = new THREE.Object3D()
  let geometry = new THREE.Geometry()

  function addLine(modalState, v1, v2) {
    const { motion } = modalState
    geometry.vertices.push(new THREE.Vector3(v1.x, v1.y, v1.z))
    geometry.vertices.push(new THREE.Vector3(v2.x, v2.y, v2.z))

    let color = motionColor[motion] || defaultColor
    geometry.colors.push(color)
    geometry.colors.push(color)

    console.log('modalState', modalState)
  }

  const toolpath = new GCodeToolpath({
    modalState: {},
    addLine: (modalState, v1, v2) => {
      addLine(modalState, v1, v2)
    },
    addArcCurve: (modalState, v1, v2, v0) => {
      //this.addArcCurve(modalState, v1, v2, v0);
    }
  })
  toolpath.loadFromString(str,function(err,data){

    let material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      linewidth: 3,
      vertexColors: THREE.VertexColors,
      opacity: 0.5,
      transparent: true
    })
    group.add(new THREE.Line(geometry, material))
    geometry = new THREE.Geometry()

  }).on('end', (results) => {
    //console.log('done', geometry)
    obs.onNext([group])
    obs.onNext({progress: 1, total: 1})
  })

  /*const runner = new GCodeRunner()
  runner.loadFromString(str, function(err, data) {
    if(!err) {
      obs.onNext(data)
    }
    else
    {
      obs.onError(err)
    }
  })
  .on('end', (results) => {
        // 'end' event listener
      //obs.onEnd()
    })*/

  return obs
}
<commit_msg>feat(faster Gcode display):Switched to buffergeometry for gcode parsing - updated rest of the code to match<commit_after>import Rx from 'rx'
import THREE from 'three'
const GCodeInterpreter = require('gcode-interpreter').GCodeInterpreter
//import GCodeInterpreter from 'gcode-interpreter'
//const interpreter = GCodeInterpreter.GCodeInterpreter
import { GCodeToolpath } from 'gcode-toolpath'

/*var GCodeRunner = function () {
  var handlers = {
    'G0': (args) => {
      console.log('G0', args)
      return 'foo'
    },
    'G1': (args) => {
      console.log('G1', args)
      return 'bar'
    }
  }
  return new GCodeInterpreter({ handlers: handlers })
}*/

export default function parse(str){
  const obs = new Rx.ReplaySubject(1)

  const defaultColor = new THREE.Color(0xFF0000)
  const motionColor = {
    'G0': [255,0,0,255],//new THREE.Color(0xFF0000),//0x07a9ff
    'G1': [7, 169, 255, 255],//new THREE.Color(0x17a9f5),//0x17a9f5
    'G2': [125, 255, 255, 255],//new THREE.Color(0xF0FF00),
    'G3': [125, 255, 125, 255]//new THREE.Color(0xF0FF0F)
  }

  let group = new THREE.Object3D()
  //let geometry = new THREE.Geometry()
  let geometry = new THREE.BufferGeometry()
  let posArray = []
  let colArray = []

  function addLine(modalState, v1, v2) {
    const { motion } = modalState

    posArray.push(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z)

    let color = (motionColor[motion] || defaultColor).map(e => (e/255))
    colArray.push(color[0], color[1], color[2], color[3], color[0], color[1], color[2], color[3])
    //colArray = colArray.concat(color, color)

    /*geometry.vertices.push(new THREE.Vector3(v1.x, v1.y, v1.z))
    geometry.vertices.push(new THREE.Vector3(v2.x, v2.y, v2.z))
    geometry.colors.push(new THREE.Color(color))
    geometry.colors.push(new THREE.Color(color))*/
  }

  const toolpath = new GCodeToolpath({
    modalState: {},
    addLine: (modalState, v1, v2) => {
      addLine(modalState, v1, v2)
    },
    addArcCurve: (modalState, v1, v2, v0) => {
      //this.addArcCurve(modalState, v1, v2, v0);
    }
  })
  toolpath.loadFromString(str,function(err,data){
    console.log('here',Date.now())
    let material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      linewidth: 5,
      vertexColors: THREE.VertexColors,
      opacity: 0.5,
      transparent: true
    })

    var positions = new Float32Array( posArray) //posArray.length  )
    var colors = new Float32Array( colArray )//posArray.length/3 * 4  )
    //positions.set( posArray )
    //colors.set ( colArray )
    geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3))
    geometry.addAttribute('color', new THREE.BufferAttribute(colors, 4))

    group.add(new THREE.Line(geometry, material))
    console.log('Done',Date.now())
    geometry = new THREE.BufferGeometry()

    /*group.add(new THREE.Line(geometry, material))
    geometry = new THREE.Geometry()*/
    console.log('done with group')

  })
  .on('data', (data) => {
    //console.log('data',data)
  })
  .on('end', (results) => {
    //console.log('done', geometry)
    obs.onNext([group])
    obs.onNext({progress: 1, total: 1})
  })

  /*const runner = new GCodeRunner()
  runner.loadFromString(str, function(err, data) {
    if(!err) {
      obs.onNext(data)
    }
    else
    {
      obs.onError(err)
    }
  })
  .on('end', (results) => {
        // 'end' event listener
      //obs.onEnd()
    })*/

  return obs
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var Joi = require('joi');
import CONST from '../constants';

var common = {
  team: Joi.number().integer().min(0),
  userUuid: Joi.string().regex(/^[A-Za-z0-9_-]+$/).min(1, 'utf8').max(128, 'utf8'),
  primaryKeyId: Joi.number().integer().min(0)
};

const schemas = {
  common: common,

  action: {
    user: common.userUuid.required(),
    type: Joi.string().uppercase().required(),
    imageData: Joi.string().when('type', { is: 'IMAGE', then: Joi.required() }),
    imageText: Joi.string().max(50, 'utf8').optional(),
    imageTextPosition: Joi.number().min(0).max(1).optional(),
    text: Joi.string().when('type', { is: 'TEXT', then: Joi.required() }),
    eventId: common.primaryKeyId.when('type', { is: 'CHECK_IN_EVENT', then: Joi.required()}),
    city: common.primaryKeyId,
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    }).when('type', {is: 'CHECK_IN_EVENT', then: Joi.required()}),
  },

  user: {
    uuid: common.userUuid.required(),
    name: Joi.string().min(1, 'utf8').max(50, 'utf8').required(),
    team: common.team.required()
  },

  userQueryParams: {
    userId: common.primaryKeyId.required(),
  },

  feedParams: {
    city: common.primaryKeyId,
    beforeId: Joi.number().integer().min(0).optional(),
    limit: Joi.number().integer().min(1).max(100).optional(),
    since: Joi.date().iso(),
    offset: Joi.number().integer().min(0),
    type: Joi.string()
      .valid(['TEXT', 'IMAGE'])
      .optional(),
    sort: Joi.string()
      .valid(CONST.FEED_SORT_TYPES_ARRAY)
      .default(CONST.FEED_SORT_TYPES.NEW)
      .optional(),
  },

  imageParams: {
    imageId: Joi.string().required()
  },

  vote: {
    value: Joi.number().integer().valid(-1, 1),
    feedItemId: Joi.number().integer().required(),
  },

  upsertMoodParams: {
    rating: Joi.number().precision(4).min(0).max(10).required(),
    description: Joi.string().min(1, 'utf8').max(128, 'utf8').optional().allow([null]).default(null),
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    }),
  },

  getMoodParams: {
    user: common.primaryKeyId,
    team: common.primaryKeyId,
    city: common.primaryKeyId,
  },

  radioParams: {
    city: common.primaryKeyId,
    id: common.primaryKeyId,
  },

  eventsParams: {
    city: common.primaryKeyId,
    id: common.primaryKeyId,
    showPast: Joi.boolean().default(false),
  },

  citiesParams: {
    city: common.primaryKeyId,
  },

  teamsParams: {
    city: common.primaryKeyId,
  },
};

const conversions = {};

function assert(obj, schemaName) {
  var joiObj = _getSchema(schemaName);

  // All this hassle to get joi to format nice error messages
  var content = {};
  content[schemaName] = obj;
  var expected = {};
  expected[schemaName] = joiObj;

  var result = Joi.validate(content, expected);

  if (result.error) {
    if (!result.error.isJoi) {
      throw result.error;
    }

    _throwJoiError(result.error);
  }

  // Return for convenience
  return result.value[schemaName];
}

// Converts string `value` to a correct js object.
// `schemaName` refers to key in `conversion` object. It defines all
// conversion functions.
function convert(obj, schemaName) {
  return _.reduce(obj, (memo, val, key) => {
    var func = _getConversion(schemaName)
    if (_.isFunction(func)) {
      memo[key] = func(val);
    } else {
      memo[key] = val;
    }
    return memo;

  }, {});
}

function _getConversion(name) {
  var conversion = _.get(conversions, name);
  if (!conversion) {
    throw new Error('Conversion with name ' + name + ' was not found');
  }
  return conversion;
}

function _getSchema(name) {
  var joiObj = _.get(schemas, name);
  if (!joiObj) {
    throw new Error('Schema with name ' + name + ' was not found');
  }
  return joiObj;
}

function _throwJoiError(err) {
  // See https://github.com/hapijs/joi/blob/v7.2.3/API.md#errors
  var msg = _.get(err, 'details.0.message') || 'Validation error';
  var newErr = new Error(msg);
  newErr.status = 400;
  throw newErr;
}

export {
  assert,
  convert,
  common,
  schemas
};
<commit_msg>Made text field mandatory when posting a COMMENT action<commit_after>var _ = require('lodash');
var Joi = require('joi');
import CONST from '../constants';

var common = {
  team: Joi.number().integer().min(0),
  userUuid: Joi.string().regex(/^[A-Za-z0-9_-]+$/).min(1, 'utf8').max(128, 'utf8'),
  primaryKeyId: Joi.number().integer().min(0)
};

const schemas = {
  common: common,

  action: {
    user: common.userUuid.required(),
    type: Joi.string().uppercase().required(),
    imageData: Joi.string().when('type', { is: 'IMAGE', then: Joi.required() }),
    imageText: Joi.string().max(50, 'utf8').optional(),
    imageTextPosition: Joi.number().min(0).max(1).optional(),
    text: Joi.string().when('type', { is: 'TEXT', then: Joi.required() }),
    eventId: common.primaryKeyId.when('type', { is: Joi.valid('CHECK_IN_EVENT', 'COMMENT'), then: Joi.required()}),
    city: common.primaryKeyId,
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    }).when('type', {is: 'CHECK_IN_EVENT', then: Joi.required()}),
  },

  user: {
    uuid: common.userUuid.required(),
    name: Joi.string().min(1, 'utf8').max(50, 'utf8').required(),
    team: common.team.required()
  },

  userQueryParams: {
    userId: common.primaryKeyId.required(),
  },

  feedParams: {
    city: common.primaryKeyId,
    beforeId: Joi.number().integer().min(0).optional(),
    limit: Joi.number().integer().min(1).max(100).optional(),
    since: Joi.date().iso(),
    offset: Joi.number().integer().min(0),
    type: Joi.string()
      .valid(['TEXT', 'IMAGE'])
      .optional(),
    sort: Joi.string()
      .valid(CONST.FEED_SORT_TYPES_ARRAY)
      .default(CONST.FEED_SORT_TYPES.NEW)
      .optional(),
  },

  imageParams: {
    imageId: Joi.string().required()
  },

  vote: {
    value: Joi.number().integer().valid(-1, 1),
    feedItemId: Joi.number().integer().required(),
  },

  upsertMoodParams: {
    rating: Joi.number().precision(4).min(0).max(10).required(),
    description: Joi.string().min(1, 'utf8').max(128, 'utf8').optional().allow([null]).default(null),
    location: Joi.object({
      latitude: Joi.number(),
      longitude: Joi.number()
    }),
  },

  getMoodParams: {
    user: common.primaryKeyId,
    team: common.primaryKeyId,
    city: common.primaryKeyId,
  },

  radioParams: {
    city: common.primaryKeyId,
    id: common.primaryKeyId,
  },

  eventsParams: {
    city: common.primaryKeyId,
    id: common.primaryKeyId,
    showPast: Joi.boolean().default(false),
  },

  citiesParams: {
    city: common.primaryKeyId,
  },

  teamsParams: {
    city: common.primaryKeyId,
  },
};

const conversions = {};

function assert(obj, schemaName) {
  var joiObj = _getSchema(schemaName);

  // All this hassle to get joi to format nice error messages
  var content = {};
  content[schemaName] = obj;
  var expected = {};
  expected[schemaName] = joiObj;

  var result = Joi.validate(content, expected);

  if (result.error) {
    if (!result.error.isJoi) {
      throw result.error;
    }

    _throwJoiError(result.error);
  }

  // Return for convenience
  return result.value[schemaName];
}

// Converts string `value` to a correct js object.
// `schemaName` refers to key in `conversion` object. It defines all
// conversion functions.
function convert(obj, schemaName) {
  return _.reduce(obj, (memo, val, key) => {
    var func = _getConversion(schemaName)
    if (_.isFunction(func)) {
      memo[key] = func(val);
    } else {
      memo[key] = val;
    }
    return memo;

  }, {});
}

function _getConversion(name) {
  var conversion = _.get(conversions, name);
  if (!conversion) {
    throw new Error('Conversion with name ' + name + ' was not found');
  }
  return conversion;
}

function _getSchema(name) {
  var joiObj = _.get(schemas, name);
  if (!joiObj) {
    throw new Error('Schema with name ' + name + ' was not found');
  }
  return joiObj;
}

function _throwJoiError(err) {
  // See https://github.com/hapijs/joi/blob/v7.2.3/API.md#errors
  var msg = _.get(err, 'details.0.message') || 'Validation error';
  var newErr = new Error(msg);
  newErr.status = 400;
  throw newErr;
}

export {
  assert,
  convert,
  common,
  schemas
};
<|endoftext|>