<commit_before>
'use strict';

var big = require('./bigdecimal.js');

var BIG255 = new big.BigInteger('255');
var ZERO = new big.BigInteger('0');
var ONE = new big.BigInteger('1');

// Data parser and serializer

function State(buffer) {
    // contains state of the buffer (i.e., buffer and offset)

    var offset = 0;

    this.readByte = function() {
        var c = buffer.readUInt8(offset);
        offset += 1;
        return c;
    }

    this.peekByte = function() {
        return buffer.readUInt8(offset);
    }

    this.writeByte = function(x) {
        buffer.writeUInt8(x, offset);
        offset += 1;
    }

    this.readInt = function() {
        var i = buffer.readUInt32BE(offset);
        offset += 4;
        return i;
    }

    this.writeInt = function(x) {
        buffer.writeUInt32BE(x, offset);
        offset += 4;
    }

    this.readBytes = function(n) {
        var bytes = buffer.slice(offset, offset + n);
        offset += n;
        return bytes;
    }

    this.writeBytes = function(x) {
        x.copy(buffer, offset);
        offset += x.length;
    }

    this.eof = function() {
        return (offset == buffer.length);
    }
}

function is_string(v) { return (typeof v === 'string'); }
function is_array(v) { return (v.constructor.name === 'Array'); }
function is_bigint(v) { return (!!v.divideAndRemainder); }

function raw_bytes(v) {
    var bytes = [];
    while(v.signum() != 0) {
        bytes.push(v.and(BIG255).intValue());
        v = v.shiftRight(8);
    }
    return bytes;
}

function mpint_to_bytes(sign, v) {
    if (sign == 0)
        return [];
    if (sign == 1) {
        var bytes = raw_bytes(v);
        if (bytes[bytes.length - 1] & 0x80)
            bytes.push(0x00);
        return bytes;
    } else {
        var bits = v.bitLength();
        var bytes = (bits >> 3) + (bits % 8 != 0);
        var mask = ONE.shiftLeft(bytes * 8).subtract(ONE);
        var repr = mask.xor(v).add(ONE);
        var bytes = raw_bytes(repr);
        if ((bytes[bytes.length - 1] & 0x80) == 0)
            bytes.push(0xff);
        return bytes;
    }
}

function to_mpint(v, base) {
    if (!is_bigint(v)) { // detect if v is already BigInteger
        if (!base) base = 10;
        v = new big.BigInteger(v.toString(), base);
    }
    return v;
}

function to_buffer(v) {
    if (is_string(v) || is_array(v))
        v = new Buffer(v);
    return v;
}

function type(klass) {
    var x = function(value, option) {
        return { 'klass': klass, 'value': value, 'option': option }
    }
    x.klass = klass;
    return x;
}

/*
    Serializing protocol is as follows:
        1. 'flatten' is called to optionally change the input to internal representation.
            Further on, this value is passed to 'size' or 'serialize'
        2. 'size' is called for every element and it should return a size in bytes
            of this object.
        3. Buffer is created to hold everything.
        4. 'serialize' is called for every object and it should serialize itself.
    Parsing is easier:
        1. 'parse' method is called for every object in turn.
            It should parse itself and return itself.
 */

var Byte = {
    flatten : null,
    size : function() { return 1; },
    serialize : function(v, state) { state.writeByte(v); },
    parse : function(state) { return state.readByte(); }
}

var Bytes = {
    flatten : to_buffer,
    size : function(v) { return v.length; },
    serialize : function(v, state) { state.writeBytes(v); },
    parse : function(state, n) { return state.readBytes(n); }
}

var Bool = {
    flatten : function(v) { return (!!v); },
    size : function() { return 1; },
    serialize : function(v, state) { state.writeByte(v ? 0x01 : 0x00); },
    parse : function(state) { return (state.readByte() != 0x00); }
}

var Uint32 = {
    flatten : null,
    size : function() { return 4; },
    serialize : function(v, state) {
        if (v < 0 || v > 0xffffffff)
            throw 'Invalid uint32';
        state.writeInt(v);
    },
    parse : function(state) { return state.readInt(); }
}

var Uint64 = {
    flatten : to_mpint,
    size : function() { return 8; },
    serialize : function(v, state) {
        if (v.signum() == -1 || v.bitLength() > 64)
            throw 'Invalid uint64';
        var bytes = raw_bytes(v);
        while (bytes.length != 8) bytes.push(0x00);
        bytes.reverse();
        return state.writeBytes(new Buffer(bytes));
    },
    parse : function(state) {
        var h = big.BigInteger.valueOf(state.readInt());
        var l = big.BigInteger.valueOf(state.readInt());
        return h.shiftLeft(32).or(l);
    }
}

var Str = {
    flatten : to_buffer,
    size : function(v) { return 4 + v.length; },
    serialize : function(v, state) {
        state.writeInt(v.length);
        state.writeBytes(v);
    },
    parse : function(state) {
        var n = state.readInt();
        return state.readBytes(n); // TODO
    }
}

var Utf8 = {
    flatten : function(v) { return new Buffer(v, 'utf8'); },
    size : Str.size,
    serialize : Str.serialize,
    parse : function(state) {
        var s = Str.parse(state);
        return s.toString('utf8');
    }
}

var Mpint = {
    flatten : function(v, base) {
        v = to_mpint(v, base);
        var sign = v.signum();
        if (sign == -1)
            v = v.negate();
        return [ sign, v ];
    },
    size : function(v) {
        var sign = v[0];
        v = v[1];
        if (sign == 0)
            return 4;
        var bits = v.bitLength();
        if (sign == 1)
            return (bits >> 3) + 1 + 4;
        // sign == -1
        if (bits % 8 != 0) {
            return (bits >> 3) + 1 + 4;
        } else {
            if (v.bitCount() == 1) // power of 2
                return (bits >> 3) + 4;
            else
                return (bits >> 3) + 1 + 4;
        }
    },
    serialize : function(v, state) {
        var bytes = mpint_to_bytes(v[0], v[1]);
        bytes.reverse(); // LSB => MSB
        return Str.serialize(Str.flatten(bytes), state);
    },
    parse : function(state) {
        var n = state.readInt();
        if (n == 0)
            return ZERO;
        var sign = (state.peekByte() & 0x80) != 0;
        var x = ZERO;
        // take integers
        for (var i = 0; i < (n >> 2); i++) {
            var u = state.readInt();
            x = x.shiftLeft(32).or(big.BigInteger.valueOf(u));
        }
        // take remaining bytes
        for (var i = 0; i < (n % 4); i++) {
            var b = state.readByte();
            x = x.shiftLeft(8).or(big.BigInteger.valueOf(b))
        }
        if (sign) {
            // we have to flip it and add 1
            var mask = ONE.shiftLeft(n * 8).subtract(ONE);
            x = x.xor(mask).add(ONE).negate();
        }
        return x;
    }
}

var Namelist = {
    flatten : function(v) {
        if (is_array(v))
            v = v.join(',');
        return v;
    },
    size : Str.size,
    serialize : Str.serialize,
    parse : function(state) {

    }
}

/* Public interface */

function serialize() {
    // used to write SSH data to a buffer
    // 1. Compute length.
    var size = 0;
    var args = [];
    for (var x in arguments) {
        var it = arguments[x];
        if (it.klass.flatten !== null)
            it.value = it.klass.flatten(it.value, it.option);
        size += it.klass.size(it.value);
    }
    var buffer = new Buffer(size);
    var state = new State(buffer);
    // 2. Serialize.
    for (var x in arguments) {
        var it = arguments[x];
        it.klass.serialize(it.value, state);
    }
    if (!state.eof())
        throw 'Fatal error (eof not reached)';
    return buffer;
}

function parse_array(buffer, spec) {
    var state = new State(buffer);
    var values = [];
    for (var i in spec) {
        var el = spec[i];
        var v = el.klass.parse(state, el.value);
        values.push(v);
    }
    return values;
}

function parse_object(buffer, spec) {
    var state = new State(buffer);
    var values = {};
    for (var key in spec) {
        var el = spec[key];
        values[key] = el.klass.parse(state, el.value);
    }
    return values;
}

function parse() {
    var buffer = arguments[0];
    var args = Array.prototype.slice.call(arguments, 1);
    if (args.length == 0)
        return [];
    var first = args[0];
    if (args.length > 1 || (args.length == 1 && !is_array(first)))
        return parse_array(buffer, args);
    return (is_array(first) ? parse_array(buffer, first) : parse_object(buffer, first));
}

function hexize() {
    return serialize.apply(this, arguments).toString('hex');
}

function repr(x) {
    var type = x.constructor.name;
    if (is_array(x)) {
        var s = x.map(repr).join(', ');
        return '[ ' + s + ' ]';
    }
    else if (is_bigint(x)) {
        return "mpint(" + x.toString() + ")";
    }
    else if (is_string(x)) {
        return '"' + x + '"';
    }
    else if (type === "Buffer") {
        return "Buffer(0x" + x.toString('hex') + ")";
    }
    else if (type === "Object") {
        var items = [];
        for(var key in x) {
            items.push(key + ": " + repr(x[key]));
        }
        return "{ " + items.join(", ") + " }";
    }
    return x.toString();
}

/* Exports */

exports.byte = type(Byte);
exports.bytes = type(Bytes);
exports.boolean = type(Bool);
exports.uint32 = type(Uint32);
exports.uint64 = type(Uint64);
exports.string = type(Str);
exports.utf8 = type(Utf8); /* like string, but works with UTF-8 */
exports.mpint = type(Mpint);
exports.namelist = type(Namelist);

