<commit_before>'use strict';

var EXTEND = require('whet.extend');

var JSAPI = module.exports = function(data, parentNode) {
    EXTEND(this, data);
    if (parentNode) this.parentNode = parentNode;
};

/**
 * Perform a deep clone of this node.
 *
 * @return {Object} element
 */
JSAPI.prototype.clone = function() {
    var node = this;
    var nodeData = {};

    Object.keys(node).forEach(function(key) {
        if (key != 'content' && key != 'parentNode') {
            nodeData[key] = node[key];
        }
    });

    // Deep-clone node data
    // This is still faster than using EXTEND(true…)
    nodeData = JSON.parse(JSON.stringify(nodeData));

    var clonedNode = new JSAPI(nodeData);

    if (node.content) {
        clonedNode.content = node.content.map(function(childNode) {
            var clonedChild = childNode.clone();
            clonedChild.parentNode = clonedNode;
            return clonedChild;
        });
    }

    return clonedNode;
};

/**
 * Determine if item is an element
 * (any, with a specific name or in a names array).
 *
 * @param {String|Array} [param] element name or names arrays
 * @return {Boolean}
 */
JSAPI.prototype.isElem = function(param) {

    if (!param) return !!this.elem;

    if (Array.isArray(param)) return !!this.elem && (param.indexOf(this.elem) > -1);

    return !!this.elem && this.elem === param;

};

/**
 * Renames an element
 *
 * @param {String} name new element name
 * @return {Object} element
 */
JSAPI.prototype.renameElem = function(name) {

    if (typeof name == 'string' && name != '')
        this.elem = this.local = name;

    return this;

};

/**
 * Determine if element is empty.
 *
 * @return {Boolean}
 */
 JSAPI.prototype.isEmpty = function() {

    return !this.content || !this.content.length;

};

/**
 * Changes content by removing elements and/or adding new elements.
 *
 * @param {Number} start Index at which to start changing the content.
 * @param {Number} n Number of elements to remove.
 * @param {Array|Object} [insertion] Elements to add to the content.
 * @return {Array} Removed elements.
 */
 JSAPI.prototype.spliceContent = function(start, n, insertion) {

    if (arguments.length < 2) return [];

    if (!Array.isArray(insertion))
        insertion = Array.apply(null, arguments).slice(2);

    insertion.forEach(function(inner) { inner.parentNode = this }, this);

    return this.content.splice.apply(this.content, [start, n].concat(insertion));

};

/**
 * Determine if element has an attribute
 * (any, or by name or by name + value).
 *
 * @param {String} [name] attribute name
 * @param {String} [val] attribute value (will be toString()'ed)
 * @return {Boolean}
 */
 JSAPI.prototype.hasAttr = function(name, val) {

    if (!this.attrs || !Object.keys(this.attrs).length) return false;

    if (!arguments.length) return !!this.attrs;

    if (val !== undefined) return !!this.attrs[name] && this.attrs[name].value === val.toString();

    return !!this.attrs[name];

};

/**
 * Get a specific attribute from an element
 * (by name or name + value).
 *
 * @param {String} name attribute name
 * @param {String} [val] attribute value (will be toString()'ed)
 * @return {Object|Undefined}
 */
 JSAPI.prototype.attr = function(name, val) {

    if (!this.hasAttr() || !arguments.length) return undefined;

    if (val !== undefined) return this.hasAttr(name, val) ? this.attrs[name] : undefined;

    return this.attrs[name];

};

/**
 * Get computed attribute value from an element
 *
 * @param {String} name attribute name
 * @return {Object|Undefined}
 */
 JSAPI.prototype.computedAttr = function(name, val) {
    if (!arguments.length) return;

    for (var elem = this; elem && (!elem.hasAttr(name) || !elem.attr(name).value); elem = elem.parentNode);

    if (val != null) {
        return elem ? elem.hasAttr(name, val) : false;
    } else if (elem && elem.hasAttr(name)) {
        return elem.attrs[name].value;
    }

};

/**
 * Remove a specific attribute.
 *
 * @param {String|Array} name attribute name
 * @param {String} [val] attribute value
 * @return {Boolean}
 */
 JSAPI.prototype.removeAttr = function(name, val, recursive) {

    if (!arguments.length) return false;

    if (Array.isArray(name)) name.forEach(this.removeAttr, this);

    if (!this.hasAttr(name)) return false;

    if (!recursive && val && this.attrs[name].value !== val) return false;

    delete this.attrs[name];

    if (!Object.keys(this.attrs).length) delete this.attrs;

    return true;

};

/**
 * Add attribute.
 *
 * @param {Object} attr attribute object
 * @return {Object} created attribute
 */
 JSAPI.prototype.addAttr = function(attr) {

    if (!attr ||
        (attr && attr.name === undefined) ||
        (attr && attr.value === undefined) ||
        (attr && attr.prefix === undefined) ||
        (attr && attr.local === undefined)
    ) return false;

    this.attrs = this.attrs || {};
    this.attrs[attr.name] = attr;

    return this.attrs[attr.name];

};

/**
 * Iterates over all attributes.
 *
 * @param {Function} callback callback
 * @param {Object} [context] callback context
 * @return {Boolean} false if there are no any attributes
 */
 JSAPI.prototype.eachAttr = function(callback, context) {

    if (!this.hasAttr()) return false;

    for (var name in this.attrs) {
        callback.call(context, this.attrs[name]);
    }

    return true;

};

/**
 * Tests whether some attribute passes the test.
 *
 * @param {Function} callback callback
 * @param {Object} [context] callback context
 * @return {Boolean} false if there are no any attributes
 */
 JSAPI.prototype.someAttr = function(callback, context) {

    if (!this.hasAttr()) return false;

    for (var name in this.attrs) {
        if (callback.call(context, this.attrs[name])) return true;
    }

    return false;

};
<commit_msg>Adding innumerable parentNode back<commit_after>'use strict';

var EXTEND = require('whet.extend');

var JSAPI = module.exports = function(data, parentNode) {
    EXTEND(this, data);
    if (parentNode) {
        Object.defineProperty(this, 'parentNode', {
            writable: true,
            value: parentNode
        })
    }
};

/**
 * Perform a deep clone of this node.
 *
 * @return {Object} element
 */
JSAPI.prototype.clone = function() {
    var node = this;
    var nodeData = {};

    Object.keys(node).forEach(function(key) {
        if (key != 'content') {
            nodeData[key] = node[key];
        }
    });

    // Deep-clone node data
    // This is still faster than using EXTEND(true…)
    nodeData = JSON.parse(JSON.stringify(nodeData));

    // parentNode gets set to a proper object by the parent clone,
    // but it needs to be true/false now to do the right thing
    // in the constructor.
    var clonedNode = new JSAPI(nodeData, !!node.parentNode);

    if (node.content) {
        clonedNode.content = node.content.map(function(childNode) {
            var clonedChild = childNode.clone();
            clonedChild.parentNode = clonedNode;
            return clonedChild;
        });
    }

    return clonedNode;
};

/**
 * Determine if item is an element
 * (any, with a specific name or in a names array).
 *
 * @param {String|Array} [param] element name or names arrays
 * @return {Boolean}
 */
JSAPI.prototype.isElem = function(param) {

    if (!param) return !!this.elem;

    if (Array.isArray(param)) return !!this.elem && (param.indexOf(this.elem) > -1);

    return !!this.elem && this.elem === param;

};

/**
 * Renames an element
 *
 * @param {String} name new element name
 * @return {Object} element
 */
JSAPI.prototype.renameElem = function(name) {

    if (typeof name == 'string' && name != '')
        this.elem = this.local = name;

    return this;

};

/**
 * Determine if element is empty.
 *
 * @return {Boolean}
 */
 JSAPI.prototype.isEmpty = function() {

    return !this.content || !this.content.length;

};

/**
 * Changes content by removing elements and/or adding new elements.
 *
 * @param {Number} start Index at which to start changing the content.
 * @param {Number} n Number of elements to remove.
 * @param {Array|Object} [insertion] Elements to add to the content.
 * @return {Array} Removed elements.
 */
 JSAPI.prototype.spliceContent = function(start, n, insertion) {

    if (arguments.length < 2) return [];

    if (!Array.isArray(insertion))
        insertion = Array.apply(null, arguments).slice(2);

    insertion.forEach(function(inner) { inner.parentNode = this }, this);

    return this.content.splice.apply(this.content, [start, n].concat(insertion));

};

/**
 * Determine if element has an attribute
 * (any, or by name or by name + value).
 *
 * @param {String} [name] attribute name
 * @param {String} [val] attribute value (will be toString()'ed)
 * @return {Boolean}
 */
 JSAPI.prototype.hasAttr = function(name, val) {

    if (!this.attrs || !Object.keys(this.attrs).length) return false;

    if (!arguments.length) return !!this.attrs;

    if (val !== undefined) return !!this.attrs[name] && this.attrs[name].value === val.toString();

    return !!this.attrs[name];

};

/**
 * Get a specific attribute from an element
 * (by name or name + value).
 *
 * @param {String} name attribute name
 * @param {String} [val] attribute value (will be toString()'ed)
 * @return {Object|Undefined}
 */
 JSAPI.prototype.attr = function(name, val) {

    if (!this.hasAttr() || !arguments.length) return undefined;

    if (val !== undefined) return this.hasAttr(name, val) ? this.attrs[name] : undefined;

    return this.attrs[name];

};

/**
 * Get computed attribute value from an element
 *
 * @param {String} name attribute name
 * @return {Object|Undefined}
 */
 JSAPI.prototype.computedAttr = function(name, val) {
    if (!arguments.length) return;

    for (var elem = this; elem && (!elem.hasAttr(name) || !elem.attr(name).value); elem = elem.parentNode);

    if (val != null) {
        return elem ? elem.hasAttr(name, val) : false;
    } else if (elem && elem.hasAttr(name)) {
        return elem.attrs[name].value;
    }

};

/**
 * Remove a specific attribute.
 *
 * @param {String|Array} name attribute name
 * @param {String} [val] attribute value
 * @return {Boolean}
 */
 JSAPI.prototype.removeAttr = function(name, val, recursive) {

    if (!arguments.length) return false;

    if (Array.isArray(name)) name.forEach(this.removeAttr, this);

    if (!this.hasAttr(name)) return false;

    if (!recursive && val && this.attrs[name].value !== val) return false;

    delete this.attrs[name];

    if (!Object.keys(this.attrs).length) delete this.attrs;

    return true;

};

/**
 * Add attribute.
 *
 * @param {Object} attr attribute object
 * @return {Object} created attribute
 */
 JSAPI.prototype.addAttr = function(attr) {

    if (!attr ||
        (attr && attr.name === undefined) ||
        (attr && attr.value === undefined) ||
        (attr && attr.prefix === undefined) ||
        (attr && attr.local === undefined)
    ) return false;

    this.attrs = this.attrs || {};
    this.attrs[attr.name] = attr;

    return this.attrs[attr.name];

};

/**
 * Iterates over all attributes.
 *
 * @param {Function} callback callback
 * @param {Object} [context] callback context
 * @return {Boolean} false if there are no any attributes
 */
 JSAPI.prototype.eachAttr = function(callback, context) {

    if (!this.hasAttr()) return false;

    for (var name in this.attrs) {
        callback.call(context, this.attrs[name]);
    }

    return true;

};

/**
 * Tests whether some attribute passes the test.
 *
 * @param {Function} callback callback
 * @param {Object} [context] callback context
 * @return {Boolean} false if there are no any attributes
 */
 JSAPI.prototype.someAttr = function(callback, context) {

    if (!this.hasAttr()) return false;

    for (var name in this.attrs) {
        if (callback.call(context, this.attrs[name])) return true;
    }

    return false;

};
<|endoftext|>


<commit_before>var assert = require("assert");
var types = require("./types");
var NodePath = require("./node-path");
var Node = types.namedTypes.Node;
var isArray = types.builtInTypes.array;
var isObject = types.builtInTypes.object;
var isFunction = types.builtInTypes.function;
var hasOwn = Object.prototype.hasOwnProperty;
var undefined;

function PathVisitor() {
    assert.ok(this instanceof PathVisitor);

    // Permanent state.
    this._reusableContextStack = [];
    this._methodNameTable = computeMethodNameTable(this);
    this.Context = makeContextConstructor(this);

    // State reset every time PathVisitor.prototype.visit is called.
    this._visiting = false;
    this._changeReported = false;
}

function computeMethodNameTable(visitor) {
    var typeNames = Object.create(null);

    for (var methodName in visitor) {
        if (/^visit[A-Z]/.test(methodName)) {
            typeNames[methodName.slice("visit".length)] = true;
        }
    }

    var supertypeTable = types.computeSupertypeLookupTable(typeNames);
    var methodNameTable = Object.create(null);

    var typeNames = Object.keys(supertypeTable);
    var typeNameCount = typeNames.length;
    for (var i = 0; i < typeNameCount; ++i) {
        var typeName = typeNames[i];
        methodName = "visit" + supertypeTable[typeName];
        if (isFunction.check(visitor[methodName])) {
            methodNameTable[typeName] = methodName;
        }
    }

    return methodNameTable;
}

PathVisitor.fromMethodsObject = function fromMethodsObject(methods) {
    if (methods instanceof PathVisitor) {
        return methods;
    }

    if (!isObject.check(methods)) {
        // An empty visitor?
        return new PathVisitor;
    }

    function Visitor() {
        assert.ok(this instanceof Visitor);
        PathVisitor.call(this);
    }

    var Vp = Visitor.prototype = Object.create(PVp);
    Vp.constructor = Visitor;

    extend(Vp, methods);
    extend(Visitor, PathVisitor);

    isFunction.assert(Visitor.fromMethodsObject);
    isFunction.assert(Visitor.visit);

    return new Visitor;
};

function extend(target, source) {
    for (var property in source) {
        if (hasOwn.call(source, property)) {
            target[property] = source[property];
        }
    }

    return target;
}

PathVisitor.visit = function visit(node, methods) {
    var visitor = PathVisitor.fromMethodsObject(methods);

    if (node instanceof NodePath) {
        visitor.visit(node);
        return node.value;
    }

    var rootPath = new NodePath({ root: node });
    visitor.visit(rootPath.get("root"));
    return rootPath.value.root;
};

var PVp = PathVisitor.prototype;

var recursiveVisitWarning = [
    "Recursively calling visitor.visit(path) resets visitor state.",
    "Try this.visit(path) or this.traverse(path) instead."
].join(" ");

PVp.visit = function(path) {
    assert.ok(!this._visiting, recursiveVisitWarning);

    // Private state that needs to be reset before every traversal.
    this._visiting = true;
    this._changeReported = false;

    // Called with the same arguments as .visit.
    this.reset.apply(this, arguments);

    try {
        return this.visitWithoutReset(path);
    } finally {
        this._visiting = false;
    }
};

PVp.reset = function(path/*, additional arguments */) {
    // Empty stub; may be reassigned or overridden by subclasses.
};

PVp.visitWithoutReset = function(path) {
    if (this instanceof this.Context) {
        // Since this.Context.prototype === this, there's a chance we
        // might accidentally call context.visitWithoutReset. If that
        // happens, re-invoke the method against context.visitor.
        return this.visitor.visitWithoutReset(path);
    }

    assert.ok(path instanceof NodePath);
    var value = path.value;

    var methodName = Node.check(value) && this._methodNameTable[value.type];
    if (methodName) {
        var context = this.acquireContext(path);
        try {
            return context.invokeVisitorMethod(methodName);
        } finally {
            this.releaseContext(context);
        }

    } else {
        // If there was no visitor method to call, visit the children of
        // this node generically.
        return visitChildren(path, this);
    }
};

function visitChildren(path, visitor) {
    assert.ok(path instanceof NodePath);
    assert.ok(visitor instanceof PathVisitor);

    var value = path.value;

    if (isArray.check(value)) {
        path.each(visitor.visitWithoutReset, visitor);
    } else if (!isObject.check(value)) {
        // No children to visit.
    } else {
        var childNames = types.getFieldNames(value);
        var childCount = childNames.length;
        var childPaths = [];

        for (var i = 0; i < childCount; ++i) {
            var childName = childNames[i];
            if (!hasOwn.call(value, childName)) {
                value[childName] = types.getFieldValue(value, childName);
            }
            childPaths.push(path.get(childName));
        }

        for (var i = 0; i < childCount; ++i) {
            visitor.visitWithoutReset(childPaths[i]);
        }
    }

    return path.value;
}

PVp.acquireContext = function(path) {
    if (this._reusableContextStack.length === 0) {
        return new this.Context(path);
    }
    return this._reusableContextStack.pop().reset(path);
};

PVp.releaseContext = function(context) {
    assert.ok(context instanceof this.Context);
    this._reusableContextStack.push(context);
    context.currentPath = null;
};

PVp.reportChanged = function() {
    this._changeReported = true;
};

PVp.wasChangeReported = function() {
    return this._changeReported;
};

function makeContextConstructor(visitor) {
    function Context(path) {
        assert.ok(this instanceof Context);
        assert.ok(this instanceof PathVisitor);
        assert.ok(path instanceof NodePath);

        Object.defineProperty(this, "visitor", {
            value: visitor,
            writable: false,
            enumerable: true,
            configurable: false
        });

        this.currentPath = path;
        this.needToCallTraverse = true;

        Object.seal(this);
    }

    assert.ok(visitor instanceof PathVisitor);

    // Note that the visitor object is the prototype of Context.prototype,
    // so all visitor methods are inherited by context objects.
    var Cp = Context.prototype = Object.create(visitor);

    Cp.constructor = Context;
    extend(Cp, sharedContextProtoMethods);

    return Context;
}

// Every PathVisitor has a different this.Context constructor and
// this.Context.prototype object, but those prototypes can all use the
// same reset, invokeVisitorMethod, and traverse function objects.
var sharedContextProtoMethods = Object.create(null);

sharedContextProtoMethods.reset =
function reset(path) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);

    this.currentPath = path;
    this.needToCallTraverse = true;

    return this;
};

sharedContextProtoMethods.invokeVisitorMethod =
function invokeVisitorMethod(methodName) {
    assert.ok(this instanceof this.Context);
    assert.ok(this.currentPath instanceof NodePath);

    var result = this.visitor[methodName].call(this, this.currentPath);

    if (result === false) {
        // Visitor methods return false to indicate that they have handled
        // their own traversal needs, and we should not complain if
        // this.needToCallTraverse is still true.
        this.needToCallTraverse = false;

    } else if (result !== undefined) {
        // Any other non-undefined value returned from the visitor method
        // is interpreted as a replacement value.
        this.currentPath = this.currentPath.replace(result)[0];

        if (this.needToCallTraverse) {
            // If this.traverse still hasn't been called, visit the
            // children of the replacement node.
            this.traverse(this.currentPath);
        }
    }

    assert.strictEqual(
        this.needToCallTraverse, false,
        "Must either call this.traverse or return false in " + methodName
    );

    var path = this.currentPath;
    return path && path.value;
};

sharedContextProtoMethods.traverse =
function traverse(path, newVisitor) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);
    assert.ok(this.currentPath instanceof NodePath);

    this.needToCallTraverse = false;

    return visitChildren(path, PathVisitor.fromMethodsObject(
        newVisitor || this.visitor
    ));
};

sharedContextProtoMethods.visit =
function visit(path, newVisitor) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);
    assert.ok(this.currentPath instanceof NodePath);

    this.needToCallTraverse = false;

    return PathVisitor.fromMethodsObject(
        newVisitor || this.visitor
    ).visitWithoutReset(path);
};

sharedContextProtoMethods.reportChanged = function reportChanged() {
    this.visitor.reportChanged();
};

module.exports = PathVisitor;
<commit_msg>Coerce first PathVisitor.prototype.visit argument to NodePath.<commit_after>var assert = require("assert");
var types = require("./types");
var NodePath = require("./node-path");
var Node = types.namedTypes.Node;
var isArray = types.builtInTypes.array;
var isObject = types.builtInTypes.object;
var isFunction = types.builtInTypes.function;
var hasOwn = Object.prototype.hasOwnProperty;
var undefined;

function PathVisitor() {
    assert.ok(this instanceof PathVisitor);

    // Permanent state.
    this._reusableContextStack = [];
    this._methodNameTable = computeMethodNameTable(this);
    this.Context = makeContextConstructor(this);

    // State reset every time PathVisitor.prototype.visit is called.
    this._visiting = false;
    this._changeReported = false;
}

function computeMethodNameTable(visitor) {
    var typeNames = Object.create(null);

    for (var methodName in visitor) {
        if (/^visit[A-Z]/.test(methodName)) {
            typeNames[methodName.slice("visit".length)] = true;
        }
    }

    var supertypeTable = types.computeSupertypeLookupTable(typeNames);
    var methodNameTable = Object.create(null);

    var typeNames = Object.keys(supertypeTable);
    var typeNameCount = typeNames.length;
    for (var i = 0; i < typeNameCount; ++i) {
        var typeName = typeNames[i];
        methodName = "visit" + supertypeTable[typeName];
        if (isFunction.check(visitor[methodName])) {
            methodNameTable[typeName] = methodName;
        }
    }

    return methodNameTable;
}

PathVisitor.fromMethodsObject = function fromMethodsObject(methods) {
    if (methods instanceof PathVisitor) {
        return methods;
    }

    if (!isObject.check(methods)) {
        // An empty visitor?
        return new PathVisitor;
    }

    function Visitor() {
        assert.ok(this instanceof Visitor);
        PathVisitor.call(this);
    }

    var Vp = Visitor.prototype = Object.create(PVp);
    Vp.constructor = Visitor;

    extend(Vp, methods);
    extend(Visitor, PathVisitor);

    isFunction.assert(Visitor.fromMethodsObject);
    isFunction.assert(Visitor.visit);

    return new Visitor;
};

function extend(target, source) {
    for (var property in source) {
        if (hasOwn.call(source, property)) {
            target[property] = source[property];
        }
    }

    return target;
}