exports.serialize = serialize;
exports.hexize = hexize;
exports.parse_array = parse_array;
exports.parse_object = parse_object;
exports.parse = parse;
exports.repr = repr;
exports.show = function(x) {
    console.log(repr(x));
}
<commit_msg>stupid me removed stupid function<commit_after>
'use strict';

var big = require('./bigdecimal.js');

var BIG255 = new big.BigInteger('255');
var ZERO = new big.BigInteger('0');
var ONE = new big.BigInteger('1');

// Data parser and serializer

function State(buffer) {
    // contains state of the buffer (i.e., buffer and offset)

    var offset = 0;

    this.readByte = function() {
        var c = buffer.readUInt8(offset);
        offset += 1;
        return c;
    }

    this.peekByte = function() {
        return buffer.readUInt8(offset);
    }

    this.writeByte = function(x) {
        buffer.writeUInt8(x, offset);
        offset += 1;
    }

    this.readInt = function() {
        var i = buffer.readUInt32BE(offset);
        offset += 4;
        return i;
    }

    this.writeInt = function(x) {
        buffer.writeUInt32BE(x, offset);
        offset += 4;
    }

    this.readBytes = function(n) {
        var bytes = buffer.slice(offset, offset + n);
        offset += n;
        return bytes;
    }

    this.writeBytes = function(x) {
        x.copy(buffer, offset);
        offset += x.length;
    }

    this.eof = function() {
        return (offset == buffer.length);
    }
}

function is_string(v) { return (typeof v === 'string'); }
function is_array(v) { return (v.constructor.name === 'Array'); }
function is_bigint(v) { return (!!v.divideAndRemainder); }

function raw_bytes(v) {
    var bytes = [];
    while(v.signum() != 0) {
        bytes.push(v.and(BIG255).intValue());
        v = v.shiftRight(8);
    }
    return bytes;
}

function mpint_to_bytes(sign, v) {
    if (sign == 0)
        return [];
    if (sign == 1) {
        var bytes = raw_bytes(v);
        if (bytes[bytes.length - 1] & 0x80)
            bytes.push(0x00);
        return bytes;
    } else {
        var bits = v.bitLength();
        var bytes = (bits >> 3) + (bits % 8 != 0);
        var mask = ONE.shiftLeft(bytes * 8).subtract(ONE);
        var repr = mask.xor(v).add(ONE);
        var bytes = raw_bytes(repr);
        if ((bytes[bytes.length - 1] & 0x80) == 0)
            bytes.push(0xff);
        return bytes;
    }
}

function to_mpint(v, base) {
    if (!is_bigint(v)) { // detect if v is already BigInteger
        if (!base) base = 10;
        v = new big.BigInteger(v.toString(), base);
    }
    return v;
}

function to_buffer(v) {
    if (is_string(v) || is_array(v))
        v = new Buffer(v);
    return v;
}

function type(klass) {
    var x = function(value, option) {
        return { 'klass': klass, 'value': value, 'option': option }
    }
    x.klass = klass;
    return x;
}

/*
    Serializing protocol is as follows:
        1. 'flatten' is called to optionally change the input to internal representation.
            Further on, this value is passed to 'size' or 'serialize'
        2. 'size' is called for every element and it should return a size in bytes
            of this object.
        3. Buffer is created to hold everything.
        4. 'serialize' is called for every object and it should serialize itself.
    Parsing is easier:
        1. 'parse' method is called for every object in turn.
            It should parse itself and return itself.
 */

var Byte = {
    flatten : null,
    size : function() { return 1; },
    serialize : function(v, state) { state.writeByte(v); },
    parse : function(state) { return state.readByte(); }
}

var Bytes = {
    flatten : to_buffer,
    size : function(v) { return v.length; },
    serialize : function(v, state) { state.writeBytes(v); },
    parse : function(state, n) { return state.readBytes(n); }
}

var Bool = {
    flatten : function(v) { return (!!v); },
    size : function() { return 1; },
    serialize : function(v, state) { state.writeByte(v ? 0x01 : 0x00); },
    parse : function(state) { return (state.readByte() != 0x00); }
}

var Uint32 = {
    flatten : null,
    size : function() { return 4; },
    serialize : function(v, state) {
        if (v < 0 || v > 0xffffffff)
            throw 'Invalid uint32';
        state.writeInt(v);
    },
    parse : function(state) { return state.readInt(); }
}

var Uint64 = {
    flatten : to_mpint,
    size : function() { return 8; },
    serialize : function(v, state) {
        if (v.signum() == -1 || v.bitLength() > 64)
            throw 'Invalid uint64';
        var bytes = raw_bytes(v);
        while (bytes.length != 8) bytes.push(0x00);
        bytes.reverse();
        return state.writeBytes(new Buffer(bytes));
    },
    parse : function(state) {
        var h = big.BigInteger.valueOf(state.readInt());
        var l = big.BigInteger.valueOf(state.readInt());
        return h.shiftLeft(32).or(l);
    }
}

var Str = {
    flatten : to_buffer,
    size : function(v) { return 4 + v.length; },
    serialize : function(v, state) {
        state.writeInt(v.length);
        state.writeBytes(v);
    },
    parse : function(state) {
        var n = state.readInt();
        return state.readBytes(n); // TODO
    }
}

var Utf8 = {
    flatten : function(v) { return new Buffer(v, 'utf8'); },
    size : Str.size,
    serialize : Str.serialize,
    parse : function(state) {
        var s = Str.parse(state);
        return s.toString('utf8');
    }
}

var Mpint = {
    flatten : function(v, base) {
        v = to_mpint(v, base);
        var sign = v.signum();
        if (sign == -1)
            v = v.negate();
        return [ sign, v ];
    },
    size : function(v) {
        var sign = v[0];
        v = v[1];
        if (sign == 0)
            return 4;
        var bits = v.bitLength();
        if (sign == 1)
            return (bits >> 3) + 1 + 4;
        // sign == -1
        if (bits % 8 != 0) {
            return (bits >> 3) + 1 + 4;
        } else {
            if (v.bitCount() == 1) // power of 2
                return (bits >> 3) + 4;
            else
                return (bits >> 3) + 1 + 4;
        }
    },
    serialize : function(v, state) {
        var bytes = mpint_to_bytes(v[0], v[1]);
        bytes.reverse(); // LSB => MSB
        return Str.serialize(Str.flatten(bytes), state);
    },
    parse : function(state) {
        var n = state.readInt();
        if (n == 0)
            return ZERO;
        var sign = (state.peekByte() & 0x80) != 0;
        var x = ZERO;
        // take integers
        for (var i = 0; i < (n >> 2); i++) {
            var u = state.readInt();
            x = x.shiftLeft(32).or(big.BigInteger.valueOf(u));
        }
        // take remaining bytes
        for (var i = 0; i < (n % 4); i++) {
            var b = state.readByte();
            x = x.shiftLeft(8).or(big.BigInteger.valueOf(b))
        }
        if (sign) {
            // we have to flip it and add 1
            var mask = ONE.shiftLeft(n * 8).subtract(ONE);
            x = x.xor(mask).add(ONE).negate();
        }
        return x;
    }
}

var Namelist = {
    flatten : function(v) {
        if (is_array(v))
            v = v.join(',');
        return v;
    },
    size : Str.size,
    serialize : Str.serialize,
    parse : function(state) {

    }
}

/* Public interface */

function serialize() {
    // used to write SSH data to a buffer
    // 1. Compute length.
    var size = 0;
    var args = [];
    for (var x in arguments) {
        var it = arguments[x];
        if (it.klass.flatten !== null)
            it.value = it.klass.flatten(it.value, it.option);
        size += it.klass.size(it.value);
    }
    var buffer = new Buffer(size);
    var state = new State(buffer);
    // 2. Serialize.
    for (var x in arguments) {
        var it = arguments[x];
        it.klass.serialize(it.value, state);
    }
    if (!state.eof())
        throw 'Fatal error (eof not reached)';
    return buffer;
}

function parse_array(buffer, spec) {
    var state = new State(buffer);
    var values = [];
    for (var i in spec) {
        var el = spec[i];
        var v = el.klass.parse(state, el.value);
        values.push(v);
    }
    return values;
}

function parse() {
    var buffer = arguments[0];
    var args = Array.prototype.slice.call(arguments, 1);
    if (args.length == 0)
        return [];
    var first = args[0];
    if (args.length > 1 || (args.length == 1 && !is_array(first)))
        return parse_array(buffer, args);
    return parse_array(buffer, first);
}

function hexize() {
    return serialize.apply(this, arguments).toString('hex');
}

function repr(x) {
    var type = x.constructor.name;
    if (is_array(x)) {
        var s = x.map(repr).join(', ');
        return '[ ' + s + ' ]';
    }
    else if (is_bigint(x)) {
        return "mpint(" + x.toString() + ")";
    }
    else if (is_string(x)) {
        return '"' + x + '"';
    }
    else if (type === "Buffer") {
        return "Buffer(0x" + x.toString('hex') + ")";
    }
    else if (type === "Object") {
        var items = [];
        for(var key in x) {
            items.push(key + ": " + repr(x[key]));
        }
        return "{ " + items.join(", ") + " }";
    }
    return x.toString();
}

/* Exports */

exports.byte = type(Byte);
exports.bytes = type(Bytes);
exports.boolean = type(Bool);
exports.uint32 = type(Uint32);
exports.uint64 = type(Uint64);
exports.string = type(Str);
exports.utf8 = type(Utf8); /* like string, but works with UTF-8 */
exports.mpint = type(Mpint);
exports.namelist = type(Namelist);

exports.serialize = serialize;
exports.hexize = hexize;
exports.parse_array = parse_array;
exports.parse = parse;
exports.repr = repr;
exports.show = function(x) {
    console.log(repr(x));
}
<|endoftext|>


<commit_before>var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
	rmultiDash = /([A-Z])/g;

function internalData( elem, name, data, pvt /* Internal Use Only */ ){
	if ( !jQuery.acceptData( elem ) ) {
		return;
	}

	var thisCache, ret,
		internalKey = jQuery.expando,
		getByName = typeof name === "string",

		// We have to handle DOM nodes and JS objects differently because IE6-7
		// can't GC object references properly across the DOM-JS boundary
		isNode = elem.nodeType,

		// Only DOM nodes need the global jQuery cache; JS object data is
		// attached directly to the object so GC can occur automatically
		cache = isNode ? jQuery.cache : elem,

		// Only defining an ID for JS objects if its cache already exists allows
		// the code to shortcut on the same path as a DOM node with no cache
		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;

	// Avoid doing any more work than we need to when trying to get data on an
	// object that has no data at all
	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
		return;
	}

	if ( !id ) {
		// Only DOM nodes need a new unique ID for each element since their data
		// ends up in the global cache
		if ( isNode ) {
			elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
		} else {
			id = internalKey;
		}
	}

	if ( !cache[ id ] ) {
		cache[ id ] = {};

		// Avoids exposing jQuery metadata on plain JS objects when the object
		// is serialized using JSON.stringify
		if ( !isNode ) {
			cache[ id ].toJSON = jQuery.noop;
		}
	}

	// An object can be passed to jQuery.data instead of a key/value pair; this gets
	// shallow copied over onto the existing cache
	if ( typeof name === "object" || typeof name === "function" ) {
		if ( pvt ) {
			cache[ id ] = jQuery.extend( cache[ id ], name );
		} else {
			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
		}
	}

	thisCache = cache[ id ];

	// jQuery data() is stored in a separate object inside the object's internal data
	// cache in order to avoid key collisions between internal data and user-defined
	// data.
	if ( !pvt ) {
		if ( !thisCache.data ) {
			thisCache.data = {};
		}

		thisCache = thisCache.data;
	}

	if ( data !== undefined ) {
		thisCache[ jQuery.camelCase( name ) ] = data;
	}

	// Check for both converted-to-camel and non-converted data property names
	// If a data property was specified
	if ( getByName ) {

		// First Try to find as-is property data
		ret = thisCache[ name ];

		// Test for null|undefined property data
		if ( ret == null ) {

			// Try to find the camelCased property
			ret = thisCache[ jQuery.camelCase( name ) ];
		}
	} else {
		ret = thisCache;
	}

	return ret;
}

function internalRemoveData( elem, name, pvt /* For internal use only */ ){
	if ( !jQuery.acceptData( elem ) ) {
		return;
	}

	var thisCache, i, l,

		isNode = elem.nodeType,

		// See jQuery.data for more information
		cache = isNode ? jQuery.cache : elem,
		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;

	// If there is already no cache entry for this object, there is no
	// purpose in continuing
	if ( !cache[ id ] ) {
		return;
	}

	if ( name ) {

		thisCache = pvt ? cache[ id ] : cache[ id ].data;

		if ( thisCache ) {

			// Support array or space separated string names for data keys
			if ( !jQuery.isArray( name ) ) {

				// try the string as a key before any manipulation
				if ( name in thisCache ) {
					name = [ name ];
				} else {

					// split the camel cased version by spaces unless a key with the spaces exists
					name = jQuery.camelCase( name );
					if ( name in thisCache ) {
						name = [ name ];
					} else {
						name = name.split(" ");
					}
				}
			}

			for ( i = 0, l = name.length; i < l; i++ ) {
				delete thisCache[ name[i] ];
			}

			// If there is no data left in the cache, we want to continue
			// and let the cache object itself get destroyed
			if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
				return;
			}
		}
	}

	// See jQuery.data for more information
	if ( !pvt ) {
		delete cache[ id ].data;

		// Don't destroy the parent cache unless the internal data object
		// had been the only thing left in it
		if ( !isEmptyDataObject( cache[ id ] ) ) {
			return;
		}
	}

	// Destroy the cache
	if ( isNode ) {
		jQuery.cleanData( [ elem ], true );

	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
	} else if ( jQuery.support.deleteExpando || cache != cache.window ) {
		delete cache[ id ];

	// When all else fails, null
	} else {
		cache[ id ] = null;
	}
}

jQuery.extend({
	cache: {},

	deletedIds: [],

	// Remove at next major release (1.9/2.0)
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data ) {
		return internalData( elem, name, data, false );
	},

	removeData: function( elem, name ) {
		return internalRemoveData( elem, name, false );
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return internalData( elem, name, data, true );
	},

	_removeData: function( elem, name ) {
		return internalRemoveData( elem, name, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];

		// nodes accept data unless otherwise specified; rejection can be conditional
		return !noData || noData !== true && elem.getAttribute("classid") === noData;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, part, attr, name, l,
			elem = this[0],
			i = 0,
			data = null;

		// Gets all values
		if ( key === undefined ) {
			if ( this.length ) {
				data = jQuery.data( elem );

				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
					attr = elem.attributes;
					for ( l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( !name.indexOf( "data-" ) ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( elem, name, data[ name ] );
						}
					}
					jQuery._data( elem, "parsedAttrs", true );
				}
			}

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split( ".", 2 );
		parts[1] = parts[1] ? "." + parts[1] : "";
		part = parts[1] + "!";

		return jQuery.access( this, function( value ) {

			if ( value === undefined ) {
				data = this.triggerHandler( "getData" + part, [ parts[0] ] );

				// Try to fetch any internally stored data first
				if ( data === undefined && elem ) {
					data = jQuery.data( elem, key );
					data = dataAttr( elem, key, data );
				}

				return data === undefined && parts[1] ?
					this.data( parts[0] ) :
					data;
			}

			parts[1] = value;
			this.each(function() {
				var self = jQuery( this );

				self.triggerHandler( "setData" + part, parts );
				jQuery.data( this, key, value );
				self.triggerHandler( "changeData" + part, parts );
			});
		}, null, value, arguments.length > 1, null, false );
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				// Only convert to a number if it doesn't change the string
				+data + "" === data ? +data :
				rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	var name;
	for ( name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}
<commit_msg>Remove deprecated $.uuid and dunseled $.deletedIds.<commit_after>var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
	rmultiDash = /([A-Z])/g;

function internalData( elem, name, data, pvt /* Internal Use Only */ ){
	if ( !jQuery.acceptData( elem ) ) {
		return;
	}

	var thisCache, ret,
		internalKey = jQuery.expando,
		getByName = typeof name === "string",

		// We have to handle DOM nodes and JS objects differently because IE6-7
		// can't GC object references properly across the DOM-JS boundary
		isNode = elem.nodeType,

		// Only DOM nodes need the global jQuery cache; JS object data is
		// attached directly to the object so GC can occur automatically
		cache = isNode ? jQuery.cache : elem,

		// Only defining an ID for JS objects if its cache already exists allows
		// the code to shortcut on the same path as a DOM node with no cache
		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;

	// Avoid doing any more work than we need to when trying to get data on an
	// object that has no data at all
	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
		return;
	}

	if ( !id ) {
		// Only DOM nodes need a new unique ID for each element since their data
		// ends up in the global cache
		if ( isNode ) {
			elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
		} else {
			id = internalKey;
		}
	}

	if ( !cache[ id ] ) {
		cache[ id ] = {};

		// Avoids exposing jQuery metadata on plain JS objects when the object
		// is serialized using JSON.stringify
		if ( !isNode ) {
			cache[ id ].toJSON = jQuery.noop;
		}
	}

	// An object can be passed to jQuery.data instead of a key/value pair; this gets
	// shallow copied over onto the existing cache
	if ( typeof name === "object" || typeof name === "function" ) {
		if ( pvt ) {
			cache[ id ] = jQuery.extend( cache[ id ], name );
		} else {
			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
		}
	}

	thisCache = cache[ id ];

	// jQuery data() is stored in a separate object inside the object's internal data
	// cache in order to avoid key collisions between internal data and user-defined
	// data.
	if ( !pvt ) {
		if ( !thisCache.data ) {
			thisCache.data = {};
		}

		thisCache = thisCache.data;
	}

	if ( data !== undefined ) {
		thisCache[ jQuery.camelCase( name ) ] = data;
	}

	// Check for both converted-to-camel and non-converted data property names
	// If a data property was specified
	if ( getByName ) {

		// First Try to find as-is property data
		ret = thisCache[ name ];

		// Test for null|undefined property data
		if ( ret == null ) {

			// Try to find the camelCased property
			ret = thisCache[ jQuery.camelCase( name ) ];
		}
	} else {
		ret = thisCache;
	}

	return ret;
}

function internalRemoveData( elem, name, pvt /* For internal use only */ ){
	if ( !jQuery.acceptData( elem ) ) {
		return;
	}

	var thisCache, i, l,

		isNode = elem.nodeType,

		// See jQuery.data for more information
		cache = isNode ? jQuery.cache : elem,
		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;

	// If there is already no cache entry for this object, there is no
	// purpose in continuing
	if ( !cache[ id ] ) {
		return;
	}

	if ( name ) {

		thisCache = pvt ? cache[ id ] : cache[ id ].data;

		if ( thisCache ) {

			// Support array or space separated string names for data keys
			if ( !jQuery.isArray( name ) ) {

				// try the string as a key before any manipulation
				if ( name in thisCache ) {
					name = [ name ];
				} else {

					// split the camel cased version by spaces unless a key with the spaces exists
					name = jQuery.camelCase( name );
					if ( name in thisCache ) {
						name = [ name ];
					} else {
						name = name.split(" ");
					}
				}
			}

			for ( i = 0, l = name.length; i < l; i++ ) {
				delete thisCache[ name[i] ];
			}

			// If there is no data left in the cache, we want to continue
			// and let the cache object itself get destroyed
			if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
				return;
			}
		}
	}

	// See jQuery.data for more information
	if ( !pvt ) {
		delete cache[ id ].data;

		// Don't destroy the parent cache unless the internal data object
		// had been the only thing left in it
		if ( !isEmptyDataObject( cache[ id ] ) ) {
			return;
		}
	}

	// Destroy the cache
	if ( isNode ) {
		jQuery.cleanData( [ elem ], true );

	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
	} else if ( jQuery.support.deleteExpando || cache != cache.window ) {
		delete cache[ id ];

	// When all else fails, null
	} else {
		cache[ id ] = null;
	}
}