PathVisitor.visit = function visit(node, methods) {
    return PathVisitor.fromMethodsObject(methods).visit(node);
};

var PVp = PathVisitor.prototype;

var recursiveVisitWarning = [
    "Recursively calling visitor.visit(path) resets visitor state.",
    "Try this.visit(path) or this.traverse(path) instead."
].join(" ");

PVp.visit = function() {
    assert.ok(!this._visiting, recursiveVisitWarning);

    // Private state that needs to be reset before every traversal.
    this._visiting = true;
    this._changeReported = false;

    var argc = arguments.length;
    var args = new Array(argc)
    for (var i = 0; i < argc; ++i) {
        args[i] = arguments[i];
    }

    if (!(args[0] instanceof NodePath)) {
        args[0] = new NodePath({ root: args[0] }).get("root");
    }

    // Called with the same arguments as .visit.
    this.reset.apply(this, args);

    try {
        return this.visitWithoutReset(args[0]);
    } finally {
        this._visiting = false;
    }
};

PVp.reset = function(path/*, additional arguments */) {
    // Empty stub; may be reassigned or overridden by subclasses.
};

PVp.visitWithoutReset = function(path) {
    if (this instanceof this.Context) {
        // Since this.Context.prototype === this, there's a chance we
        // might accidentally call context.visitWithoutReset. If that
        // happens, re-invoke the method against context.visitor.
        return this.visitor.visitWithoutReset(path);
    }

    assert.ok(path instanceof NodePath);
    var value = path.value;

    var methodName = Node.check(value) && this._methodNameTable[value.type];
    if (methodName) {
        var context = this.acquireContext(path);
        try {
            return context.invokeVisitorMethod(methodName);
        } finally {
            this.releaseContext(context);
        }

    } else {
        // If there was no visitor method to call, visit the children of
        // this node generically.
        return visitChildren(path, this);
    }
};

function visitChildren(path, visitor) {
    assert.ok(path instanceof NodePath);
    assert.ok(visitor instanceof PathVisitor);

    var value = path.value;

    if (isArray.check(value)) {
        path.each(visitor.visitWithoutReset, visitor);
    } else if (!isObject.check(value)) {
        // No children to visit.
    } else {
        var childNames = types.getFieldNames(value);
        var childCount = childNames.length;
        var childPaths = [];

        for (var i = 0; i < childCount; ++i) {
            var childName = childNames[i];
            if (!hasOwn.call(value, childName)) {
                value[childName] = types.getFieldValue(value, childName);
            }
            childPaths.push(path.get(childName));
        }

        for (var i = 0; i < childCount; ++i) {
            visitor.visitWithoutReset(childPaths[i]);
        }
    }

    return path.value;
}

PVp.acquireContext = function(path) {
    if (this._reusableContextStack.length === 0) {
        return new this.Context(path);
    }
    return this._reusableContextStack.pop().reset(path);
};

PVp.releaseContext = function(context) {
    assert.ok(context instanceof this.Context);
    this._reusableContextStack.push(context);
    context.currentPath = null;
};

PVp.reportChanged = function() {
    this._changeReported = true;
};

PVp.wasChangeReported = function() {
    return this._changeReported;
};

function makeContextConstructor(visitor) {
    function Context(path) {
        assert.ok(this instanceof Context);
        assert.ok(this instanceof PathVisitor);
        assert.ok(path instanceof NodePath);

        Object.defineProperty(this, "visitor", {
            value: visitor,
            writable: false,
            enumerable: true,
            configurable: false
        });

        this.currentPath = path;
        this.needToCallTraverse = true;

        Object.seal(this);
    }

    assert.ok(visitor instanceof PathVisitor);

    // Note that the visitor object is the prototype of Context.prototype,
    // so all visitor methods are inherited by context objects.
    var Cp = Context.prototype = Object.create(visitor);

    Cp.constructor = Context;
    extend(Cp, sharedContextProtoMethods);

    return Context;
}

// Every PathVisitor has a different this.Context constructor and
// this.Context.prototype object, but those prototypes can all use the
// same reset, invokeVisitorMethod, and traverse function objects.
var sharedContextProtoMethods = Object.create(null);

sharedContextProtoMethods.reset =
function reset(path) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);

    this.currentPath = path;
    this.needToCallTraverse = true;

    return this;
};

sharedContextProtoMethods.invokeVisitorMethod =
function invokeVisitorMethod(methodName) {
    assert.ok(this instanceof this.Context);
    assert.ok(this.currentPath instanceof NodePath);

    var result = this.visitor[methodName].call(this, this.currentPath);

    if (result === false) {
        // Visitor methods return false to indicate that they have handled
        // their own traversal needs, and we should not complain if
        // this.needToCallTraverse is still true.
        this.needToCallTraverse = false;

    } else if (result !== undefined) {
        // Any other non-undefined value returned from the visitor method
        // is interpreted as a replacement value.
        this.currentPath = this.currentPath.replace(result)[0];

        if (this.needToCallTraverse) {
            // If this.traverse still hasn't been called, visit the
            // children of the replacement node.
            this.traverse(this.currentPath);
        }
    }

    assert.strictEqual(
        this.needToCallTraverse, false,
        "Must either call this.traverse or return false in " + methodName
    );

    var path = this.currentPath;
    return path && path.value;
};

sharedContextProtoMethods.traverse =
function traverse(path, newVisitor) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);
    assert.ok(this.currentPath instanceof NodePath);

    this.needToCallTraverse = false;

    return visitChildren(path, PathVisitor.fromMethodsObject(
        newVisitor || this.visitor
    ));
};

sharedContextProtoMethods.visit =
function visit(path, newVisitor) {
    assert.ok(this instanceof this.Context);
    assert.ok(path instanceof NodePath);
    assert.ok(this.currentPath instanceof NodePath);

    this.needToCallTraverse = false;

    return PathVisitor.fromMethodsObject(
        newVisitor || this.visitor
    ).visitWithoutReset(path);
};

sharedContextProtoMethods.reportChanged = function reportChanged() {
    this.visitor.reportChanged();
};

module.exports = PathVisitor;
<|endoftext|>


<commit_before>// Prepares request environment (`this` context of server methods/filters).

'use strict';

var _       = require('lodash');
var Puncher = require('puncher');
var date    = require('./date');

////////////////////////////////////////////////////////////////////////////////

var DEFAULT_HTTP_PORT  = 80;
var DEFAULT_HTTPS_PORT = 443;

var tzOffset = (new Date).getTimezoneOffset();

//  deepClone(obj) -> Object
//  - obj (Mixed): Original object to get cloned
//
//  Returns a deep copy of given object. All nested objects are deeply copied
//  instead of passing by reference.
//
//  **WARNING** This is a potentional bottleneck and performance-killer,
//              although it's used for a trivial case. Probably it would be
//              better to change it to `JSON.parse(JSON.stringify(obj))`
//
/*
function deepClone(obj) {
  // TODO: Add preventor of circular dependencies

  if (!_.isObject(obj) || _.isFunction(obj)) {
    return obj;
  }

  if (_.isDate(obj)) {
    return new Date(obj.getTime());
  }

  if (_.isRegExp(obj)) {
    return new RegExp(obj.source, obj.toString().replace(/.*\//, ""));
  }

  if (_.isArray(obj) || _.isArguments(obj)) {
    return Array.prototype.map.call(obj, function (val) {
      return deepClone(val);
    });
  }

  return _.reduce(obj, function (memo, val, key) {
    memo[key] = deepClone(val);
    return memo;
  }, {});
}
*/

// Finds the most appropriate server binding in config, by ApiPath.
//
// Probably, can be cached (if use _.memoize, swap params first)
function findServerSocketConfig(N, apiPath) {
  var splitted = apiPath.split('.'), bind;

  // Reduce apiPath looking for matching binds.
  while (!_.isEmpty(splitted)) {
    bind = N.config.bind[splitted.join('.')];

    if (bind) {
      return bind; // Found.
    }

    splitted.pop();
  }

  return N.config.bind['default'] || null;
}

////////////////////////////////////////////////////////////////////////////////

/**
 *  lib.env(options) -> Object
 *  - options (Object): Environment options.
 *
 *  Create new request environment object.
 *
 *
 *  ##### Options
 *
 *  - **http**: HTTP origin object that contains `req` and `res`.
 *  - **rpc**: API3 (Ajax) origin that contains `req` and `res`.
 *  - **skip**: Array of middlewares to skip
 *  - **session**: Session object
 *    - **locale**: Locale name as String
 *  - **method**: Name of the server method, e.g. `'forums.posts.show'`
 *  - **layout**: Layout name as String
 **/
module.exports = function env(N, options) {
  var req = options.req
    , res = options.res;

  var ctx = {

    params: options.params || {},
    method: null,

    // Contains server chain response on success
    data: {},

    // internal, to pass error from server chain to responders
    err: null,
    // internal, rendered data
    body: null,
    // internal, http status code (set in responders)
    status: N.io.OK,
    // filled by formidable with `fields & `files` structures, for http POST requests
    post: null,

    headers: {},

    runtime: {
      page_data: {}
    },

    extras:  {
      puncher: new Puncher(),
      settings: {
        params: {},
        fetch: function fetchSettings(keys, callback) {
          N.settings.get(keys, this.params, {}, callback);
        }
      }
    },

    helpers: {},

    origin: {
      req: req,
      res: res
    },

    session: options.session || null,

    request: {
      type:        options.type,
      isEncrypted: options.isEncrypted,
      ip:          options.remoteAddress,
      matched:     options.matched || null
    },

    response: {
      data: {
        head: {
          title: null, // should be filled with default value

          // List of assets for yepnope,
          // Each element is an object with properties:
          //
          //    type:   css|js
          //    link:   asset_url
          //
          // example: assets.push({type: 'js', link: '//example.com/foo.js'});
          assets: []
        },
        /*menus: {},
        blocks: {}*/
      }
    },
    log_request: function () {}
  };

  function resolveI18nPath(path) {
    if ('@' === path.charAt(0)) {
      // absolute
      return path.slice(1);
    } else {
      // relative
      return ctx.method + '.' + path;
    }
  }

  // Server-only helper closures.
  //
  ctx.t = function translate_helper(phrase, params) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.t(locale, resolveI18nPath(phrase), params);
  };

  ctx.t.exists = function translate_exists_helper(phrase) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.hasPhrase(locale, resolveI18nPath(phrase));
  };

  // Server and render helper closures.
  //
  ctx.helpers.set_layout = function set_layout_helper(layout) {
    ctx.response.layout = layout;
  };

  ctx.helpers.link_to = function link_to_helper(name, params) {
    return N.runtime.router.linkTo(name, params) || '#';
  };

  // Constructs full URL using current env and N.config.bind
  //
  ctx.helpers.url_to = function url_to_helper(apiPath, params, linkDefaults) {
    // Reconstruct linkDefaults to prevent side-effects.
    linkDefaults = _.pick(linkDefaults || {}, 'protocol', 'hostname', 'port');

    // Detect protocol.
    if (!linkDefaults.protocol) {
      linkDefaults.protocol = ctx.request.isEncrypted ? 'https' : 'http';
    }

    // Detect hostname.
    if (!linkDefaults.hostname && ctx.origin.req.headers['host']) {
      linkDefaults.hostname = ctx.origin.req.headers['host'].split(':')[0];
    }

    var bind = findServerSocketConfig(N, apiPath);

    // Detect port.
    if (bind && !linkDefaults.port) {
      if ('https' === linkDefaults.protocol) {
        // For encrypted HTTPS connection.
        if (bind.ssl.forwarded || DEFAULT_HTTPS_PORT === bind.ssl.listen.port) {
          linkDefaults.port = null; // Do not set default port explicitly.
        } else {
          linkDefaults.port = bind.ssl.listen.port;
        }
      } else {
        // For plain HTTP connection.
        if (bind.forwarded || DEFAULT_HTTP_PORT === bind.listen.port) {
          linkDefaults.port = null; // Do not set default port explicitly.
        } else {
          linkDefaults.port = bind.listen.port;
        }
      }
    }

    return N.runtime.router.linkTo(apiPath, params, linkDefaults);
  };

  ctx.helpers.asset_path = function asset_path_helper(path) {
    var asset = N.runtime.assets.manifest.assets[path];

    return asset ? N.runtime.router.linkTo('core.assets', { path: asset }) : '#';
  };

  ctx.helpers.asset_include = function asset_include_helper(path) {
    var asset  = N.runtime.assets.environment.findAsset(path)
      , result = '';

    if (asset) {
      try {
        result = asset.toString();
      } catch (err) {
        N.logger.error('Failed inline asset %s:\n%s'
        , path
        , err.stack || err.message || err
        );
      }
    }

    return result;
  };

  ctx.helpers.t = function translate_helper(phrase, params) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.t(locale, phrase, params);
  };

  ctx.helpers.t.exists = function translate_exists_helper(phrase) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.hasPhrase(locale, phrase);
  };

  ctx.helpers.date = function date_helper(value, format) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return date(value, format, locale, tzOffset);
  };

  ctx.helpers.add_raw_data = function add_raw_data_helper(key, data) {
    if (ctx.runtime.page_data.hasOwnProperty(key)) {
      N.logger.warn('Override of %j key in env.runtime.page_data');
    }

    ctx.runtime.page_data[key] = data;
  };

  // Resulting `env` object.
  return ctx;
};
<commit_msg>env fix<commit_after>// Prepares request environment (`this` context of server methods/filters).

'use strict';

var _       = require('lodash');
var Puncher = require('puncher');
var date    = require('./date');

////////////////////////////////////////////////////////////////////////////////

var DEFAULT_HTTP_PORT  = 80;
var DEFAULT_HTTPS_PORT = 443;

var tzOffset = (new Date).getTimezoneOffset();

//  deepClone(obj) -> Object
//  - obj (Mixed): Original object to get cloned
//
//  Returns a deep copy of given object. All nested objects are deeply copied
//  instead of passing by reference.
//
//  **WARNING** This is a potentional bottleneck and performance-killer,
//              although it's used for a trivial case. Probably it would be
//              better to change it to `JSON.parse(JSON.stringify(obj))`
//
/*
function deepClone(obj) {
  // TODO: Add preventor of circular dependencies

  if (!_.isObject(obj) || _.isFunction(obj)) {
    return obj;
  }

  if (_.isDate(obj)) {
    return new Date(obj.getTime());
  }

  if (_.isRegExp(obj)) {
    return new RegExp(obj.source, obj.toString().replace(/.*\//, ""));
  }

  if (_.isArray(obj) || _.isArguments(obj)) {
    return Array.prototype.map.call(obj, function (val) {
      return deepClone(val);
    });
  }

  return _.reduce(obj, function (memo, val, key) {
    memo[key] = deepClone(val);
    return memo;
  }, {});
}
*/

// Finds the most appropriate server binding in config, by ApiPath.
//
// Probably, can be cached (if use _.memoize, swap params first)
function findServerSocketConfig(N, apiPath) {
  var splitted = apiPath.split('.'), bind;

  // Reduce apiPath looking for matching binds.
  while (!_.isEmpty(splitted)) {
    bind = N.config.bind[splitted.join('.')];

    if (bind) {
      return bind; // Found.
    }

    splitted.pop();
  }

  return N.config.bind['default'] || null;
}

////////////////////////////////////////////////////////////////////////////////

/**
 *  lib.env(options) -> Object
 *  - options (Object): Environment options.
 *
 *  Create new request environment object.
 *
 *
 *  ##### Options
 *
 *  - **http**: HTTP origin object that contains `req` and `res`.
 *  - **rpc**: API3 (Ajax) origin that contains `req` and `res`.
 *  - **skip**: Array of middlewares to skip
 *  - **session**: Session object
 *    - **locale**: Locale name as String
 *  - **method**: Name of the server method, e.g. `'forums.posts.show'`
 *  - **layout**: Layout name as String
 **/
module.exports = function env(N, options) {
  var req = options.req
    , res = options.res;

  var ctx = {

    params: options.params || {},
    method: null,

    // Contains server chain response on success
    data: {},

    // internal, to pass error from server chain to responders
    err: null,
    // internal, rendered data
    body: null,
    // internal, http status code (set in responders)
    status: N.io.OK,
    // filled by formidable with `fields & `files` structures, for http POST requests
    post: null,

    headers: {},

    runtime: {
      page_data: {}
    },

    extras:  {
      puncher: new Puncher(),
      settings: {
        params: {},
        fetch: function fetchSettings(keys, callback) {
          N.settings.get(keys, this.params, {}, callback);
        }
      }
    },

    helpers: {},

    origin: {
      req: req,
      res: res
    },

    session: options.session || null,

    request: {
      type:        options.type,
      isEncrypted: options.isEncrypted,
      ip:          options.remoteAddress,
      matched:     options.matched || null
    },

    response: {
      data: {
        head: {
          title: null, // should be filled with default value

          // List of assets for yepnope,
          // Each element is an object with properties:
          //
          //    type:   css|js
          //    link:   asset_url
          //
          // example: assets.push({type: 'js', link: '//example.com/foo.js'});
          assets: []
        },
        menus: {},
        blocks: {}
      }
    },
    log_request: function () {}
  };

  function resolveI18nPath(path) {
    if ('@' === path.charAt(0)) {
      // absolute
      return path.slice(1);
    } else {
      // relative
      return ctx.method + '.' + path;
    }
  }

  // Server-only helper closures.
  //
  ctx.t = function translate_helper(phrase, params) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.t(locale, resolveI18nPath(phrase), params);
  };

  ctx.t.exists = function translate_exists_helper(phrase) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.hasPhrase(locale, resolveI18nPath(phrase));
  };

  // Server and render helper closures.
  //
  ctx.helpers.set_layout = function set_layout_helper(layout) {
    ctx.response.layout = layout;
  };

  ctx.helpers.link_to = function link_to_helper(name, params) {
    return N.runtime.router.linkTo(name, params) || '#';
  };

  // Constructs full URL using current env and N.config.bind
  //
  ctx.helpers.url_to = function url_to_helper(apiPath, params, linkDefaults) {
    // Reconstruct linkDefaults to prevent side-effects.
    linkDefaults = _.pick(linkDefaults || {}, 'protocol', 'hostname', 'port');

    // Detect protocol.
    if (!linkDefaults.protocol) {
      linkDefaults.protocol = ctx.request.isEncrypted ? 'https' : 'http';
    }

    // Detect hostname.
    if (!linkDefaults.hostname && ctx.origin.req.headers['host']) {
      linkDefaults.hostname = ctx.origin.req.headers['host'].split(':')[0];
    }

    var bind = findServerSocketConfig(N, apiPath);

    // Detect port.
    if (bind && !linkDefaults.port) {
      if ('https' === linkDefaults.protocol) {
        // For encrypted HTTPS connection.
        if (bind.ssl.forwarded || DEFAULT_HTTPS_PORT === bind.ssl.listen.port) {
          linkDefaults.port = null; // Do not set default port explicitly.
        } else {
          linkDefaults.port = bind.ssl.listen.port;
        }
      } else {
        // For plain HTTP connection.
        if (bind.forwarded || DEFAULT_HTTP_PORT === bind.listen.port) {
          linkDefaults.port = null; // Do not set default port explicitly.
        } else {
          linkDefaults.port = bind.listen.port;
        }
      }
    }

    return N.runtime.router.linkTo(apiPath, params, linkDefaults);
  };

  ctx.helpers.asset_path = function asset_path_helper(path) {
    var asset = N.runtime.assets.manifest.assets[path];

    return asset ? N.runtime.router.linkTo('core.assets', { path: asset }) : '#';
  };

  ctx.helpers.asset_include = function asset_include_helper(path) {
    var asset  = N.runtime.assets.environment.findAsset(path)
      , result = '';

    if (asset) {
      try {
        result = asset.toString();
      } catch (err) {
        N.logger.error('Failed inline asset %s:\n%s'
        , path
        , err.stack || err.message || err
        );
      }
    }

    return result;
  };

  ctx.helpers.t = function translate_helper(phrase, params) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.t(locale, phrase, params);
  };

  ctx.helpers.t.exists = function translate_exists_helper(phrase) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return N.runtime.i18n.hasPhrase(locale, phrase);
  };

  ctx.helpers.date = function date_helper(value, format) {
    var locale = ctx.runtime.locale || N.config.locales['default'];

    return date(value, format, locale, tzOffset);
  };

  ctx.helpers.add_raw_data = function add_raw_data_helper(key, data) {
    if (ctx.runtime.page_data.hasOwnProperty(key)) {
      N.logger.warn('Override of %j key in env.runtime.page_data');
    }

    ctx.runtime.page_data[key] = data;
  };

  // Resulting `env` object.
  return ctx;
};
<|endoftext|>


<commit_before>const Discord = require('discord.js');
const client = new Discord.Client();
const weather = require('weather-js');
const sql = require("sqlite");
//const mysql = require('mysql');

//----------------------------------------------------------------------------------------------------------------------------------

sql.open("./score.sqlite");

//----------------------------------------------------------------------------------------------------------------------------------

client.config = require('./config.json');
client.log = require('./functions/log.js');
client.commands = new Discord.Collection();

//----------------------------------------------------------------------------------------------------------------------------------