jQuery.extend({
	cache: {},

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data ) {
		return internalData( elem, name, data, false );
	},

	removeData: function( elem, name ) {
		return internalRemoveData( elem, name, false );
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return internalData( elem, name, data, true );
	},

	_removeData: function( elem, name ) {
		return internalRemoveData( elem, name, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];

		// nodes accept data unless otherwise specified; rejection can be conditional
		return !noData || noData !== true && elem.getAttribute("classid") === noData;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, part, attr, name, l,
			elem = this[0],
			i = 0,
			data = null;

		// Gets all values
		if ( key === undefined ) {
			if ( this.length ) {
				data = jQuery.data( elem );

				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
					attr = elem.attributes;
					for ( l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( !name.indexOf( "data-" ) ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( elem, name, data[ name ] );
						}
					}
					jQuery._data( elem, "parsedAttrs", true );
				}
			}

			return data;
		}

		// Sets multiple values
		if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split( ".", 2 );
		parts[1] = parts[1] ? "." + parts[1] : "";
		part = parts[1] + "!";

		return jQuery.access( this, function( value ) {

			if ( value === undefined ) {
				data = this.triggerHandler( "getData" + part, [ parts[0] ] );

				// Try to fetch any internally stored data first
				if ( data === undefined && elem ) {
					data = jQuery.data( elem, key );
					data = dataAttr( elem, key, data );
				}

				return data === undefined && parts[1] ?
					this.data( parts[0] ) :
					data;
			}

			parts[1] = value;
			this.each(function() {
				var self = jQuery( this );

				self.triggerHandler( "setData" + part, parts );
				jQuery.data( this, key, value );
				self.triggerHandler( "changeData" + part, parts );
			});
		}, null, value, arguments.length > 1, null, false );
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				// Only convert to a number if it doesn't change the string
				+data + "" === data ? +data :
				rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	var name;
	for ( name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}
<|endoftext|>


<commit_before>const cheerio = require('cheerio'),
    request = require('request');

exports.action = (msg, args) => {

    let embedObject = {}

    msg.channel.send('Fetching profile...')
        .then(msg2 => {
            request(`https://miiverse.nintendo.net/users/${args.split(' ')[0]}`, function(err, resp, html) {
                console.log(resp.statusCode)
                if (!err && resp.statusCode == 200) {
                    $ = cheerio.load(html);
                    let genres = $('.favorite-game-genre').children('.note').children('span').toArray();
                    let genreString;
                    if (genres.map(c => c.children[0].data).length > 0) {
                        genreString = genres.map(c => c.children[0].data).join(', ');
                    } else {
                        genreString = 'None';
                    }
                    let systems = $('.game').children('.note').children('div').toArray().map(c => c.children);
                    let systemArray = [];
                    for (system in systems) {
                        let sysName = systems[system].find(x => x.name == 'span').children[0].data;
                        if (sysName == 'System in the Nintendo 3DS Family') {
                            sysName = 'Nintendo 3DS';
                        }
                        systemArray.push(sysName);
                    }
                    embedObject = {
                        title: `${$('.id-name').text()} (${$('.nick-name').text()})`,
                        url: `https://miiverse.nintendo.net${$('.nick-name').attr('href')}`,
                        description: $('.js-truncated-text').text(),
                        color: 0x5ac800,
                        thumbnail: {
                            url: $('#sidebar-profile-body').children('.icon-container').children('a').children('.icon').attr('src')
                        },
                        fields: [{
                                name: 'Following',
                                value: $('.test-following-count').text(),
                                inline: true
                            },

                            {
                                name: 'Followers',
                                value: $('.test-follower-count').text(),
                                inline: true
                            },
                            {
                                name: 'Game Experience',
                                value: $('.test-game-skill').text(),
                                inline: true
                            },
                            {
                                name: 'Country',
                                value: $('.user-main-profile').children('.note').toArray()[0].children[0].data,
                                inline: true
                            },
                            {
                                name: genres.length > 1 ? 'Favourite Game Genres' : 'Favourite Game Genre',
                                value: genreString

                            },
                            {
                                name: 'Systems Owned',
                                value: systemArray.join(', ')
                            }
                        ]
                    }
                    msg2.channel.send('', { embed: embedObject });
                } else if (resp.statusCode == 404) {
                    setTimeout(function() {
                        msg2.channel.send('Couldn\'t find a profile with that username. Check your spelling and try again.');
                    }, 100);
                } else {
                    msg2.channel.send('Unknown error.');
                }
                msg2.delete();
            });
        });

}<commit_msg>Deprecate Miiverse command :c<commit_after>module.exports = { action: () => {} };

// This command is now deprecated, due to the shutdown of Miiverse.

/*const cheerio = require('cheerio'),
    request = require('request');

exports.action = (msg, args) => {

    let embedObject = {}

    msg.channel.send('Fetching profile...')
        .then(msg2 => {
            request(`https://miiverse.nintendo.net/users/${args.split(' ')[0]}`, function(err, resp, html) {
                console.log(resp.statusCode)
                if (!err && resp.statusCode == 200) {
                    $ = cheerio.load(html);
                    let genres = $('.favorite-game-genre').children('.note').children('span').toArray();
                    let genreString;
                    if (genres.map(c => c.children[0].data).length > 0) {
                        genreString = genres.map(c => c.children[0].data).join(', ');
                    } else {
                        genreString = 'None';
                    }
                    let systems = $('.game').children('.note').children('div').toArray().map(c => c.children);
                    let systemArray = [];
                    for (system in systems) {
                        let sysName = systems[system].find(x => x.name == 'span').children[0].data;
                        if (sysName == 'System in the Nintendo 3DS Family') {
                            sysName = 'Nintendo 3DS';
                        }
                        systemArray.push(sysName);
                    }
                    embedObject = {
                        title: `${$('.id-name').text()} (${$('.nick-name').text()})`,
                        url: `https://miiverse.nintendo.net${$('.nick-name').attr('href')}`,
                        description: $('.js-truncated-text').text(),
                        color: 0x5ac800,
                        thumbnail: {
                            url: $('#sidebar-profile-body').children('.icon-container').children('a').children('.icon').attr('src')
                        },
                        fields: [{
                                name: 'Following',
                                value: $('.test-following-count').text(),
                                inline: true
                            },

                            {
                                name: 'Followers',
                                value: $('.test-follower-count').text(),
                                inline: true
                            },
                            {
                                name: 'Game Experience',
                                value: $('.test-game-skill').text(),
                                inline: true
                            },
                            {
                                name: 'Country',
                                value: $('.user-main-profile').children('.note').toArray()[0].children[0].data,
                                inline: true
                            },
                            {
                                name: genres.length > 1 ? 'Favourite Game Genres' : 'Favourite Game Genre',
                                value: genreString

                            },
                            {
                                name: 'Systems Owned',
                                value: systemArray.join(', ')
                            }
                        ]
                    }
                    msg2.channel.send('', { embed: embedObject });
                } else if (resp.statusCode == 404) {
                    setTimeout(function() {
                        msg2.channel.send('Couldn\'t find a profile with that username. Check your spelling and try again.');
                    }, 100);
                } else {
                    msg2.channel.send('Unknown error.');
                }
                msg2.delete();
            });
        });

}*/<|endoftext|>


<commit_before>'use strict';

const regenerate = require('regenerate');
const whitespaceCodePoints = require('unicode-13.0.0/General_Category/Space_Separator/code-points.js');

const set = regenerate()
	.addRange(0x20, 0x7E) // printable ASCII symbols
	.remove('"')          // not `"`
	.remove('\'')         // not `'`
	.remove('\\')         // not `\`
	.remove('`');         // not '`'

const whitespace = regenerate(whitespaceCodePoints)
	.removeRange(0x00, 0x7F)
	.add(0x2028, 0x2029);

module.exports = {
	'whitelist': set.toString().slice(1, -1),
	'whitespace': whitespace.toString(),
	'version': require('../package.json').version
};
<commit_msg>Tweak whitespace script<commit_after>'use strict';

const regenerate = require('regenerate');

const set = regenerate()
	.addRange(0x20, 0x7E) // printable ASCII symbols
	.remove('"')          // not `"`
	.remove('\'')         // not `'`
	.remove('\\')         // not `\`
	.remove('`');         // not '`'

const whitespace = regenerate()
	.add(require('unicode-13.0.0/General_Category/Space_Separator/code-points.js'))
	.removeRange(0x20, 0x7E) // printable ASCII symbols
	.add(0x2028, 0x2029);

module.exports = {
	'whitelist': set.toString().slice(1, -1),
	'whitespace': whitespace.toString(),
	'version': require('../package.json').version
};
<|endoftext|>


<commit_before>var debug       = require('debug')('auth:data');
var Entity      = require('azure-entities');
var assert      = require('assert');
var _           = require('lodash');
var taskcluster = require('taskcluster-client');

var Client = Entity.configure({
  version:          1,
  partitionKey:     Entity.keys.StringKey('clientId'),
  rowKey:           Entity.keys.ConstantKey('client'),
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    details:        Entity.types.JSON
  }
}).configure({
  version:          2,
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    /**
     * Details object with properties:
     * - created          // Time when client was created
     * - lastModified     // Last time client was modified
     * - lastDateUsed     // Only updated if more than 6 hours out of date
     * - lastRotated      // Last time accessToken was reset
     * (more properties may be added in the future)
     */
    details:        Entity.types.JSON,
    scopes:         Entity.types.JSON,  // new in v2
    disabled:       Entity.types.Number // new in v2
  },
  migrate(item) {
    item.scopes = [];
    item.disabled = 0;
    return item;
  }
}).configure({
  version:          3,
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    /**
     * Details object with properties:
     * - created            // Time when client was created
     * - lastModified       // Last time client was modified
     * - lastDateUsed       // Only updated if more than 6 hours out of date
     * - lastRotated        // Last time accessToken was reset
     * - deleteOnExpiration // if true, can be deleted after expiration
     *                      // (new in v3)
     * (more properties may be added in the future)
     */
    details:        Entity.types.JSON,
    scopes:         Entity.types.JSON,
    disabled:       Entity.types.Number
  },
  migrate(item) {
    item.details = _.defaults({}, item.details, {deleteOnExpiration: false});
    return item;
  }
});

/** Get scopes granted to this client */
Client.prototype.expandedScopes = function(resolver) {
  return resolver.resolve(this.scopes);
};

/** Get JSON representation of client */
Client.prototype.json = function(resolver) {
  return {
    clientId:           this.clientId,
    description:        this.description,
    expires:            this.expires.toJSON(),
    created:            this.details.created,
    lastModified:       this.details.lastModified,
    lastDateUsed:       this.details.lastDateUsed,
    lastRotated:        this.details.lastRotated,
    deleteOnExpiration: this.details.deleteOnExpiration,
    scopes:             this.scopes,
    expandedScopes:     this.expandedScopes(resolver),
    disabled:           !!this.disabled
  };
};

/**
 * Ensure root client exists and has the given accessToken.
 *
 * Should only be called if the app is configured with a rootAccessToken.
 * Otherwise, app should assume whatever is in the table storage is the
 * root access token, and that appropriate role is attached.
 */
Client.ensureRootClient = function(accessToken) {
  assert(typeof(accessToken) === 'string',
         "Expected accessToken to be a string");
  let Client = this;
  // Create client resolving conflicts by overwriting
  return Client.create({
    clientId:         'root',
    description:      "Automatically created `root` client with star scopes " +
                      "for bootstrapping API access",
    accessToken:      accessToken,
    expires:          taskcluster.fromNow('24 hours'),
    details: {
      created:        new Date().toJSON(),
      lastModified:   new Date().toJSON(),
      lastDateUsed:   new Date().toJSON(),
      lastRotated:    new Date().toJSON(),
      deleteOnExpiration: false,
    },
    scopes:           ['*'],
    disabled:         0,
  }, true);
};

/**
 * Delete all clients that expired before `now`, unless
 * details.deleteOnExpiration is false.
 */

Client.purgeExpired = async function(now = new Date()) {
  var count = 0;
  var expired = await this.scan({
    expires: Entity.op.lessThan(now),
  }, {
    limit: 100,
    handler: async client => {
      if (client.details.deleteOnExpiration) {
        count++;
        await client.remove(true);
      }
    },
  });

  return count;
};

// Export Client
exports.Client = Client;

var Role = Entity.configure({
  version:          1,
  partitionKey:     Entity.keys.StringKey('roleId'),
  rowKey:           Entity.keys.ConstantKey('role'),
  signEntities:     true,
  properties: {
    roleId:         Entity.types.String,
    description:    Entity.types.Text,
    scopes:         Entity.types.JSON,
    /**
     * Details object with properties:
     * - created
     * - lastModified
     * (more properties may be added in the future)
     */
    details:        Entity.types.JSON,
  }
});

/** Get JSON representation of a role */
Role.prototype.json = function(resolver) {
  let scopes = ['assume:' + this.roleId];
  if (this.roleId.endsWith('*')) {
    scopes = this.scopes;
  }
  return {
    roleId:         this.roleId,
    description:    this.description,
    created:        this.details.created,
    lastModified:   this.details.lastModified,
    scopes:         this.scopes,
    expandedScopes: resolver.resolve(scopes)
  };
};

// Export Role
exports.Role = Role;
<commit_msg>Use Entity.types.Schema to enforce details<commit_after>var debug       = require('debug')('auth:data');
var Entity      = require('azure-entities');
var assert      = require('assert');
var _           = require('lodash');
var taskcluster = require('taskcluster-client');

var Client = Entity.configure({
  version:          1,
  partitionKey:     Entity.keys.StringKey('clientId'),
  rowKey:           Entity.keys.ConstantKey('client'),
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    details:        Entity.types.JSON
  }
}).configure({
  version:          2,
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    /**
     * Details object with properties:
     * - created          // Time when client was created
     * - lastModified     // Last time client was modified
     * - lastDateUsed     // Only updated if more than 6 hours out of date
     * - lastRotated      // Last time accessToken was reset
     * (more properties may be added in the future)
     */
    details:        Entity.types.JSON,
    scopes:         Entity.types.JSON,  // new in v2
    disabled:       Entity.types.Number // new in v2
  },
  migrate(item) {
    item.scopes = [];
    item.disabled = 0;
    return item;
  }
}).configure({
  version:          3,
  signEntities:     true,
  properties: {
    clientId:       Entity.types.String,
    description:    Entity.types.Text,
    accessToken:    Entity.types.EncryptedText,
    expires:        Entity.types.Date,
    /**
     * Details object with properties:
     * - created            // Time when client was created
     * - lastModified       // Last time client was modified
     * - lastDateUsed       // Only updated if more than 6 hours out of date
     * - lastRotated        // Last time accessToken was reset
     * - deleteOnExpiration // if true, can be deleted after expiration
     *                      // (new in v3)
     * (more properties may be added in the future)
     */
    details:        Entity.types.Schema({
      type: 'object',
      properties: {
        created:            {type: 'string', format: 'date-time'},
        lastModified:       {type: 'string', format: 'date-time'},
        lastDataUsed:       {type: 'string', format: 'date-time'},
        lastRotated:        {type: 'string', format: 'date-time'},
        deleteOnExpiration: {type: 'boolean'},
      },
      required: [
        'created', 'lastModified', 'lastDataUsed', 'lastRotated',
        'deleteOnExpiration',
      ],
    }),
    scopes:         Entity.types.JSON,
    disabled:       Entity.types.Number
  },
  migrate(item) {
    item.details = _.defaults({}, item.details, {deleteOnExpiration: false});
    return item;
  }
});

/** Get scopes granted to this client */
Client.prototype.expandedScopes = function(resolver) {
  return resolver.resolve(this.scopes);
};

/** Get JSON representation of client */
Client.prototype.json = function(resolver) {
  return {
    clientId:           this.clientId,
    description:        this.description,
    expires:            this.expires.toJSON(),
    created:            this.details.created,
    lastModified:       this.details.lastModified,
    lastDateUsed:       this.details.lastDateUsed,
    lastRotated:        this.details.lastRotated,
    deleteOnExpiration: this.details.deleteOnExpiration,
    scopes:             this.scopes,
    expandedScopes:     this.expandedScopes(resolver),
    disabled:           !!this.disabled
  };
};

/**
 * Ensure root client exists and has the given accessToken.
 *
 * Should only be called if the app is configured with a rootAccessToken.
 * Otherwise, app should assume whatever is in the table storage is the
 * root access token, and that appropriate role is attached.
 */
Client.ensureRootClient = function(accessToken) {
  assert(typeof(accessToken) === 'string',
         "Expected accessToken to be a string");
  let Client = this;
  // Create client resolving conflicts by overwriting
  return Client.create({
    clientId:         'root',
    description:      "Automatically created `root` client with star scopes " +
                      "for bootstrapping API access",
    accessToken:      accessToken,
    expires:          taskcluster.fromNow('24 hours'),
    details: {
      created:        new Date().toJSON(),
      lastModified:   new Date().toJSON(),
      lastDateUsed:   new Date().toJSON(),
      lastRotated:    new Date().toJSON(),
      deleteOnExpiration: false,
    },
    scopes:           ['*'],
    disabled:         0,
  }, true);
};

/**
 * Delete all clients that expired before `now`, unless
 * details.deleteOnExpiration is false.
 */

Client.purgeExpired = async function(now = new Date()) {
  var count = 0;
  var expired = await this.scan({
    expires: Entity.op.lessThan(now),
  }, {
    limit: 100,
    handler: async client => {
      if (client.details.deleteOnExpiration) {
        count++;
        await client.remove(true);
      }
    },
  });

  return count;
};

// Export Client
exports.Client = Client;

var Role = Entity.configure({
  version:          1,
  partitionKey:     Entity.keys.StringKey('roleId'),
  rowKey:           Entity.keys.ConstantKey('role'),
  signEntities:     true,
  properties: {
    roleId:         Entity.types.String,
    description:    Entity.types.Text,
    scopes:         Entity.types.JSON,
    /**
     * Details object with properties:
     * - created
     * - lastModified
     * (more properties may be added in the future)
     */
    details:        Entity.types.JSON,
  }
});