//COMANDOS
client.commands.set('ping', require('./commands/ping.js'));
client.commands.set('falar', require('./commands/falar.js'));
client.commands.set('ajuda', require('./commands/ajuda.js'));
client.commands.set('limpar', require('./commands/limpar.js'));
client.commands.set('ban', require('./commands/ban.js'));
client.commands.set('kick', require('./commands/kick.js'));
client.commands.set('unban', require('./commands/unban.js'));
client.commands.set('roll', require('./commands/roll.js'));
client.commands.set('bot', require('./commands/conversaBot.js'));
client.commands.set('morra', require('./commands/conversaMorra.js'));
client.commands.set('soma', require('./commands/calcularSoma.js'));
client.commands.set('sub', require('./commands/calcularSub.js'));
client.commands.set('mult', require('./commands/calcularMult.js'));
client.commands.set('div', require('./commands/calcularDiv.js'));
client.commands.set('fsalvos', require('./commands/canalSalvos.js'));
client.commands.set('fprincipal', require('./commands/canalPrincipal.js'));
client.commands.set('resp', require('./commands/resp.js'));
client.commands.set('playinitiald', require('./commands/radioPlayInitialD.js'));
client.commands.set('playmoe', require('./commands/radioPlayMoe.js'));
client.commands.set('playanimenfo', require('./commands/radioPlayAnimeNfo.js'));
client.commands.set('stop', require('./commands/radioStop.js'));
client.commands.set('userinfo', require('./commands/userinfo.js'));
client.commands.set('serverinfo', require('./commands/serverinfo.js'));
client.commands.set('tempo', require('./commands/tempo.js'));
client.commands.set('afk', require('./commands/joinAway.js'));
client.commands.set('level', require('./commands/levelXp.js'));
client.commands.set('pontos', require('./commands/levelPoints.js'));

//----------------------------------------------------------------------------------------------------------------------------------

//MENSAGEM
client.on('messageReactionAdd', (reaction, user) => require('./events/messageReactionAdd.js')(client, reaction, user));
//----------------------------------------------------------------------------------------------------------------------------------
client.on('message', message => {
  //BANCO DE DADOS
  sql.get(`SELECT * FROM scores WHERE userId ="${message.author.id}"`).then(row =>
  { if (!row) { sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);
  } else {  let curLevel = Math.floor(0.1 * Math.sqrt(row.points + 1));
    if (curLevel > row.level) { row.level = curLevel;  sql.run(`UPDATE scores SET points = ${row.points + 1}, level = ${row.level} WHERE userId = ${message.author.id}`);  message.reply(`Ding! Parabéns! Você subiu de level. O seu level atual é **${curLevel}**!`);    }
  sql.run(`UPDATE scores SET points = ${row.points + 1} WHERE userId = ${message.author.id}`);  }
  }).catch(() => { console.error;
  sql.run("CREATE TABLE IF NOT EXISTS scores (userId TEXT, points INTEGER, level INTEGER)").then(() => {
  sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);   });  });
  //FILTRO DE PALAVRÃO
  const msgbanida = message.content.toUpperCase();
  if (msgbanida.includes('PPPPP')) { setTimeout(() => { message.channel.edit('**'+message.author.username+'**, A sua mensagem foi deletada. Por favor não diga palavrões!!! Rhrumnn!!!');}, 5000).then(msg => {msg.delete(60000)}); }
  //MENSAGEM REQUIRE
  require('./events/message.js')(client, message, sql) });
//----------------------------------------------------------------------------------------------------------------------------------

//READY
client.on('ready', () => { var channel = client.channels.get('167715230082662401'); channel.sendMessage("**O BoT está online!**").then(msg => {msg.delete(60000)}); require('./events/ready.js')(client) });