/** Get JSON representation of a role */
Role.prototype.json = function(resolver) {
  let scopes = ['assume:' + this.roleId];
  if (this.roleId.endsWith('*')) {
    scopes = this.scopes;
  }
  return {
    roleId:         this.roleId,
    description:    this.description,
    created:        this.details.created,
    lastModified:   this.details.lastModified,
    scopes:         this.scopes,
    expandedScopes: resolver.resolve(scopes)
  };
};

// Export Role
exports.Role = Role;
<|endoftext|>


<commit_before>var ProcessRunner = require('../lib/process_runner')
var expect = require('chai').expect
var assert = require('chai').assert
var child_process = require('child_process')
var BufferStream = require('./support/buffer_stream')
var Launcher = require('../lib/launcher')
var bd = require('bodydouble')
var stub = bd.stub

describe('ProcessRunner', function(){
  var runner
  var launcher
  var settings
  var process

  describe('bare process', function(){

    beforeEach(function(){
      settings = { protocol: 'process' }
      process = FakeProcess()
      launcher = new Launcher('launcher', settings)
      launcher.process = process
      bd.stub(launcher, 'launch').delegatesTo(function(cb){
        cb(process)
      })
      runner = new ProcessRunner({
        launcher: launcher
      })
    })
    it('should not be tap', function(){
      expect(runner.isTap()).not.to.be.ok
    })
    it('should not have results', function(){
      expect(runner.hasResults()).not.to.be.ok
    })
    it('initially has 0 messages', function(){
      expect(runner.get('messages').length).to.equal(0)
    })
    it('hasMessages if messages has length > 0', function(){
      expect(runner.hasMessages()).not.to.be.ok
      runner.get('messages').push({})
      expect(runner.hasMessages()).to.be.ok
    })
    it('reads stdout into messages', function(){
      process.stdout.write('foobar')
      expect(runner.get('messages').length).to.equal(1)
      var message = runner.get('messages').at(0)
      expect(message.get('type')).to.equal('log')
      expect(message.get('text')).to.equal('foobar')
    })
    it('reads stderr into messages', function(){
      process.stderr.write('foobar')
      expect(runner.get('messages').length).to.equal(1)
      var message = runner.get('messages').at(0)
      expect(message.get('type')).to.equal('error')
      expect(message.get('text')).to.equal('foobar')
    })
    it('should have results object be undefined', function(){
      expect(runner.get('results')).to.equal(null)
    })
  })

  describe('tap', function(){
    beforeEach(function(){
      process = FakeProcess()
      launcher = new Launcher('launcher', { protocol: 'tap' })
      launcher.process = process
      bd.stub(launcher, 'launch').delegatesTo(function(cb){
        cb(process)
      })
      runner = new ProcessRunner({
        launcher: launcher
      })
    })
    it('should is tap', function(){
      expect(runner.isTap()).to.be.ok
    })
    it('should have results', function(){
      expect(runner.hasResults()).to.be.ok
    })
    it('should have a results object', function(){
      expect(runner.get('results')).not.to.equal(null)
    })
    it('reads tap', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'ok 1 hello() should be "hello world"',
        '# hello says hello to bob',
        'ok 2 hello(bob) should be "hello bob"',
        '',
        '1..2',
        '# tests 2',
        '# pass  2',
        '',
        '# ok'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        var total = results.get('total')
        var pass = results.get('passed')
        var fail = results.get('failed')
        expect(pass).to.equal(2)
        expect(total).to.equal(2)
        expect(fail).to.equal(0)
        var tests = results.get('tests')
        expect(tests.length).to.equal(2)
        expect(tests.at(0).get('name')).to.equal('hello() should be "hello world"')
        expect(tests.at(1).get('name')).to.equal('hello(bob) should be "hello bob"')
        done()
      }, 0)
    })
    it('read tap with failing test case', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'not ok 1 hello() should be "hello world"',
        '  ---',
        '    operator: equal',
        '    expected: "hell world"',
        '    actual:   "hello world"',
        '    at: Test._cb (/Users/david/git/testem/examples/tape_example/tests.js:6:7)',
        '  ...',
        '# hello says hello to bob',
        'ok 2 hello(bob) should be "hello bob"',
        ' ',
        '1..2',
        '# tests 2',
        '# pass  1',
        '# fail  1'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        var total = results.get('total')
        var pass = results.get('passed')
        var fail = results.get('failed')
        expect(pass).to.equal(1)
        expect(total).to.equal(2)
        expect(fail).to.equal(1)
        var tests = results.get('tests')
        expect(tests.length).to.equal(2)
        expect(tests.at(0).get('name')).to.equal('hello() should be "hello world"')
        expect(tests.at(1).get('name')).to.equal('hello(bob) should be "hello bob"')
        var failItems = tests.at(0).get('items')

        // this tests for case documented in <https://github.com/airportyh/testem/issues/291>
        expect(failItems[0].message).to.equal(null)
        expect(failItems[0].operator).to.equal('equal')
        expect(failItems[0].expected).to.equal('"hell world"')
        expect(failItems[0].actual).to.equal('"hello world"')
        expect(failItems[0].at).to.equal('Test._cb (/Users/david/git/testem/examples/tape_example/tests.js:6:7)')
        done()
      }, 0)
    })

    it('reads tape output with a stacktrace', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'ok 1 hello() should be "hello world"',
        '# hello says hello to bob',
        'not ok 2 Error: blah',
        '  ---',
        '    operator: error',
        '    expected: ',
        '    actual:   {}',
        '    stack:',
        '      Error: blah',
        '        at Test._cb (/Users/airportyh/Home/Code/testem/examples/tape_example/tests.js:11:11)',
        '        at Test.run (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:52:14)',
        '        at Test.<anonymous> (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/results.js:108:24)',
        '        at Test.g (events.js:175:14)',
        '        at Test.EventEmitter.emit (events.js:92:17)',
        '        at Test.end (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:85:27)',
        '        at Object._onImmediate (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:163:35)',
        '        at processImmediate [as _immediateCallback] (timers.js:330:15)',
        '  ...',
        '',
        '1..2',
        '# tests 2',
        '# pass  0',
        '# fail  2'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        expect(results.get('total')).to.equal(2)
        expect(results.get('passed')).to.equal(1)
        expect(results.get('failed')).to.equal(1)
        var tests = results.get('tests')
        var failingTest = tests.at(1)
        var failingItems = failingTest.get('items')
        var stack = failingItems[0].stack
        expect(typeof stack).to.equal('string')
        expect(stack).to.match(/Error\:/)
        done()
      }, 0)
    })

  })

})

function FakeProcess(){
  var p = bd.mock(child_process.exec(''))
  p.stdout = BufferStream()
  p.stderr = BufferStream()
  return p
}<commit_msg>Fixed test.<commit_after>var ProcessRunner = require('../lib/process_runner')
var expect = require('chai').expect
var assert = require('chai').assert
var child_process = require('child_process')
var BufferStream = require('./support/buffer_stream')
var Launcher = require('../lib/launcher')
var bd = require('bodydouble')
var stub = bd.stub