//GUILD
client.on('guildCreate', guild => require('./events/guildCreate.js')(client, guild));
client.on('guildMemberAdd', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Seja bem vindo(a) **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberRemove', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Adeus **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberUpdate', (oldMember, newMember) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+oldMember+'** **atualizou** os seus dados!').then(msg => {msg.delete(60000)}) } );
client.on('guildUpdate', (guild, oldGuild, newGuild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O servidor **'+oldGuild+'** foi **atualizado**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanAdd', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** foi **banido**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanRemove', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** foi **desbanido**!').then(msg => {msg.delete(60000)}) } );

//EMOJI
client.on('emojiCreate', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('emojiDelete', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('emojiUpdate', (emoji, oldEmoji, newEmoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+oldEmoji+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//ROLES
client.on('roleCreate', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A nova **Role** '+role+' foi adicionada!').then(msg => {msg.delete(60000)}) } );
client.on('roleDelete', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A **Role** '+role+' foi deletada!!').then(msg => {msg.delete(60000)}) } );
client.on('roleUpdate', (role, oldRole, newRole) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A **Role** '+oldRole+' foi **atualizada**!').then(msg => {msg.delete(60000)}) } );

//CANAL
client.on('channelCreate', (channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova **sala de conversa** foi **criada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelDelete', (channel, guild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma **sala de conversa** foi **deletada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelPinsUpdate', (channel, time) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova mensagem foi **fixada** em **'+time+'**!').then(msg => {msg.delete(60000)}) } );
client.on('channelUpdate', (channel, oldChannel, newChannel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A sala de conversa **'+oldChannel+'** foi atualizada!').then(msg => {msg.delete(60000)}) } );

//----------------------------------------------------------------------------------------------------------------------------------
//-----Nao usado por causa de spam
/*client.on('voiceStateUpdate', (oldMember, newMember) => { let newUserChannel = newMember.voiceChannel; let oldUserChannel = oldMember.voiceChannel;
if(oldUserChannel === undefined && newUserChannel !== undefined) { entra no canal --- CODIGO de msg aqui } else if(newUserChannel === undefined){ sai no canal --- CODIGO de msg aqui }}); */
//----------------------------------------------------------------------------------------------------------------------------------
//-----mysql Heroku connect database
/*var con;
if(process.env.DATABASE_URL) { con = mysql.createConnection(process.env.DATABASE_URL); } */

//client.login(config.token)
client.login(process.env.BOT_TOKEN);<commit_msg><commit_after>const Discord = require('discord.js');
const client = new Discord.Client();
const weather = require('weather-js');
const sql = require("sqlite");
//const mysql = require('mysql');

//----------------------------------------------------------------------------------------------------------------------------------

sql.open("./score.sqlite");

//----------------------------------------------------------------------------------------------------------------------------------

client.config = require('./config.json');
client.log = require('./functions/log.js');
client.commands = new Discord.Collection();

//----------------------------------------------------------------------------------------------------------------------------------

//COMANDOS
client.commands.set('ping', require('./commands/ping.js'));
client.commands.set('falar', require('./commands/falar.js'));
client.commands.set('ajuda', require('./commands/ajuda.js'));
client.commands.set('limpar', require('./commands/limpar.js'));
client.commands.set('ban', require('./commands/ban.js'));
client.commands.set('kick', require('./commands/kick.js'));
client.commands.set('unban', require('./commands/unban.js'));
client.commands.set('roll', require('./commands/roll.js'));
client.commands.set('bot', require('./commands/conversaBot.js'));
client.commands.set('morra', require('./commands/conversaMorra.js'));
client.commands.set('soma', require('./commands/calcularSoma.js'));
client.commands.set('sub', require('./commands/calcularSub.js'));
client.commands.set('mult', require('./commands/calcularMult.js'));
client.commands.set('div', require('./commands/calcularDiv.js'));
client.commands.set('fsalvos', require('./commands/canalSalvos.js'));
client.commands.set('fprincipal', require('./commands/canalPrincipal.js'));
client.commands.set('resp', require('./commands/resp.js'));
client.commands.set('playinitiald', require('./commands/radioPlayInitialD.js'));
client.commands.set('playmoe', require('./commands/radioPlayMoe.js'));
client.commands.set('playanimenfo', require('./commands/radioPlayAnimeNfo.js'));
client.commands.set('stop', require('./commands/radioStop.js'));
client.commands.set('userinfo', require('./commands/userinfo.js'));
client.commands.set('serverinfo', require('./commands/serverinfo.js'));
client.commands.set('tempo', require('./commands/tempo.js'));
client.commands.set('afk', require('./commands/joinAway.js'));
client.commands.set('level', require('./commands/levelXp.js'));
client.commands.set('pontos', require('./commands/levelPoints.js'));

//----------------------------------------------------------------------------------------------------------------------------------

//MENSAGEM
client.on('messageReactionAdd', (reaction, user) => require('./events/messageReactionAdd.js')(client, reaction, user));
//----------------------------------------------------------------------------------------------------------------------------------
client.on('message', message => {
  //BANCO DE DADOS
  sql.get(`SELECT * FROM scores WHERE userId ="${message.author.id}"`).then(row =>
  { if (!row) { sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);
  } else {  let curLevel = Math.floor(0.1 * Math.sqrt(row.points + 1));
    if (curLevel > row.level) { row.level = curLevel;  sql.run(`UPDATE scores SET points = ${row.points + 1}, level = ${row.level} WHERE userId = ${message.author.id}`);  message.reply(`Ding! Parabéns! Você subiu de level. O seu level atual é **${curLevel}**!`);    }
  sql.run(`UPDATE scores SET points = ${row.points + 1} WHERE userId = ${message.author.id}`);  }
  }).catch(() => { console.error;
  sql.run("CREATE TABLE IF NOT EXISTS scores (userId TEXT, points INTEGER, level INTEGER)").then(() => {
  sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);   });  });
  //FILTRO DE PALAVRÃO
  const msgbanida = message.content.toUpperCase();
  if (msgbanida.includes('PPPPP')) { await message.channel.edit('**'+message.author.username+'**, A sua mensagem foi deletada. Por favor não diga palavrões!!! Rhrumnn!!!').then(msg => {msg.delete(60000)}); }
  //MENSAGEM REQUIRE
  require('./events/message.js')(client, message, sql) });
//----------------------------------------------------------------------------------------------------------------------------------

//READY
client.on('ready', () => { var channel = client.channels.get('167715230082662401'); channel.sendMessage("**O BoT está online!**").then(msg => {msg.delete(60000)}); require('./events/ready.js')(client) });

//GUILD
client.on('guildCreate', guild => require('./events/guildCreate.js')(client, guild));
client.on('guildMemberAdd', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Seja bem vindo(a) **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberRemove', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Adeus **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberUpdate', (oldMember, newMember) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+oldMember+'** **atualizou** os seus dados!').then(msg => {msg.delete(60000)}) } );
client.on('guildUpdate', (guild, oldGuild, newGuild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O servidor **'+oldGuild+'** foi **atualizado**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanAdd', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** foi **banido**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanRemove', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** foi **desbanido**!').then(msg => {msg.delete(60000)}) } );

//EMOJI
client.on('emojiCreate', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('emojiDelete', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('emojiUpdate', (emoji, oldEmoji, newEmoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+oldEmoji+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//ROLES
client.on('roleCreate', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A nova **Role** '+role+' foi adicionada!').then(msg => {msg.delete(60000)}) } );
client.on('roleDelete', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A **Role** '+role+' foi deletada!!').then(msg => {msg.delete(60000)}) } );
client.on('roleUpdate', (role, oldRole, newRole) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A **Role** '+oldRole+' foi **atualizada**!').then(msg => {msg.delete(60000)}) } );

//CANAL
client.on('channelCreate', (channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova **sala de conversa** foi **criada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelDelete', (channel, guild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma **sala de conversa** foi **deletada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelPinsUpdate', (channel, time) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova mensagem foi **fixada** em **'+time+'**!').then(msg => {msg.delete(60000)}) } );
client.on('channelUpdate', (channel, oldChannel, newChannel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A sala de conversa **'+oldChannel+'** foi atualizada!').then(msg => {msg.delete(60000)}) } );

//----------------------------------------------------------------------------------------------------------------------------------
//-----Nao usado por causa de spam
/*client.on('voiceStateUpdate', (oldMember, newMember) => { let newUserChannel = newMember.voiceChannel; let oldUserChannel = oldMember.voiceChannel;
if(oldUserChannel === undefined && newUserChannel !== undefined) { entra no canal --- CODIGO de msg aqui } else if(newUserChannel === undefined){ sai no canal --- CODIGO de msg aqui }}); */
//----------------------------------------------------------------------------------------------------------------------------------
//-----mysql Heroku connect database
/*var con;
if(process.env.DATABASE_URL) { con = mysql.createConnection(process.env.DATABASE_URL); } */

//client.login(config.token)
client.login(process.env.BOT_TOKEN);<|endoftext|>


<commit_before>/**
 * DEPENDENCIES
 */
var twit = require('twit');
var config = require('./config');
var sentiment = require('./sentiment');

var Twitter = new twit(config);

var queryString = '#100DaysOfCode, #100daysofcode';

// Console Welcome Msg
console.log('Welcome to #100DaysOfCode');

// RETWEET
// find latest tweets according to #100daysofcode
var retweet = function () {
  var params = {
    q: queryString,
    result_type: 'recent',
    lang: 'en'
  };
  // for more parameters options, see: https://dev.twitter.com/rest/reference/get/search/tweets
  Twitter.get('search/tweets', params, function (err, data) {
    // if no errors
    if (!err) {
      // grab ID of tweet to retweet
      var retweetId = data.statuses[0].id_str;
      // Tell Twitter to retweet
      Twitter.post('statuses/retweet/:id', {
        id: retweetId
      }, function (err, response) {
        // if error while retweet
        if (err) {
          console.log('While Retweet. ERROR!...Maybe Duplicate Tweet');
        } else {
          console.log('Retweet. SUCCESS!');
        }

      });
    }
    // if unable to search a tweet
    else {
      console.log('Cannot Search Tweet. ERROR!');
    }
  });
};

retweet();
// retweet every 10 minutes
setInterval(retweet, 600000);

// FAVORITE ==============================
// find a random tweet using querySring and 'favorite' it
var favoriteTweet = function () {
  var params = {
    q: queryString,
    result_type: 'recent',
    lang: 'en'
  };
  // for more parameters, see: https://dev.twitter.com/rest/reference

  // find a tweet
  Twitter.get('search/tweets', params, function (err, data) {
    // find tweets randomly
    var tweet = data.statuses;
    var randomTweet = ranDom(tweet);    //pick a random tweet

    //if random tweet is found
    if (typeof randomTweet != 'undefined') {
      // Tell Twitter to 'favorite' it
      Twitter.post('favorites/create', { id: randomTweet.id_str }, function (err, response) {
        // if error while 'favorite'
        if (err) {
          console.log('Cannot Favorite. ERROR!');
        }
        else {
          console.log('Favorite Done. SUCCESS!');
        }
      });
    }
  });
};
// grab & 'favorite' a tweet ASAP program is running
favoriteTweet();
// 'favorite' a tweet every 12 minutes
setInterval(favoriteTweet, 720000);

// STREAM API for interacting with a USER =======
// set up a user stream
var userStream = Twitter.stream('user');

// REPLY-FOLLOW BOT ============================
// what to do when someone follows you?
userStream.on('follow', followed);

// ...trigger the callback
function followed(event) {
  console.log('Follow Event now RUNNING');
  // get USER's twitter handler (screen name)
  var name = event.source.name,
    screenName = event.source.screen_name;
  // function that replies back to every USER who followed for the first time
  tweetNow('@' + screenName + ' Thank you. What are you working on today?');
}

// function definition to tweet back to USER who followed
function tweetNow(tweetTxt) {
  var tweet = {
    status: tweetTxt
  };
  Twitter.post('statuses/update', tweet, function (err, data, response) {
    if (err) {
      console.log("Cannot Reply to Follower. ERROR!");
    }
    else {
      console.log('Reply to follower. SUCCESS!');
    }
  });
}

// Congratulation Messages for Day 1 & Day 100 ========
const hashtagStream = Twitter.stream('statuses/filter', {
  track: ['#100DaysOfCode']
});

// Function that checks if day 1 or day 100
var checkIfFirstOrLastDay = function() {
  hashtagStream.on('tweet', (tweet) => {
    if (checkIfLastDay(tweet)) {
        console.log(`Sending a congrats to @${tweet.user.screen_name}`)
        tweetNow(`WOOT! You did it @${tweet.user.screen_name}! Party Time!`)
    } else if (checkIfFirstDay(tweet)) {
      console.log(`Sending a congrats to @${tweet.user.screen_name}`)
      tweetNow(`Congrats on your first day @${tweet.user.screen_name}! Keep it up!`)
    };
  });
}
checkIfFirstOrLastDay();
setImmediate(checkIfFirstOrLastDay, 720000);

// NOTE: String elements in firstDay & lastDay are case insensitive

function checkIfFirstDay(tweet) {
  const firstDay = ['first day', 'day one', 'day 1/100'];
  const firstdayRegex = /\bday\s?0?1\b/i;
  console.log(`Checking if first day`)
  for (let i = 0; i < firstDay.length; i++) {
    if (checkTweetForText(tweet.text, firstDay[i]) || tweet.text.match(firstdayRegex) != null) {
      return true;
    }
  }
}

function checkIfLastDay(tweet) {
  const lastDay = ['#day100', 'final day', 'day 100', 'one hundred', '100/100'];
  const lastdayRegex = /\bday\s?100\b/i;
  console.log(`Checking if Last day`)
  for (let i = 0; i < lastDay.length; i++) {
    if (checkTweetForText(tweet.text, lastDay[i]) || tweet.text.match(lastdayRegex) != null) {
      return true;
    }
  }
}

function checkTweetForText(tweetText, value){
  return tweetText.toLowerCase().indexOf(value) > -1 && tweetText.toLowerCase().indexOf('100daysofcode') > -1
}

function ranDom(arr) {
  var index = Math.floor(Math.random() * arr.length);
  return arr[index];
}

// SENTIMENT DETECTION =================
const hashtagStream2 = Twitter.stream('statuses/filter', {
   track: '#100DaysOfCode'
});

var sentimentBot = function() {
  hashtagStream2.on('tweet', (tweet) => {
    console.log(`Sentiment Bot Running`)
    //  Setup the http call
    var httpCall = sentiment.init()

    // Don't do anything if it's the bot tweet
    if (tweet.user.screen_name == '_100DaysOfCode') return;

    httpCall.send("txt=" + tweet.text).end(function (result) {

      var sentim = result.body.result.sentiment;
      var confidence = parseFloat(result.body.result.confidence);

      // if sentiment is Negative and the confidence is above 75%
      if (sentim == 'Negative' && confidence >= 75) {

        // get a random quote
        var phrase = sentiment.randomQuote()
        var screen_name = tweet.user.screen_name

        // tweet a random encouragement phrase
        tweetNow('@' + screen_name + ' ' + phrase)

      }

    });
  });
};
sentimentBot();
<commit_msg>Update bot.js<commit_after>/**
 * DEPENDENCIES
 */
var twit = require('twit');
var config = require('./config');
var sentiment = require('./sentiment');

var Twitter = new twit(config);

var queryString = '#100DaysOfCode, #100daysofcode';

// Console Welcome Msg
console.log('Welcome to #100DaysOfCode');

// RETWEET
// find latest tweets according to #100daysofcode
var retweet = function () {
  var params = {
    q: queryString,
    result_type: 'recent',
    lang: 'en'
  };
  // for more parameters options, see: https://dev.twitter.com/rest/reference/get/search/tweets
  Twitter.get('search/tweets', params, function (err, data) {
    // if no errors
    if (!err) {
      // grab ID of tweet to retweet
      var retweetId = data.statuses[0].id_str;
      // Tell Twitter to retweet
      Twitter.post('statuses/retweet/:id', {
        id: retweetId
      }, function (err, response) {
        // if error while retweet
        if (err) {
          console.log('While Retweet. ERROR!...Maybe Duplicate Tweet');
        } else {
          console.log('Retweet. SUCCESS!');
        }

      });
    }
    // if unable to search a tweet
    else {
      console.log('Cannot Search Tweet. ERROR!');
    }
  });
};

retweet();
// retweet every 20 minutes
setInterval(retweet, 1200000);

// FAVORITE ==============================
// find a random tweet using querySring and 'favorite' it
var favoriteTweet = function () {
  var params = {
    q: queryString,
    result_type: 'recent',
    lang: 'en'
  };
  // for more parameters, see: https://dev.twitter.com/rest/reference

  // find a tweet
  Twitter.get('search/tweets', params, function (err, data) {
    // find tweets randomly
    var tweet = data.statuses;
    var randomTweet = ranDom(tweet);    //pick a random tweet

    //if random tweet is found
    if (typeof randomTweet != 'undefined') {
      // Tell Twitter to 'favorite' it
      Twitter.post('favorites/create', { id: randomTweet.id_str }, function (err, response) {
        // if error while 'favorite'
        if (err) {
          console.log('Cannot Favorite. ERROR!');
        }
        else {
          console.log('Favorite Done. SUCCESS!');
        }
      });
    }
  });
};
// grab & 'favorite' a tweet ASAP program is running
favoriteTweet();
// 'favorite' a tweet every 16 minutes
setInterval(favoriteTweet, 960000);

// STREAM API for interacting with a USER =======
// set up a user stream
var userStream = Twitter.stream('user');

// REPLY-FOLLOW BOT ============================
// what to do when someone follows you?
userStream.on('follow', followed);

// ...trigger the callback
function followed(event) {
  console.log('Follow Event now RUNNING');
  // get USER's twitter handler (screen name)
  var name = event.source.name,
    screenName = event.source.screen_name;
  // function that replies back to every USER who followed for the first time
  tweetNow('@' + screenName + ' Thank you. What are you working on today?');
}

// function definition to tweet back to USER who followed
function tweetNow(tweetTxt) {
  var tweet = {
    status: tweetTxt
  };
  Twitter.post('statuses/update', tweet, function (err, data, response) {
    if (err) {
      console.log("Cannot Reply to Follower. ERROR!");
    }
    else {
      console.log('Reply to follower. SUCCESS!');
    }
  });
}

// Congratulation Messages for Day 1 & Day 100 ========
const hashtagStream = Twitter.stream('statuses/filter', {
  track: ['#100DaysOfCode']
});

// Function that checks if day 1 or day 100
var checkIfFirstOrLastDay = function() {
  hashtagStream.on('tweet', (tweet) => {
    if (checkIfLastDay(tweet)) {
        console.log(`Sending a congrats to @${tweet.user.screen_name}`)
        tweetNow(`WOOT! You did it @${tweet.user.screen_name}! Party Time!`)
    } else if (checkIfFirstDay(tweet)) {
      console.log(`Sending a congrats to @${tweet.user.screen_name}`)
      tweetNow(`Congrats on your first day @${tweet.user.screen_name}! Keep it up!`)
    };
  });
}
checkIfFirstOrLastDay();
setImmediate(checkIfFirstOrLastDay, 720000);

// NOTE: String elements in firstDay & lastDay are case insensitive

function checkIfFirstDay(tweet) {
  const firstDay = ['first day', 'day one', 'day 1/100'];
  const firstdayRegex = /\bday\s?0?1\b/i;
  console.log(`Checking if first day`)
  for (let i = 0; i < firstDay.length; i++) {
    if (checkTweetForText(tweet.text, firstDay[i]) || tweet.text.match(firstdayRegex) != null) {
      return true;
    }
  }
}

function checkIfLastDay(tweet) {
  const lastDay = ['#day100', 'final day', 'day 100', 'one hundred', '100/100'];
  const lastdayRegex = /\bday\s?100\b/i;
  console.log(`Checking if Last day`)
  for (let i = 0; i < lastDay.length; i++) {
    if (checkTweetForText(tweet.text, lastDay[i]) || tweet.text.match(lastdayRegex) != null) {
      return true;
    }
  }
}

function checkTweetForText(tweetText, value){
  return tweetText.toLowerCase().indexOf(value) > -1 && tweetText.toLowerCase().indexOf('100daysofcode') > -1
}

function ranDom(arr) {
  var index = Math.floor(Math.random() * arr.length);
  return arr[index];
}

// SENTIMENT DETECTION =================
const hashtagStream2 = Twitter.stream('statuses/filter', {
   track: '#100DaysOfCode'
});

var sentimentBot = function() {
  hashtagStream2.on('tweet', (tweet) => {
    console.log(`Sentiment Bot Running`)
    //  Setup the http call
    var httpCall = sentiment.init()

    // Don't do anything if it's the bot tweet
    if (tweet.user.screen_name == '_100DaysOfCode') return;

    httpCall.send("txt=" + tweet.text).end(function (result) {

      var sentim = result.body.result.sentiment;
      var confidence = parseFloat(result.body.result.confidence);

      // if sentiment is Negative and the confidence is above 75%
      if (sentim == 'Negative' && confidence >= 75) {

        // get a random quote
        var phrase = sentiment.randomQuote()
        var screen_name = tweet.user.screen_name

        // tweet a random encouragement phrase
        tweetNow('@' + screen_name + ' ' + phrase)

      }

    });
  });
};
sentimentBot();
<|endoftext|>


<commit_before>const PROTO_VER_1_10 = require('minecraft-data')('1.10.2').version.version
const { once } = require('events')

module.exports = inject

function inject (bot, options) {
  const CHAT_LENGTH_LIMIT = options.chatLengthLimit || ((bot.protocolVersion > PROTO_VER_1_10) ? 256 : 100)
  const USERNAME_REGEX = '(?:\\(.+\\)|\\[.+\\]|.)*?(\\w+)'

  const ChatMessage = require('prismarine-chat')(bot.version)
  // add an array, containing objects such as {pattern:/regex pattern/, chatType:"string", description:"string"}
  // chat.pattern.type will emit an event for bot.on() of the same type, eg chatType = whisper will trigger bot.on('whisper')
  bot.chatPatterns = [
    {
      pattern: new RegExp(`^${USERNAME_REGEX} whispers(?: to you)?:? (.*)$`),
      type: 'whisper',
      description: 'Vanilla whisper'
    },
    {
      pattern: new RegExp(`^\\[${USERNAME_REGEX} -> \\w+\\s?\\] (.*)$`),
      type: 'whisper',
      description: 'Essentials whisper'
    },
    {
      pattern: new RegExp(`^${USERNAME_REGEX}\\s?[>:\\-»\\]\\)~]+\\s(.*)$`),
      type: 'chat',
      description: 'Universal chat'
    }
  ]

  bot.chatAddPattern = (patternValue, typeValue, descriptionValue) => {
    // description is not required but recommended
    if (typeof descriptionValue === 'undefined') {
      descriptionValue = 'None'
    }
    bot.chatPatterns.push({
      pattern: patternValue,
      type: typeValue,
      description: descriptionValue
    })
  }

  bot._client.on('chat', (packet) => {
    function checkForChatPatterns (msg) {
      const stringMsg = msg.toString()
      let matchAny = false
      // iterate through each object in chat.patterns array and test if .pattern matches
      for (const { pattern, type } of bot.chatPatterns) {
        // Chat pattern matches server messages so drop them
        if (stringMsg.startsWith('[Server:')) break

        const match = stringMsg.match(pattern)
        if (match) {
          matchAny = true
          bot.emit(type, ...match.slice(1), msg.translate, msg)
        }
      }

      if (matchAny === false) {
        bot.emit('unmachedMessage', stringMsg, msg)
      }
    }

    let msg
    try {
      msg = new ChatMessage(JSON.parse(packet.message))
    } catch (e) {
      msg = new ChatMessage(packet.message)
    }

    const ChatPositions = {
      0: 'chat',
      1: 'system',
      2: 'game_info'
    }

    const chatPosition = ChatPositions[packet.position]

    bot.emit('message', msg, chatPosition)
    checkForChatPatterns(msg)

    // Position 2 is the action bar
    if (packet.position === 2) bot.emit('actionBar', msg)
  })

  function chatWithHeader (header, message) {
    if (typeof message === 'number') message = message.toString()
    if (typeof message !== 'string') {
      throw new Error('Incorrect type! Should be a string.')
    }

    const lengthLimit = CHAT_LENGTH_LIMIT - header.length
    message.split('\n').forEach((subMessage) => {
      if (!subMessage) return
      let i
      let smallMsg
      for (i = 0; i < subMessage.length; i += lengthLimit) {
        smallMsg = header + subMessage.substring(i, i + lengthLimit)
        bot._client.write('chat', { message: smallMsg })
      }
    })
  }

  async function tabComplete (text, assumeCommand = false, sendBlockInSight = true) {
    let position

    if (sendBlockInSight) {
      const block = bot.blockInSight()

      if (block) {
        position = block.position
      }
    }

    bot._client.write('tab_complete', {
      text,
      assumeCommand,
      lookedAtBlock: position
    })

    const [packet] = await once(bot._client, 'tab_complete')
    return packet.matches
  }

  bot.whisper = (username, message) => {
    chatWithHeader(`/tell ${username} `, message)
  }
  bot.chat = (message) => {
    chatWithHeader('', message)
  }

  bot.tabComplete = callbackify(tabComplete)
}

function callbackify (f) { // specifically for this function because cb isn't the last parameter
  return function (...args) {
    const cb = args[1]
    args.splice(1, 1)
    return f(...args).then(r => { if (cb) { cb(undefined, r) } return r }, err => { if (cb) { cb(err) } else throw err })
  }
}
<commit_msg>Changed error message<commit_after>const PROTO_VER_1_10 = require('minecraft-data')('1.10.2').version.version
const { once } = require('events')

module.exports = inject

function inject (bot, options) {
  const CHAT_LENGTH_LIMIT = options.chatLengthLimit || ((bot.protocolVersion > PROTO_VER_1_10) ? 256 : 100)
  const USERNAME_REGEX = '(?:\\(.+\\)|\\[.+\\]|.)*?(\\w+)'

  const ChatMessage = require('prismarine-chat')(bot.version)
  // add an array, containing objects such as {pattern:/regex pattern/, chatType:"string", description:"string"}
  // chat.pattern.type will emit an event for bot.on() of the same type, eg chatType = whisper will trigger bot.on('whisper')
  bot.chatPatterns = [
    {
      pattern: new RegExp(`^${USERNAME_REGEX} whispers(?: to you)?:? (.*)$`),
      type: 'whisper',
      description: 'Vanilla whisper'
    },
    {
      pattern: new RegExp(`^\\[${USERNAME_REGEX} -> \\w+\\s?\\] (.*)$`),
      type: 'whisper',
      description: 'Essentials whisper'
    },
    {
      pattern: new RegExp(`^${USERNAME_REGEX}\\s?[>:\\-»\\]\\)~]+\\s(.*)$`),
      type: 'chat',
      description: 'Universal chat'
    }
  ]

  bot.chatAddPattern = (patternValue, typeValue, descriptionValue) => {
    // description is not required but recommended
    if (typeof descriptionValue === 'undefined') {
      descriptionValue = 'None'
    }
    bot.chatPatterns.push({
      pattern: patternValue,
      type: typeValue,
      description: descriptionValue
    })
  }

  bot._client.on('chat', (packet) => {
    function checkForChatPatterns (msg) {
      const stringMsg = msg.toString()
      let matchAny = false
      // iterate through each object in chat.patterns array and test if .pattern matches
      for (const { pattern, type } of bot.chatPatterns) {
        // Chat pattern matches server messages so drop them
        if (stringMsg.startsWith('[Server:')) break

        const match = stringMsg.match(pattern)
        if (match) {
          matchAny = true
          bot.emit(type, ...match.slice(1), msg.translate, msg)
        }
      }

      if (matchAny === false) {
        bot.emit('unmachedMessage', stringMsg, msg)
      }
    }

    let msg
    try {
      msg = new ChatMessage(JSON.parse(packet.message))
    } catch (e) {
      msg = new ChatMessage(packet.message)
    }

    const ChatPositions = {
      0: 'chat',
      1: 'system',
      2: 'game_info'
    }

    const chatPosition = ChatPositions[packet.position]

    bot.emit('message', msg, chatPosition)
    checkForChatPatterns(msg)

    // Position 2 is the action bar
    if (packet.position === 2) bot.emit('actionBar', msg)
  })

  function chatWithHeader (header, message) {
    if (typeof message === 'number') message = message.toString()
    if (typeof message !== 'string') {
      throw new Error('Incorrect type! Should be a string or number.')
    }

    const lengthLimit = CHAT_LENGTH_LIMIT - header.length
    message.split('\n').forEach((subMessage) => {
      if (!subMessage) return
      let i
      let smallMsg
      for (i = 0; i < subMessage.length; i += lengthLimit) {
        smallMsg = header + subMessage.substring(i, i + lengthLimit)
        bot._client.write('chat', { message: smallMsg })
      }
    })
  }

  async function tabComplete (text, assumeCommand = false, sendBlockInSight = true) {
    let position

    if (sendBlockInSight) {
      const block = bot.blockInSight()

      if (block) {
        position = block.position
      }
    }

    bot._client.write('tab_complete', {
      text,
      assumeCommand,
      lookedAtBlock: position
    })

    const [packet] = await once(bot._client, 'tab_complete')
    return packet.matches
  }

  bot.whisper = (username, message) => {
    chatWithHeader(`/tell ${username} `, message)
  }
  bot.chat = (message) => {
    chatWithHeader('', message)
  }

  bot.tabComplete = callbackify(tabComplete)
}

function callbackify (f) { // specifically for this function because cb isn't the last parameter
  return function (...args) {
    const cb = args[1]
    args.splice(1, 1)
    return f(...args).then(r => { if (cb) { cb(undefined, r) } return r }, err => { if (cb) { cb(err) } else throw err })
  }
}
<|endoftext|>


<commit_before>var utils = require('./../utils');
var fs = require('fs');
var shell = require('shelljs');
var path = require('path');
var mime = require('mime');
var cwd = process.cwd();
require("consoleplusplus");
console.disableTimestamp();
var cleancss = require('clean-css');
var crypto = require('crypto');
var md5;

var addedTohtml = false;
var allCss = [];
var allCssCode = '';
var cped = {};
var concatedCss = {};
exports.reset = function () {
    allCss = [];
    allCssCode = '';
    cped = {};
    concatedCss = {};
    addedTohtml = false;
};

exports.reg = /<(link)\s+[\s\S]*?["'\s\w\/]>\s*/ig;

var converter = {
    /**
     * 将图片转化为base64编码的data-uri形式
     * @param mu        匹配到的值（url(...)）
     * @param uriString 捕获到的uri字符串（./xxx/xxx.xxx?xxx#xxx）
     * @param filename  图片地址
     * @return {string}
     */
    tobase64: function (mu, uriString, filename) {
        if (!fs.existsSync(filename)) {
            console.error('no such file: ' + filename);
            return mu;
        } else {
            console.info('#green{[convert file]} ' + filename + ' #green{to data uri]}\n');
             return mu.replace(uriString, [
                'data:',
                mime.lookup(filename),
                ';base64,',
                fs.readFileSync(filename).toString('base64')
            ].join(''));
        }
    }
};

/**
 * 处理css代码中的静态文件引用
 * @param csscode
 * @param cssPath
 * @param projectPublishRoot
 * @returns {XML|string|void|*}
 */
exports.dealWithUrl = function (csscode, cssPath, projectPublishRoot) {
    return csscode.replace(utils.regs['url'], function (mu, $1, $2, $3, $4) {
        if ($3 === '' || //空 url 不处理
            $3.indexOf('http') === 0) {//网上的资源，直接返回，不处理
            return mu;
        }
        var staticPath = path.resolve(path.dirname(cssPath), $3);
        var psuf = '';
        staticPath = staticPath.replace(/\?.*$|#.*$/ig, function (m) {//处理url中带有 # ？后缀
            psuf = m;
            return '';
        });
        if (Object.keys(converter).indexOf($4) > -1) { // 对命中标记的图片进行处理
            return converter[$4](mu, $3, staticPath);
        }
        shell.cp('-rf', staticPath, projectPublishRoot + '/statics');//拷贝到目标目录
        if (!cped[staticPath]) {
            cped[staticPath] = true;
            console.info('#green{[copy file]} ' + $3 + ' #green{to /statics.]}\n');
        }
        var md5Name = utils.md5file(projectPublishRoot + '/statics/' + path.basename(staticPath));
        return mu.replace($3, '../statics/' + md5Name + psuf); //css会被放到static统计的目录中，因此是 ../statics
    });
};

/**
 * 搜集所有link，拷贝link 所需资源到statics，并将md5后的名称替换css中的名称
 * 收集css代码，并拷贝css依赖的图片等资源到statics中
 * @param m 匹配到的字符串
 * @param htmlpath html页面的路径
 * @param projectRoot 项目原路径
 * @param pageName html页面的名称
 * @param concatServerBaseUrl 上传到cms后，固定的server前缀
 * @param projectPublishRoot 项目发布后的路径
 */
exports.preReplace = function (m, htmlpath, projectRoot, pageName, concatServerBaseUrl, projectPublishRoot) {
    if (m.match(/role\s*=\s*(['"]?)\s*debug\s*\1/) !== null) { //只处理带有role=debug的项
        var getHref = m.match(/(?:\shref\s*=\s*)(['"]?)([^'"\s]*)\1/);
        var cssPath = path.resolve(path.dirname(htmlpath), getHref[2]);
        if (!concatedCss[cssPath]) {
            allCssCode += exports.dealWithUrl(fs.readFileSync(cssPath, 'utf-8'), cssPath, projectPublishRoot);
            allCss.push(m);
            concatedCss[cssPath] = true;
        }
    }
};

/**
 * 替换
 * @param m 匹配到的字符串
 * @param htmlpath html页面的路径
 * @param projectRoot 项目原路径
 * @param pageName html页面的名称
 * @param baseurl 上传到cms后，固定的server前缀
 * @param publishroot 项目发布后的路径
 */
exports.replace = function (m, htmlpath, projectRoot, pageName, baseurl, publishroot) {
    if (m.match(/role\s*=\s*(['"]?)\s*debug\s*\1/) !== null) {//设置为role=debug的标签，删掉
        if (!addedTohtml) {//最后一个link标签
            console.info('#green{[pack css files]}:');
            var mincss = new cleancss().minify(allCssCode);
            mincss = mincss.styles || mincss;//兼容新旧版本的cleancss的minify接口
            md5 = crypto.createHash('md5');
            var cssMd5 = md5.update(mincss)
                .digest('hex')
                .substring(0, 6);
            fs.writeFileSync(path.resolve(cwd, './__publish__/' + projectRoot + '/styles/' + pageName + '_' + cssMd5 + '.css'), mincss);
            allCss.forEach(function (val) {
                console.log(val.match(/(?:\shref\s*=\s*)(['"]?)([^'"\s]*)\1/)[2]);
            });
            console.info('#green{[pack css files done.]}\n');
            addedTohtml = true;
            return '<link rel="stylesheet" href="' + baseurl + '/styles/' + pageName + '_' + cssMd5 + '.css"/>';
        } else {
            return '';
        }
    }
    return m;
};<commit_msg>MOD：调整分支写法，避免误会<commit_after>var utils = require('./../utils');
var fs = require('fs');
var shell = require('shelljs');
var path = require('path');
var mime = require('mime');
var cwd = process.cwd();
require("consoleplusplus");
console.disableTimestamp();
var cleancss = require('clean-css');
var crypto = require('crypto');
var md5;

var addedTohtml = false;
var allCss = [];
var allCssCode = '';
var cped = {};
var concatedCss = {};
exports.reset = function () {
    allCss = [];
    allCssCode = '';
    cped = {};
    concatedCss = {};
    addedTohtml = false;
};

exports.reg = /<(link)\s+[\s\S]*?["'\s\w\/]>\s*/ig;

var converter = {
    /**
     * 将图片转化为base64编码的data-uri形式
     * @param mu        匹配到的值（url(...)）
     * @param uriString 捕获到的uri字符串（./xxx/xxx.xxx?xxx#xxx）
     * @param filename  图片地址
     * @return {string}
     */
    tobase64: function (mu, uriString, filename) {
        if (!fs.existsSync(filename)) {
            console.error('no such file: ' + filename);
            return mu;
        } else {
            console.info('#green{[convert file]} ' + filename + ' #green{to data uri]}\n');
             return mu.replace(uriString, [
                'data:',
                mime.lookup(filename),
                ';base64,',
                fs.readFileSync(filename).toString('base64')
            ].join(''));
        }
    }
};

/**
 * 处理css代码中的静态文件引用
 * @param csscode
 * @param cssPath
 * @param projectPublishRoot
 * @returns {XML|string|void|*}
 */
exports.dealWithUrl = function (csscode, cssPath, projectPublishRoot) {
    return csscode.replace(utils.regs['url'], function (mu, $1, $2, $3, $4) {
        if ($3 === '' || //空 url 不处理
            $3.indexOf('http') === 0) {//网上的资源，直接返回，不处理
            return mu;
        }
        var staticPath = path.resolve(path.dirname(cssPath), $3);
        var psuf = '';
        staticPath = staticPath.replace(/\?.*$|#.*$/ig, function (m) {//处理url中带有 # ？后缀
            psuf = m;
            return '';
        });
        if (Object.keys(converter).indexOf($4) > -1) { // 对命中标记的图片进行处理
            return converter[$4](mu, $3, staticPath);
        } else {
            shell.cp('-rf', staticPath, projectPublishRoot + '/statics');//拷贝到目标目录
            if (!cped[staticPath]) {
                cped[staticPath] = true;
                console.info('#green{[copy file]} ' + $3 + ' #green{to /statics.]}\n');
            }
            var md5Name = utils.md5file(projectPublishRoot + '/statics/' + path.basename(staticPath));
            return mu.replace($3, '../statics/' + md5Name + psuf); //css会被放到static统计的目录中，因此是 ../statics
        }
    });
};

/**
 * 搜集所有link，拷贝link 所需资源到statics，并将md5后的名称替换css中的名称
 * 收集css代码，并拷贝css依赖的图片等资源到statics中
 * @param m 匹配到的字符串
 * @param htmlpath html页面的路径
 * @param projectRoot 项目原路径
 * @param pageName html页面的名称
 * @param concatServerBaseUrl 上传到cms后，固定的server前缀
 * @param projectPublishRoot 项目发布后的路径
 */
exports.preReplace = function (m, htmlpath, projectRoot, pageName, concatServerBaseUrl, projectPublishRoot) {
    if (m.match(/role\s*=\s*(['"]?)\s*debug\s*\1/) !== null) { //只处理带有role=debug的项
        var getHref = m.match(/(?:\shref\s*=\s*)(['"]?)([^'"\s]*)\1/);
        var cssPath = path.resolve(path.dirname(htmlpath), getHref[2]);
        if (!concatedCss[cssPath]) {
            allCssCode += exports.dealWithUrl(fs.readFileSync(cssPath, 'utf-8'), cssPath, projectPublishRoot);
            allCss.push(m);
            concatedCss[cssPath] = true;
        }
    }
};

/**
 * 替换
 * @param m 匹配到的字符串
 * @param htmlpath html页面的路径
 * @param projectRoot 项目原路径
 * @param pageName html页面的名称
 * @param baseurl 上传到cms后，固定的server前缀
 * @param publishroot 项目发布后的路径
 */
exports.replace = function (m, htmlpath, projectRoot, pageName, baseurl, publishroot) {
    if (m.match(/role\s*=\s*(['"]?)\s*debug\s*\1/) !== null) {//设置为role=debug的标签，删掉
        if (!addedTohtml) {//最后一个link标签
            console.info('#green{[pack css files]}:');
            var mincss = new cleancss().minify(allCssCode);
            mincss = mincss.styles || mincss;//兼容新旧版本的cleancss的minify接口
            md5 = crypto.createHash('md5');
            var cssMd5 = md5.update(mincss)
                .digest('hex')
                .substring(0, 6);
            fs.writeFileSync(path.resolve(cwd, './__publish__/' + projectRoot + '/styles/' + pageName + '_' + cssMd5 + '.css'), mincss);
            allCss.forEach(function (val) {
                console.log(val.match(/(?:\shref\s*=\s*)(['"]?)([^'"\s]*)\1/)[2]);
            });
            console.info('#green{[pack css files done.]}\n');
            addedTohtml = true;
            return '<link rel="stylesheet" href="' + baseurl + '/styles/' + pageName + '_' + cssMd5 + '.css"/>';
        } else {
            return '';
        }
    }
    return m;
};<|endoftext|>