describe('ProcessRunner', function(){
  var runner
  var launcher
  var settings
  var process

  describe('bare process', function(){

    beforeEach(function(){
      settings = { protocol: 'process' }
      process = FakeProcess()
      launcher = new Launcher('launcher', settings)
      launcher.process = process
      bd.stub(launcher, 'launch').delegatesTo(function(cb){
        cb(process)
      })
      runner = new ProcessRunner({
        launcher: launcher
      })
    })
    it('should not be tap', function(){
      expect(runner.isTap()).not.to.be.ok
    })
    it('should not have results', function(){
      expect(runner.hasResults()).not.to.be.ok
    })
    it('initially has 0 messages', function(){
      expect(runner.get('messages').length).to.equal(0)
    })
    it('hasMessages if messages has length > 0', function(){
      expect(runner.hasMessages()).not.to.be.ok
      runner.get('messages').push({})
      expect(runner.hasMessages()).to.be.ok
    })
    it('reads stdout into messages', function(){
      process.stdout.write('foobar')
      expect(runner.get('messages').length).to.equal(1)
      var message = runner.get('messages').at(0)
      expect(message.get('type')).to.equal('log')
      expect(message.get('text')).to.equal('foobar')
    })
    it('reads stderr into messages', function(){
      process.stderr.write('foobar')
      expect(runner.get('messages').length).to.equal(1)
      var message = runner.get('messages').at(0)
      expect(message.get('type')).to.equal('error')
      expect(message.get('text')).to.equal('foobar')
    })
    it('should have results object be undefined', function(){
      expect(runner.get('results')).to.equal(null)
    })
  })

  describe('tap', function(){
    beforeEach(function(){
      process = FakeProcess()
      launcher = new Launcher('launcher', { protocol: 'tap' })
      launcher.process = process
      bd.stub(launcher, 'launch').delegatesTo(function(cb){
        cb(process)
      })
      runner = new ProcessRunner({
        launcher: launcher
      })
    })
    it('should is tap', function(){
      expect(runner.isTap()).to.be.ok
    })
    it('should have results', function(){
      expect(runner.hasResults()).to.be.ok
    })
    it('should have a results object', function(){
      expect(runner.get('results')).not.to.equal(null)
    })
    it('reads tap', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'ok 1 hello() should be "hello world"',
        '# hello says hello to bob',
        'ok 2 hello(bob) should be "hello bob"',
        '',
        '1..2',
        '# tests 2',
        '# pass  2',
        '',
        '# ok'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        var total = results.get('total')
        var pass = results.get('passed')
        var fail = results.get('failed')
        expect(pass).to.equal(2)
        expect(total).to.equal(2)
        expect(fail).to.equal(0)
        var tests = results.get('tests')
        expect(tests.length).to.equal(2)
        expect(tests.at(0).get('name')).to.equal('hello() should be "hello world"')
        expect(tests.at(1).get('name')).to.equal('hello(bob) should be "hello bob"')
        done()
      }, 0)
    })
    it('read tap with failing test case', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'not ok 1 hello() should be "hello world"',
        '  ---',
        '    operator: equal',
        '    expected: "hell world"',
        '    actual:   "hello world"',
        '    at: Test._cb (/Users/david/git/testem/examples/tape_example/tests.js:6:7)',
        '  ...',
        '# hello says hello to bob',
        'ok 2 hello(bob) should be "hello bob"',
        ' ',
        '1..2',
        '# tests 2',
        '# pass  1',
        '# fail  1'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        var total = results.get('total')
        var pass = results.get('passed')
        var fail = results.get('failed')
        expect(pass).to.equal(1)
        expect(total).to.equal(2)
        expect(fail).to.equal(1)
        var tests = results.get('tests')
        expect(tests.length).to.equal(2)
        expect(tests.at(0).get('name')).to.equal('hello() should be "hello world"')
        expect(tests.at(1).get('name')).to.equal('hello(bob) should be "hello bob"')
        var failItems = tests.at(0).get('items')

        // this tests for case documented in <https://github.com/airportyh/testem/issues/291>
        expect(!failItems[0].message).to.equal(true)
        expect(failItems[0].operator).to.equal('equal')
        expect(failItems[0].expected).to.equal('"hell world"')
        expect(failItems[0].actual).to.equal('"hello world"')
        expect(failItems[0].at).to.equal('Test._cb (/Users/david/git/testem/examples/tape_example/tests.js:6:7)')

        done()
      }, 0)
    })

    it('reads tape output with a stacktrace', function(done){
      var tap = [
        'TAP version 13',
        '# hello says hello',
        'ok 1 hello() should be "hello world"',
        '# hello says hello to bob',
        'not ok 2 Error: blah',
        '  ---',
        '    operator: error',
        '    expected: ',
        '    actual:   {}',
        '    stack:',
        '      Error: blah',
        '        at Test._cb (/Users/airportyh/Home/Code/testem/examples/tape_example/tests.js:11:11)',
        '        at Test.run (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:52:14)',
        '        at Test.<anonymous> (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/results.js:108:24)',
        '        at Test.g (events.js:175:14)',
        '        at Test.EventEmitter.emit (events.js:92:17)',
        '        at Test.end (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:85:27)',
        '        at Object._onImmediate (/Users/airportyh/Home/Code/testem/examples/tape_example/node_modules/tape/lib/test.js:163:35)',
        '        at processImmediate [as _immediateCallback] (timers.js:330:15)',
        '  ...',
        '',
        '1..2',
        '# tests 2',
        '# pass  0',
        '# fail  2'
      ].join('\n')
      process.stdout.end(tap)
      setTimeout(function(){
        var results = runner.get('results')
        expect(results.get('total')).to.equal(2)
        expect(results.get('passed')).to.equal(1)
        expect(results.get('failed')).to.equal(1)
        var tests = results.get('tests')
        var failingTest = tests.at(1)
        var failingItems = failingTest.get('items')
        var stack = failingItems[0].stack
        expect(typeof stack).to.equal('string')
        expect(stack).to.match(/Error\:/)
        done()
      }, 0)
    })

  })

})

function FakeProcess(){
  var p = bd.mock(child_process.exec(''))
  p.stdout = BufferStream()
  p.stderr = BufferStream()
  return p
}<|endoftext|>


<commit_before>const Command = require('../base/Command');

class Register extends Command {
    constructor(client) {
        super(client, {
            name: 'register',
            category: "SWGoH",
            aliases: ['reg']
        });
    }

    async run(client, message, [action, userID, allyCode, ...args], options) { // eslint-disable-line no-unused-vars
        const level = options.level;
        action = action.toLowerCase();
        const acts = ['add', 'update', 'remove'];
        if (!action || !acts.includes(action)) {
            return message.channel.send('You need to choose either `add`, `remove`, or `update`.');
        }
        if (!userID) {
            return message.channel.send(message.language.get('COMMAND_REGISTER_MISSING_ARGS'));
        } else {
            if (userID === 'me') {
                userID = message.author.id;
            } else if (client.isUserID(userID)) {
                userID = userID.replace(/[^\d]*/g, '');
                // If they are trying to add someone else and they don't have the right perms, stop em
                if (userID !== message.author.id) {
                    if (level < 3) {
                        return message.channel.send(message.language.get('COMMAND_SHARDTIMES_MISSING_ROLE'));
                    } else if (!message.guild.members.has(userID) && action === 'add') {  // If they are trying to add someone that is not in their server
                        return message.channel.send('You can only add users that are in your server.');
                    } else if (!message.guild.members.has(userID) && action === 'remove' && level < 4) {   // If they are trying to remove someone else
                        return message.channel.send('You cannot remove other people');
                    }
                }
            } else {
                // Bad name, grumblin time
                return message.channel.send(message.language.get('COMMAND_SHARDTIMES_INVALID_USER'));
            }
        }
        const exists = await client.allyCodes.findOne({where: {id: userID}})
            .then(token => token != null)
            .then(isUnique => isUnique);

        switch (action) {
            case 'add':
                if (!allyCode) {
                    return message.channel.send(message.language.get('COMMAND_REGISTER_MISSING_ALLY'));
                } else {
                    if (client.isAllyCode(allyCode)) {
                        allyCode = allyCode.replace(/[^\d]*/g, '');
                    } else {
                        // Bad code, grumblin time
                        return message.channel.send(message.language.get('COMMAND_REGISTER_INVALID_ALLY', allyCode));
                    }
                }
                if (!exists) {
                    // Sync up their swgoh account
                    message.channel.send(message.language.get('COMMAND_REGISTER_PLEASE_WAIT')).then(async msg => {
                        await client.swgohAPI.updatePlayer(allyCode).then(async (u) => {
                            if (!u) {
                                await msg.edit(message.language.get('COMMAND_REGISTER_FAILURE'));
                            } else {
                                await client.allyCodes.create({
                                    id: userID,
                                    allyCode: allyCode
                                });
                                await msg.edit(message.language.get('COMMAND_REGISTER_SUCCESS', u.name));
                            }
                        });
                    });
                } else {
                    return message.channel.send('You are already registered! Please use `;register update`.');
                }
                break;
            case 'update':
                if (!exists) {
                    return message.channel.send('You have not registered yet.');
                } else {
                    let ally = await client.allyCodes.findOne({where: {id: userID}});
                    ally = ally.dataValues.allyCode;
                    await message.channel.send(message.language.get('COMMAND_REGISTER_PLEASE_WAIT')).then(async msg => {
                        await client.swgohAPI.updatePlayer(ally).then(async (u) => {
                            if (!u) {
                                await msg.edit(message.language.get('COMMAND_REGISTER_UPDATE_FAILURE'));
                            } else {
                                await msg.edit(message.language.get('COMMAND_REGISTER_UPDATE_SUCCESS', u.name));
                            }
                        });
                    });
                }
                break;
            case 'remove':
                if (!exists) {
                    message.channel.send('You were not linked to a SWGoH account.');
                } else {
                    await client.allyCodes.destroy({where: {id: userID}})
                        .then(() => {
                            message.channel.send('Successfully unlinked.');
                        })
                        .catch(() => {
                            message.channel.send('Something went wrong, please try again.');
                        });
                }
                break;
            default:
                client.helpOut(message, this);

        }
    }
}

module.exports = Register;

<commit_msg>Fixed quick bug<commit_after>const Command = require('../base/Command');

class Register extends Command {
    constructor(client) {
        super(client, {
            name: 'register',
            category: "SWGoH",
            aliases: ['reg']
        });
    }

    async run(client, message, [action, userID, allyCode, ...args], options) { // eslint-disable-line no-unused-vars
        const level = options.level;
        const acts = ['add', 'update', 'remove'];
        if (!action || !acts.includes(action.toLowerCase())) {
            return message.channel.send('You need to choose either `add`, `remove`, or `update`.');
        }
        action = action.toLowerCase();
        if (!userID) {
            return message.channel.send(message.language.get('COMMAND_REGISTER_MISSING_ARGS'));
        } else {
            if (userID === 'me') {
                userID = message.author.id;
            } else if (client.isUserID(userID)) {
                userID = userID.replace(/[^\d]*/g, '');
                // If they are trying to add someone else and they don't have the right perms, stop em
                if (userID !== message.author.id) {
                    if (level < 3) {
                        return message.channel.send(message.language.get('COMMAND_SHARDTIMES_MISSING_ROLE'));
                    } else if (!message.guild.members.has(userID) && action === 'add') {  // If they are trying to add someone that is not in their server
                        return message.channel.send('You can only add users that are in your server.');
                    } else if (!message.guild.members.has(userID) && action === 'remove' && level < 4) {   // If they are trying to remove someone else
                        return message.channel.send('You cannot remove other people');
                    }
                }
            } else {
                // Bad name, grumblin time
                return message.channel.send(message.language.get('COMMAND_SHARDTIMES_INVALID_USER'));
            }
        }
        const exists = await client.allyCodes.findOne({where: {id: userID}})
            .then(token => token != null)
            .then(isUnique => isUnique);

        switch (action) {
            case 'add':
                if (!allyCode) {
                    return message.channel.send(message.language.get('COMMAND_REGISTER_MISSING_ALLY'));
                } else {
                    if (client.isAllyCode(allyCode)) {
                        allyCode = allyCode.replace(/[^\d]*/g, '');
                    } else {
                        // Bad code, grumblin time
                        return message.channel.send(message.language.get('COMMAND_REGISTER_INVALID_ALLY', allyCode));
                    }
                }
                if (!exists) {
                    // Sync up their swgoh account
                    message.channel.send(message.language.get('COMMAND_REGISTER_PLEASE_WAIT')).then(async msg => {
                        await client.swgohAPI.updatePlayer(allyCode).then(async (u) => {
                            if (!u) {
                                await msg.edit(message.language.get('COMMAND_REGISTER_FAILURE'));
                            } else {
                                await client.allyCodes.create({
                                    id: userID,
                                    allyCode: allyCode
                                });
                                await msg.edit(message.language.get('COMMAND_REGISTER_SUCCESS', u.name));
                            }
                        });
                    });
                } else {
                    return message.channel.send('You are already registered! Please use `;register update`.');
                }
                break;
            case 'update':
                if (!exists) {
                    return message.channel.send('You have not registered yet.');
                } else {
                    let ally = await client.allyCodes.findOne({where: {id: userID}});
                    ally = ally.dataValues.allyCode;
                    await message.channel.send(message.language.get('COMMAND_REGISTER_PLEASE_WAIT')).then(async msg => {
                        await client.swgohAPI.updatePlayer(ally).then(async (u) => {
                            if (!u) {
                                await msg.edit(message.language.get('COMMAND_REGISTER_UPDATE_FAILURE'));
                            } else {
                                await msg.edit(message.language.get('COMMAND_REGISTER_UPDATE_SUCCESS', u.name));
                            }
                        });
                    });
                }
                break;
            case 'remove':
                if (!exists) {
                    message.channel.send('You were not linked to a SWGoH account.');
                } else {
                    await client.allyCodes.destroy({where: {id: userID}})
                        .then(() => {
                            message.channel.send('Successfully unlinked.');
                        })
                        .catch(() => {
                            message.channel.send('Something went wrong, please try again.');
                        });
                }
                break;
            default:
                client.helpOut(message, this);

        }
    }
}

module.exports = Register;

<|endoftext|>


<commit_before>'use strict';

var exec = require('child_process').exec;

var users;

module.exports = function register(controller, db) {

  users = db.collection('users');

  controller.hears(['register'], ['direct_message','mention','direct_mention', 'message_received'], function(bot, message) {
    bot.api.users.info({user: message.user}, function (err, _user) {
      var user = _user.user;
      bot.reply(message, 'Hello ' + user.real_name + '!');
      bot.startPrivateConversation(message, function(response, convo) {
        convo.ask('What is your cohort? Please use all caps. ie.) HRR16', function(response, convo){
          convo.ask('What is your thesis group? Make sure this matches your slack channel name EXACTLY.', function(response, convo) {
            user.cohort = convo.responses['What is your cohort? Please use all caps. ie.) HRR16'].text;
            user.thesisGroup = convo.responses['What is your thesis group? Make sure this matches your slack channel name EXACTLY.'].text;
            users.insertMany([user], function(err, result){
              if(err) {
                convo.say('Whoops. Something happened and your info was unable to be saved to the database. Please try again. If the error persists please contact remote.beta.communication@')
              } else {
                convo.say('Thanks!');
              }
              convo.next();
            });
          });
          convo.next();
        });
        convo.next();
      });
    });
  });
};
<commit_msg>(fix) Update register.js to omit thesis wording<commit_after>'use strict';

var exec = require('child_process').exec;

var users;

module.exports = function register(controller, db) {

  users = db.collection('users');

  controller.hears(['register'], ['direct_message','mention','direct_mention', 'message_received'], function(bot, message) {
    bot.api.users.info({user: message.user}, function (err, _user) {
      var user = _user.user;
      bot.reply(message, 'Hello ' + user.real_name + '!');
      bot.startPrivateConversation(message, function(response, convo) {
        convo.ask('What is your cohort? Please use all caps. ie.) HRR16', function(response, convo){
          convo.ask('What is your group name? Make sure this matches your slack channel name EXACTLY.', function(response, convo) {
            user.cohort = convo.responses['What is your cohort? Please use all caps. ie.) HRR16'].text;
            user.thesisGroup = convo.responses['What is your group name? Make sure this matches your slack channel name EXACTLY.'].text;
            users.insertMany([user], function(err, result){
              if(err) {
                convo.say('Whoops. Something happened and your info was unable to be saved to the database. Please try again. If the error persists please contact remote.beta.communication@')
              } else {
                convo.say('Thanks!');
              }
              convo.next();
            });
          });
          convo.next();
        });
        convo.next();
      });
    });
  });
};
<|endoftext|>


<commit_before>exports.names = ['roulette'];
exports.hidden = true;
exports.enabled = true;
exports.matchStart = false;
exports.cd_all = 0;
exports.cd_user = 0;
exports.cd_manager = 0;
exports.min_role = PERMISSIONS.BOUNCER_PLUS;
var roulette_duration = 60; // in seconds
var roulette_timer = false;
exports.handler = function (data) {
    var rest = _.rest(data.message.split(' '), 1).join(' ').trim().toLowerCase();

    if (rest === 'stop') {
        if (bot.running_roulette === true) {
            modMessage(data, 'The roulette has been cancelled. :sadness:');
            clearTimeout(roulette_timer);
            roulette_timer = false;
            bot.running_roulette = false;
        }
    } else {
        if (bot.running_roulette !== true) {
            var roulette_length = roulette_duration * 1000;
            if (rest.length > 0 && data.from.role > 2) {
                /* Only managers can create custom length roulettes. */
                var roulette_length_arg = parseInt(rest);
                if (!isNaN(roulette_length_arg) && roulette_length_arg > 0) {
                    roulette_length = roulette_length_arg * 1000;
                }
            }
            modMessage(data, 'The roulette is now open! Type .join to participate! The roulette will finish in ' + (roulette_length/1000) + ' seconds.');
            bot.running_roulette = true;
            bot.roulette_users = [];

            roulette_timer = setTimeout(function () {
                bot.running_roulette = false;
                if (bot.roulette_users.length > 0) {
                    logger.info(bot.roulette_users);
                    var winner_index = _.random(0, bot.roulette_users.length-1);
                    var winner = bot.roulette_users[winner_index];
                    var position = _.random(1, bot.getWaitList().length);
                    chatMessage('A winner has been picked (' + bot.roulette_users.length + ' participants)! @' + winner + ' to position ' + position + '.');

                    var users = bot.getUsers();
                    var user = _.findWhere(users, {username: winner});
                    if (user !== undefined) {
                        move_user(user.id, position);
                        var current_position = bot.getWaitListPosition(user.id);
                        logger.info('[ROULETTE]', data.from.username + ' roulette ended with ' + bot.roulette_users.length + ' participants. @' + winner + ' from ' + current_position + ' to position ' + position + '.');
                    } else {
                        chatMessage('/me user who won roulette isn\'t even here :4head:');
                    }
                } else {
                    chatMessage('/me No one joined the roulette, what the fuck guys. :dansgame:');
                }
            }, roulette_length);
        } else {
            modMessage(data, 'The roulette is already running.');
        }
    }
};
<commit_msg>roulette now outputs a special message if the person is moved to the position he's currently at<commit_after>exports.names = ['roulette'];
exports.hidden = true;
exports.enabled = true;
exports.matchStart = false;
exports.cd_all = 0;
exports.cd_user = 0;
exports.cd_manager = 0;
exports.min_role = PERMISSIONS.BOUNCER_PLUS;
var roulette_duration = 60; // in seconds
var roulette_timer = false;
exports.handler = function (data) {
    var rest = _.rest(data.message.split(' '), 1).join(' ').trim().toLowerCase();

    if (rest === 'stop') {
        if (bot.running_roulette === true) {
            modMessage(data, 'The roulette has been cancelled. :sadness:');
            clearTimeout(roulette_timer);
            roulette_timer = false;
            bot.running_roulette = false;
        }
    } else {
        if (bot.running_roulette !== true) {
            var roulette_length = roulette_duration * 1000;
            if (rest.length > 0 && data.from.role > 2) {
                /* Only managers can create custom length roulettes. */
                var roulette_length_arg = parseInt(rest);
                if (!isNaN(roulette_length_arg) && roulette_length_arg > 0) {
                    roulette_length = roulette_length_arg * 1000;
                }
            }
            modMessage(data, 'The roulette is now open! Type .join to participate! The roulette will finish in ' + (roulette_length/1000) + ' seconds.');
            bot.running_roulette = true;
            bot.roulette_users = [];

            roulette_timer = setTimeout(function () {
                bot.running_roulette = false;
                if (bot.roulette_users.length > 0) {
                    logger.info(bot.roulette_users);
                    var winner_index = _.random(0, bot.roulette_users.length-1);
                    var winner = bot.roulette_users[winner_index];
                    var position = _.random(1, bot.getWaitList().length);
                    chatMessage('A winner has been picked (' + bot.roulette_users.length + ' participants)! @' + winner + ' to position ' + position + '.');

                    var users = bot.getUsers();
                    var user = _.findWhere(users, {username: winner});
                    if (user !== undefined) {
                        var current_position = bot.getWaitListPosition(user.id);
                        logger.info('[ROULETTE]', data.from.username + ' roulette ended with ' + bot.roulette_users.length + ' participants. @' + winner + ' from ' + current_position + ' to position ' + position + '.');
                        if (current_position == position) {
                            chatMessage('nice value, from ' + current_position + ' to ' + position + ' :trumpw:');
                        }

                        move_user(user.id, position);
                    } else {
                        chatMessage('/me user who won roulette isn\'t even here :4head:');
                    }
                } else {
                    chatMessage('/me No one joined the roulette, what the fuck guys. :dansgame:');
                }
            }, roulette_length);
        } else {
            modMessage(data, 'The roulette is already running.');
        }
    }
};
<|endoftext|>