<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Fix 'AboutObjects.js'<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>// Currently in sync with Node.js lib/internal/util/types.js
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9

'use strict';

function uncurryThis(f) {
  return f.call.bind(f);
}

var TypedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);

var TypedArrayProto_toStringTag =
    uncurryThis(
      Object.getOwnPropertyDescriptor(TypedArrayPrototype,
                                      Symbol.toStringTag).get);

// Cached to make sure no userland code can tamper with it.
var isArrayBufferView = ArrayBuffer.isView;

exports.isTypedArray = function(value) {
  return TypedArrayProto_toStringTag(value) !== undefined;
}

exports.isUint8Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint8Array';
}

exports.isUint8ClampedArray = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint8ClampedArray';
}

exports.isUint16Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint16Array';
}

exports.isUint32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint32Array';
}

exports.isInt8Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int8Array';
}

exports.isInt16Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int16Array';
}

exports.isInt32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int32Array';
}

exports.isFloat32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Float32Array';
}

exports.isFloat64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Float64Array';
}

exports.isBigInt64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'BigInt64Array';
}

exports.isBigUint64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'BigUint64Array';
}

var ObjectToString = uncurryThis(Object.prototype.toString);

exports.isPromise = function(value) {
  return ObjectToString(value) === '[object Promise]';
}

exports.isMap = function(value) {
  return ObjectToString(value) === '[object Map]';
}

exports.isSet = function(value) {
  return ObjectToString(value) === '[object Set]';
}

exports.isWeakMap = function(value) {
  return ObjectToString(value) === '[object WeakMap]';
}

exports.isWeakSet = function(value) {
  return ObjectToString(value) === '[object WeakSet]';
}

exports.isArrayBuffer = function(value) {
  return ObjectToString(value) === '[object ArrayBuffer]';
}

exports.isDataView = function(value) {
  return ObjectToString(value) === '[object DataView]';
}

exports.isArrayBuffer = function(value) {
  return ObjectToString(value) === '[object ArrayBuffer]';
}

exports.isSharedArrayBuffer = function(value) {
  return ObjectToString(value) === '[object SharedArrayBuffer]';
}

exports.isAsyncFunction = function(value) {
  return ObjectToString(value) === '[object AsyncFunction]';
}

exports.isGeneratorFunction = function(value) {
  return ObjectToString(value) === '[object GeneratorFunction]';
};

exports.isMapIterator = function(value) {
  return ObjectToString(value) === '[object Map Iterator]';
}

exports.isMapIterator = function(value) {
  return ObjectToString(value) === '[object Map Iterator]';
}
<commit_msg>Export isArrayBufferView<commit_after>// Currently in sync with Node.js lib/internal/util/types.js
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9

'use strict';

function uncurryThis(f) {
  return f.call.bind(f);
}

var TypedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);

var TypedArrayProto_toStringTag =
    uncurryThis(
      Object.getOwnPropertyDescriptor(TypedArrayPrototype,
                                      Symbol.toStringTag).get);

exports.isArrayBufferView = ArrayBuffer.isView;

exports.isTypedArray = function(value) {
  return TypedArrayProto_toStringTag(value) !== undefined;
}

exports.isUint8Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint8Array';
}

exports.isUint8ClampedArray = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint8ClampedArray';
}

exports.isUint16Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint16Array';
}

exports.isUint32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Uint32Array';
}

exports.isInt8Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int8Array';
}

exports.isInt16Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int16Array';
}

exports.isInt32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Int32Array';
}

exports.isFloat32Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Float32Array';
}

exports.isFloat64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'Float64Array';
}

exports.isBigInt64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'BigInt64Array';
}

exports.isBigUint64Array = function(value) {
  return TypedArrayProto_toStringTag(value) === 'BigUint64Array';
}

var ObjectToString = uncurryThis(Object.prototype.toString);

exports.isPromise = function(value) {
  return ObjectToString(value) === '[object Promise]';
}

exports.isMap = function(value) {
  return ObjectToString(value) === '[object Map]';
}

exports.isSet = function(value) {
  return ObjectToString(value) === '[object Set]';
}

exports.isWeakMap = function(value) {
  return ObjectToString(value) === '[object WeakMap]';
}

exports.isWeakSet = function(value) {
  return ObjectToString(value) === '[object WeakSet]';
}

exports.isArrayBuffer = function(value) {
  return ObjectToString(value) === '[object ArrayBuffer]';
}

exports.isDataView = function(value) {
  return ObjectToString(value) === '[object DataView]';
}

exports.isArrayBuffer = function(value) {
  return ObjectToString(value) === '[object ArrayBuffer]';
}

exports.isSharedArrayBuffer = function(value) {
  return ObjectToString(value) === '[object SharedArrayBuffer]';
}

exports.isAsyncFunction = function(value) {
  return ObjectToString(value) === '[object AsyncFunction]';
}

exports.isGeneratorFunction = function(value) {
  return ObjectToString(value) === '[object GeneratorFunction]';
};

exports.isMapIterator = function(value) {
  return ObjectToString(value) === '[object Map Iterator]';
}

exports.isMapIterator = function(value) {
  return ObjectToString(value) === '[object Map Iterator]';
}
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */

// Provides control sap.m.ObjectStatus.
sap.ui.define([
	'./library',
	'sap/ui/core/Control',
	'sap/ui/core/ValueStateSupport',
	'sap/ui/core/IndicationColorSupport',
	'sap/ui/core/library',
	'sap/ui/base/DataType',
	'./ObjectStatusRenderer'
],
	function(library, Control, ValueStateSupport, IndicationColorSupport, coreLibrary, DataType, ObjectStatusRenderer) {
	"use strict";

	// shortcut for sap.m.ImageHelper
	var ImageHelper = library.ImageHelper;

	// shortcut for sap.ui.core.TextDirection
	var TextDirection = coreLibrary.TextDirection;

	// shortcuts for sap.ui.core.ValueState
	var ValueState = coreLibrary.ValueState;

	/**
	 * Constructor for a new ObjectStatus.
	 *
	 * @param {string} [sId] ID for the new control, generated automatically if no ID is given
	 * @param {object} [mSettings] Initial settings for the new control
	 *
	 * @class
	 * Status information that can be either text with a value state, or an icon.
	 *
	 *
	 * With 1.63, large design of the control is supported by setting sapMObjectStatusLarge CSS class to the ObjectStatus.
	 *
	 * @extends sap.ui.core.Control
	 * @implements sap.ui.core.IFormContent
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @alias sap.m.ObjectStatus
	 * @see {@link fiori:https://experience.sap.com/fiori-design-web/object-display-elements/#-object-status Object Status}
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var ObjectStatus = Control.extend("sap.m.ObjectStatus", /** @lends sap.m.ObjectStatus.prototype */ { metadata : {

		interfaces : ["sap.ui.core.IFormContent"],
		library : "sap.m",
		designtime: "sap/m/designtime/ObjectStatus.designtime",
		properties : {

			/**
			 * Defines the ObjectStatus title.
			 */
			title : {type : "string", group : "Misc", defaultValue : null},

			/**
			 * Defines the ObjectStatus text.
			 */
			text : {type : "string", group : "Misc", defaultValue : null},

			/**
			 * Indicates if the ObjectStatus text and icon can be clicked/tapped by the user.
			 *
			 * Note: If you set this property to true, you have to also set the text or icon property.
			 *
			 * @since 1.54
			 */
			active : {type : "boolean", group : "Misc", defaultValue : false},

			/**
			 * Defines the text value state.
			 */
			state : {type : "string", group : "Misc", defaultValue : ValueState.None},

			/**
			 * Determines whether the background color reflects the set state instead of the control's text.
			 * @since 1.66
			 */
			inverted : {type : "boolean", group : "Misc", defaultValue : false},

			/**
			 * Icon URI. This may be either an icon font or image path.
			 */
			icon : {type : "sap.ui.core.URI", group : "Misc", defaultValue : null},

			/**
			 * By default, this is set to true but then one or more requests are sent trying to get the density perfect version of image if this version of image doesn't exist on the server.
			 *
			 * If bandwidth is key for the application, set this value to false.
			 */
			iconDensityAware : {type : "boolean", group : "Appearance", defaultValue : true},

			/**
			 * Determines the direction of the text, not including the title.
			 * Available options for the text direction are LTR (left-to-right) and RTL (right-to-left). By default the control inherits the text direction from its parent control.
			 */
			textDirection : {type : "sap.ui.core.TextDirection", group : "Appearance", defaultValue : TextDirection.Inherit}
		},
		associations : {

			/**
			 * Association to controls / IDs, which describe this control (see WAI-ARIA attribute aria-describedby).
			 */
			ariaDescribedBy : {type : "sap.ui.core.Control", multiple : true, singularName : "ariaDescribedBy"}
		},
		events : {

			/**
			 * Fires when the user clicks/taps on active text.
			 * @since 1.54
			 */
			press : {}
		},
		dnd: { draggable: true, droppable: false }
	}});

	/**
	 * Called when the control is destroyed.
	 *
	 * @private
	 */
	ObjectStatus.prototype.exit = function() {
		if (this._oImageControl) {
			this._oImageControl.destroy();
			this._oImageControl = null;
		}
	};

	/**
	 * Lazy loads feed icon image.
	 *
	 * @returns {object} The feed icon image
	 * @private
	 */
	ObjectStatus.prototype._getImageControl = function() {
		var sImgId = this.getId() + '-icon',
			bIsIconOnly = !this.getText() && !this.getTitle(),
			mProperties = {
				src : this.getIcon(),
				densityAware : this.getIconDensityAware(),
				useIconTooltip : false
			};

		if (bIsIconOnly) {
			mProperties.decorative = false;
			mProperties.alt = sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("OBJECT_STATUS_ICON");
		}

		this._oImageControl = ImageHelper.getImageControl(sImgId, this._oImageControl, this, mProperties);

		return this._oImageControl;
	};

	/**
	 * Sets value for the state property. The default value is ValueState.None.
	 * @public
	 * @param {string} sValue New value for property state.
	 * It should be valid value of enumeration sap.ui.core.ValueState or sap.ui.core.IndicationColor
	 * @returns {sap.m.ObjectStatus} this to allow method chaining
	 */
	ObjectStatus.prototype.setState = function(sValue) {
		if (sValue == null) {
			sValue = ValueState.None;
		} else if (!DataType.getType("sap.ui.core.ValueState").isValid(sValue) && !DataType.getType("sap.ui.core.IndicationColor").isValid(sValue)) {
			throw new Error('"' + sValue + '" is not a value of the enums sap.ui.core.ValueState or sap.ui.core.IndicationColor for property "state" of ' + this);
		}

		return this.setProperty("state", sValue);
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.ontap = function(oEvent) {
		if (this._isClickable(oEvent)) {
			this.firePress();
		}
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.onsapenter = function(oEvent) {
		if (this._isActive()) {
			this.firePress();

			// mark the event that it is handled by the control
			oEvent.setMarked();
		}
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.onsapspace = function(oEvent) {
		this.onsapenter(oEvent);
	};

	/**
	 * Checks if the ObjectStatus should be set to active.
	 * @private
	 * @returns {boolean} If the ObjectStatus is active
	 */
	ObjectStatus.prototype._isActive = function() {

		return  this.getActive() && (this.getText().trim() || this.getIcon().trim());
	};

	/**
	 * Checks if the ObjectStatus is empty.
	 * @private
	 * @returns {boolean} If the ObjectStatus is empty
	 */
	ObjectStatus.prototype._isEmpty = function() {

		return !(this.getText().trim() || this.getIcon().trim() || this.getTitle().trim());
	};

	/**
	 * Called when the control is touched.
	 * @param {object} oEvent The fired event
	 * @private
	 */
	ObjectStatus.prototype.ontouchstart = function(oEvent) {
		if (this._isClickable(oEvent)) {
			// mark the event that it is handled by the control
			oEvent.setMarked();
		}
	};

	/**
	 * @see sap.ui.core.Control#getAccessibilityInfo
	 *
	 * @returns {Object} Current accessibility state of the control
	 * @protected
	 */
	ObjectStatus.prototype.getAccessibilityInfo = function() {
		var sState = ValueStateSupport.getAdditionalText(this.getState());

		if (this.getState() != ValueState.None) {
			sState = (sState !== null) ? sState : IndicationColorSupport.getAdditionalText(this.getState());
		}

		return {
			description: (
				(this.getTitle() || "") + " " +
				(this.getText() || "") + " " +
				(sState !== null ? sState : "") + " " +
				(this.getTooltip() || "") + " " +
				sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("OBJECT_STATUS")
			).trim()
		};
	};

	ObjectStatus.prototype._isClickable = function(oEvent) {
		var sSourceId = oEvent.target.id;

		//event should only be fired if the click is on the text, link or icon
		return this._isActive() && (sSourceId === this.getId() + "-link" || sSourceId === this.getId() + "-text" || sSourceId === this.getId() + "-statusIcon" || sSourceId === this.getId() + "-icon");
	};

	return ObjectStatus;

});
<commit_msg>[FIX] sap.m.ObjectStatus: documentation update<commit_after>/*!
 * ${copyright}
 */

// Provides control sap.m.ObjectStatus.
sap.ui.define([
	'./library',
	'sap/ui/core/Control',
	'sap/ui/core/ValueStateSupport',
	'sap/ui/core/IndicationColorSupport',
	'sap/ui/core/library',
	'sap/ui/base/DataType',
	'./ObjectStatusRenderer'
],
	function(library, Control, ValueStateSupport, IndicationColorSupport, coreLibrary, DataType, ObjectStatusRenderer) {
	"use strict";

	// shortcut for sap.m.ImageHelper
	var ImageHelper = library.ImageHelper;

	// shortcut for sap.ui.core.TextDirection
	var TextDirection = coreLibrary.TextDirection;

	// shortcuts for sap.ui.core.ValueState
	var ValueState = coreLibrary.ValueState;

	/**
	 * Constructor for a new ObjectStatus.
	 *
	 * @param {string} [sId] ID for the new control, generated automatically if no ID is given
	 * @param {object} [mSettings] Initial settings for the new control
	 *
	 * @class
	 * Status information that can be either text with a value state, or an icon.
	 *
	 *
	 * With 1.63, large design of the control is supported by setting sapMObjectStatusLarge CSS class to the ObjectStatus.
	 *
	 * @extends sap.ui.core.Control
	 * @implements sap.ui.core.IFormContent
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @alias sap.m.ObjectStatus
	 * @see {@link fiori:https://experience.sap.com/fiori-design-web/object-display-elements/#-object-status Object Status}
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var ObjectStatus = Control.extend("sap.m.ObjectStatus", /** @lends sap.m.ObjectStatus.prototype */ { metadata : {

		interfaces : ["sap.ui.core.IFormContent"],
		library : "sap.m",
		designtime: "sap/m/designtime/ObjectStatus.designtime",
		properties : {

			/**
			 * Defines the ObjectStatus title.
			 */
			title : {type : "string", group : "Misc", defaultValue : null},

			/**
			 * Defines the ObjectStatus text.
			 */
			text : {type : "string", group : "Misc", defaultValue : null},

			/**
			 * Indicates if the ObjectStatus text and icon can be clicked/tapped by the user.
			 *
			 * Note: If you set this property to true, you have to also set the text or icon property.
			 *
			 * @since 1.54
			 */
			active : {type : "boolean", group : "Misc", defaultValue : false},

			/**
			 * Defines the text value state. The allowed values are from the enum type
			 * sap.ui.core.ValueState. Since version 1.66 the state property also accepts
			 * values from enum type sap.ui.core.IndicationColor.
			 */
			state : {type : "string", group : "Misc", defaultValue : ValueState.None},

			/**
			 * Determines whether the background color reflects the set state instead of the control's text.
			 * @since 1.66
			 */
			inverted : {type : "boolean", group : "Misc", defaultValue : false},

			/**
			 * Icon URI. This may be either an icon font or image path.
			 */
			icon : {type : "sap.ui.core.URI", group : "Misc", defaultValue : null},

			/**
			 * By default, this is set to true but then one or more requests are sent trying to get the density perfect version of image if this version of image doesn't exist on the server.
			 *
			 * If bandwidth is key for the application, set this value to false.
			 */
			iconDensityAware : {type : "boolean", group : "Appearance", defaultValue : true},

			/**
			 * Determines the direction of the text, not including the title.
			 * Available options for the text direction are LTR (left-to-right) and RTL (right-to-left). By default the control inherits the text direction from its parent control.
			 */
			textDirection : {type : "sap.ui.core.TextDirection", group : "Appearance", defaultValue : TextDirection.Inherit}
		},
		associations : {

			/**
			 * Association to controls / IDs, which describe this control (see WAI-ARIA attribute aria-describedby).
			 */
			ariaDescribedBy : {type : "sap.ui.core.Control", multiple : true, singularName : "ariaDescribedBy"}
		},
		events : {

			/**
			 * Fires when the user clicks/taps on active text.
			 * @since 1.54
			 */
			press : {}
		},
		dnd: { draggable: true, droppable: false }
	}});

	/**
	 * Called when the control is destroyed.
	 *
	 * @private
	 */
	ObjectStatus.prototype.exit = function() {
		if (this._oImageControl) {
			this._oImageControl.destroy();
			this._oImageControl = null;
		}
	};

	/**
	 * Lazy loads feed icon image.
	 *
	 * @returns {object} The feed icon image
	 * @private
	 */
	ObjectStatus.prototype._getImageControl = function() {
		var sImgId = this.getId() + '-icon',
			bIsIconOnly = !this.getText() && !this.getTitle(),
			mProperties = {
				src : this.getIcon(),
				densityAware : this.getIconDensityAware(),
				useIconTooltip : false
			};

		if (bIsIconOnly) {
			mProperties.decorative = false;
			mProperties.alt = sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("OBJECT_STATUS_ICON");
		}

		this._oImageControl = ImageHelper.getImageControl(sImgId, this._oImageControl, this, mProperties);

		return this._oImageControl;
	};

	/**
	 * Sets value for the state property. The default value is ValueState.None.
	 * @public
	 * @param {string} sValue New value for property state.
	 * It should be valid value of enumeration sap.ui.core.ValueState or sap.ui.core.IndicationColor
	 * @returns {sap.m.ObjectStatus} this to allow method chaining
	 */
	ObjectStatus.prototype.setState = function(sValue) {
		if (sValue == null) {
			sValue = ValueState.None;
		} else if (!DataType.getType("sap.ui.core.ValueState").isValid(sValue) && !DataType.getType("sap.ui.core.IndicationColor").isValid(sValue)) {
			throw new Error('"' + sValue + '" is not a value of the enums sap.ui.core.ValueState or sap.ui.core.IndicationColor for property "state" of ' + this);
		}

		return this.setProperty("state", sValue);
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.ontap = function(oEvent) {
		if (this._isClickable(oEvent)) {
			this.firePress();
		}
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.onsapenter = function(oEvent) {
		if (this._isActive()) {
			this.firePress();

			// mark the event that it is handled by the control
			oEvent.setMarked();
		}
	};

	/**
	 * @private
	 * @param {object} oEvent The fired event
	 */
	ObjectStatus.prototype.onsapspace = function(oEvent) {
		this.onsapenter(oEvent);
	};

	/**
	 * Checks if the ObjectStatus should be set to active.
	 * @private
	 * @returns {boolean} If the ObjectStatus is active
	 */
	ObjectStatus.prototype._isActive = function() {

		return  this.getActive() && (this.getText().trim() || this.getIcon().trim());
	};

	/**
	 * Checks if the ObjectStatus is empty.
	 * @private
	 * @returns {boolean} If the ObjectStatus is empty
	 */
	ObjectStatus.prototype._isEmpty = function() {

		return !(this.getText().trim() || this.getIcon().trim() || this.getTitle().trim());
	};

	/**
	 * Called when the control is touched.
	 * @param {object} oEvent The fired event
	 * @private
	 */
	ObjectStatus.prototype.ontouchstart = function(oEvent) {
		if (this._isClickable(oEvent)) {
			// mark the event that it is handled by the control
			oEvent.setMarked();
		}
	};

	/**
	 * @see sap.ui.core.Control#getAccessibilityInfo
	 *
	 * @returns {Object} Current accessibility state of the control
	 * @protected
	 */
	ObjectStatus.prototype.getAccessibilityInfo = function() {
		var sState = ValueStateSupport.getAdditionalText(this.getState());

		if (this.getState() != ValueState.None) {
			sState = (sState !== null) ? sState : IndicationColorSupport.getAdditionalText(this.getState());
		}

		return {
			description: (
				(this.getTitle() || "") + " " +
				(this.getText() || "") + " " +
				(sState !== null ? sState : "") + " " +
				(this.getTooltip() || "") + " " +
				sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("OBJECT_STATUS")
			).trim()
		};
	};

	ObjectStatus.prototype._isClickable = function(oEvent) {
		var sSourceId = oEvent.target.id;

		//event should only be fired if the click is on the text, link or icon
		return this._isActive() && (sSourceId === this.getId() + "-link" || sSourceId === this.getId() + "-text" || sSourceId === this.getId() + "-statusIcon" || sSourceId === this.getId() + "-icon");
	};

	return ObjectStatus;

});
<|endoftext|>


<commit_before>// This module expects that all custom JS files have already been brought into
// scope, that my_modules contains a list of .wasm files, and that it is
// included from a webpage.
var my_print;

function kremlin_start () {
  my_print = (...msg) =>
    document.getElementById("terminal").appendChild(
      document.createTextNode(msg.join(" ")+"\n"));

  if (!("WebAssembly" in this))
    my_print("Error: WebAssembly not enabled. Use Chrome Canary?");

  my_print("... assembling WASM modules " + my_modules);
  return Promise.all(my_modules.map(m => fetch(m + ".wasm")))
    .then(responses =>
      Promise.all(responses.map(r => r.arrayBuffer()))
    ).then(bufs =>
      link(my_imports || {}, bufs.map((b, i) => ({ buf: b, name: my_modules[i] }))))
    .then(scope => {
      for (let m of Object.keys(scope)) {
        if ("main" in scope[m]) {
          my_print("... main found in module " + m);
          return scope[m].main();
        }
      }
      if (!("main" in window)) {
        my_print("... no main in current window");
        throw "Aborting";
      }
      return main();
    }).then(err => {
      my_print("... main exited with " + err);
      if (err != 0)
        throw "Main returned non-zero status";
    }).catch(e =>
      my_print(e)
    );
}
<commit_msg>A few tricks to facilitate debugging<commit_after>// This module expects that all custom JS files have already been brought into
// scope, that my_modules contains a list of .wasm files, and that it is
// included from a webpage.
var my_print;

function kremlin_start () {
  my_print = (...msg) =>
    document.getElementById("terminal").appendChild(
      document.createTextNode(msg.join(" ")+"\n"));

  if (!("my_imports" in this))
    this.my_imports = {};

  if (!("WebAssembly" in this))
    my_print("Error: WebAssembly not enabled. Use Chrome Canary?");

  my_print("... assembling WASM modules " + my_modules);
  return Promise.all(my_modules.map(m => fetch(m + ".wasm")))
    .then(responses =>
      Promise.all(responses.map(r => r.arrayBuffer()))
    ).then(bufs =>
      link(my_imports, bufs.map((b, i) => ({ buf: b, name: my_modules[i] }))))
    .then(scope => {
      for (let m of Object.keys(scope)) {
        if ("main" in scope[m]) {
          my_print("... main found in module " + m);
          return scope[m].main(scope);
        }
      }
      if (!("main" in window)) {
        my_print("... no main in current window");
        throw "Aborting";
      }
      return main(scope);
    }).then(err => {
      my_print("... main exited with " + err);
      if (err != 0)
        throw "Main returned non-zero status";
    }).catch(e =>
      my_print(e)
    );
}
<|endoftext|>


<commit_before>
module.exports = {
  variants: {
    items: {
      // keepNames: true,
      resize: {
        mini : '300x200',
        preview: '800x600'
      },
      crop: {
        thumb: '200x200'
      },
      resizeAndCrop: {
        large: {
          resize: '1000x1000',
          crop: '900x900'
        }
      }
    },

    gallery: {
      crop: {
        thumb: '100x100'
      }
    }
  },

  storage: {
    Local: {
      path: '/tmp',
      mode: 0777
    },
    Rackspace: {
      username: 'USERNAME',
      apiKey: 'API_KEY',
      // authUrl: "https://lon.auth.api.rackspacecloud.com",
      container: 'CONTAINER'
    },
    S3: {
      key: 'KEY',
      secret: 'SECRET',
      bucket: 'BUCKET',
      cdn: 'http://CDN_URL', // (optional)
      storageClass: 'REDUCED_REDUNDANCY' // (optional)
      // set `secure: false` if you want to use buckets with characters like '.' (dot)
    }
  },

  debug: true
}
<commit_msg>add undocumented orientation to exampels<commit_after>
module.exports = {
  variants: {
    items: {
      // keepNames: true,
      resize: {
        mini : '300x200',
        preview: '800x600'
      },
      crop: {
        thumb: '200x200'
      },
      resizeAndCrop: {
        large: {
          resize: '1000x1000',
          crop: '900x900 Center'
        }
      }
    },

    gallery: {
      crop: {
        thumb: '100x100'
      }
    }
  },

  storage: {
    Local: {
      path: '/tmp',
      mode: 0777
    },
    Rackspace: {
      username: 'USERNAME',
      apiKey: 'API_KEY',
      // authUrl: "https://lon.auth.api.rackspacecloud.com",
      container: 'CONTAINER'
    },
    S3: {
      key: 'KEY',
      secret: 'SECRET',
      bucket: 'BUCKET',
      cdn: 'http://CDN_URL', // (optional)
      storageClass: 'REDUCED_REDUNDANCY' // (optional)
      // set `secure: false` if you want to use buckets with characters like '.' (dot)
    }
  },

  debug: true
}
<|endoftext|>


<commit_before>/**
 * @typedef {Object} Platform - a specific Destiny account (one per platform and Destiny version)
 * @property {string} label - the readable name of the platform
 */

/**
 * Platform types (membership types) in the Bungie API.
 * @type {Platform[]}
 */
export const PLATFORMS = {
  1: {
    label: 'Xbox'
  },

  2: {
    label: 'PlayStation'
  },

  254: {
    label: 'Bungie.net'
  }
};
<commit_msg>Add Blizzard account type<commit_after>/**
 * @typedef {Object} Platform - a specific Destiny account (one per platform and Destiny version)
 * @property {string} label - the readable name of the platform
 */

/**
 * Platform types (membership types) in the Bungie API.
 * @type {Platform[]}
 */
export const PLATFORMS = {
  1: {
    label: 'Xbox'
  },

  2: {
    label: 'PlayStation'
  },

  4: {
    label: 'Blizzard'
  },

  10: {
    label: 'Demon'
  },

  254: {
    label: 'Bungie.net'
  }
};
<|endoftext|>


<commit_before>'use strict';

/*
 # Notifies about Jenkins build errors via Jenkins Notification Plugin
 #
 # Dependencies:
 #   "url": ""
 #   "querystring": ""
 #
 # Configuration:
 #   Just put this url <HUBOT_URL>:<PORT>/hubot/jenkins-notify?room=<room> to your Jenkins
 #   Notification config. See here: https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
 #
 # Commands:
 #   None
 #
 # URLS:
 #   POST /hubot/jenkins-notify?room=<room>[&type=<type>]
 #
 # Authors:
 #   spajus
 */

var http, querystring, url;
url = require('url');
querystring = require('querystring');
http = require('http');

var IntervalMinutes = 30;
var MaxSoundsPerInterval = 2;//For any given interval, there will be no more than this number of jenkins sounds
//10 - 1 = One Sound per ten minutes

var soundsSoFar = 0;

function makeSound (urlOfSound) {
    if (!(/http/.test(urlOfSound))) {
        urlOfSound = 'http://xserve:5051/' + urlOfSound;
    }

    if (soundsSoFar >= MaxSoundsPerInterval) {
        console.log('Declining to make a sound: %s', urlOfSound);
        return;
    }
    soundsSoFar += 1;
    setTimeout(function () {
        soundsSoFar -= 1;
    }, IntervalMinutes * 60 * 1000);

    http.get(urlOfSound, function(res) {
        return console.log(res.statusCode);
    });
}

module.exports = function(robot) {

    var foo = {};

    return robot.router.post("/hubot/jenkins-notify", function(req, res) {
        var build, data, envelope, query, room;
        foo.failing = foo.failing || [];
        query = querystring.parse(url.parse(req.url).query);
        res.end('');
        envelope = {};
        envelope.user = {};
        if (query.room) {
            envelope.room = query.room;
        }
        if (query.type) {
            envelope.user.type = query.type;
        }
        room = 'dev';
        try {
            data = req.body;
            console.log("BUILD: " + data.name + " - #" + data.build.number + ": " + data.build.status);
            if (data.build.phase === 'STARTED') {
                if (data.name.match(/mothra.*qa/i)) {
                    makeSound('mothra-qa');
                }
            }
            if (data.build.phase === 'COMPLETED') {
                if (data.name.match(/.*qa.*/i) && !data.name.match(/.*selenium.*/i)) {
                   console.log("Notifying QA");
                   robot.messageRoom('#qa', "" + data.name + " build #" + data.build.number + " : " + data.build.status);
                   robot.messageRoom('#qa', "" + data.build.full_url);
                }
                if (data.build.status === 'FAILURE') {
                    console.log("Failure");
                    if (foo.failing.indexOf(data.name) >= 0) {
                        build = "is still";
                    } else {
                        build = "started";
                    }
                    robot.messageRoom(room, "" + data.name + " build #" + data.build.number + " " + build + " failing (" + (encodeURI(data.build.full_url)) + ")");
                    if (foo.failing.indexOf(data.name) < 0) {
                        foo.failing.push(data.name);
                    }
                    if (data.name.match(/mothra.*qa/i)) {
                        console.log("MOTHRA!!");
                        console.log(res.statusCode);
                        robot.messageRoom('#dev', "Mothra has the upper hand!");
                        robot.messageRoom('#dev', "http://i.imgur.com/CoqJxBx.gif");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        console.log("MECHA GODZILLA!!!!");
                        console.log(res.statusCode);
                        makeSound('mechawins');
                        robot.messageRoom('qa-chat', "Mecha Godzilla is winning!");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/LkziC7bd1yLUk/giphy.gif");
                    }
                }
                if (data.build.status === 'SUCCESS') {
                    console.log("Success");
                    if (data.name === '1stdibs.com Deploy Production PROD PROD PROD PROD') {
                        makeSound('shipit');
                        robot.messageRoom("#release", "1stdibs.com hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'Admin-v2 Deploy (PROD)') {
                        makeSound('shipit-adminv2');
                        robot.messageRoom("#release", "Admin v2 hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'Admin-v1 Deploy (PROD) (RACKSPACE)') {
                        makeSound('shipit-adminv1');
                        robot.messageRoom("#release", "Admin v1 hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'JAVA-InventoryService (Prod)') {
                        makeSound('shipit-inventory');
                        robot.messageRoom("#release", "Inventory service hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'JAVA-IdentityService (Prod)') {
                        makeSound('shipit-identity');
                        robot.messageRoom("#release", "Identity service hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.build && data.build.parameters && data.build.parameters.SERVER_HOSTNAME === 'deathstar.1stdibs.com') {
                        makeSound('deathstar');
                        robot.messageRoom("#dev", "The Death Star is now fully armed and operational");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        console.log("MECHA GODZILLA!!!!");
                        console.log(res.statusCode);
                        makeSound('mechaloses');
                        robot.messageRoom('qa-chat', "Mecha Godzilla has been defeated!");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/33T28J1KEkRq0/giphy.gif");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/yygLBxnwBVynu/giphy.gif");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/tEgJl9nSsfTGM/giphy.gif");
                    }
                }
            }
        } catch (error) {
            console.log("jenkins-notify error: " + error + ". Data: " + req.body);
            return console.log(error.stack);
        }
    });
};

<commit_msg>QA notification formatting<commit_after>'use strict';

/*
 # Notifies about Jenkins build errors via Jenkins Notification Plugin
 #
 # Dependencies:
 #   "url": ""
 #   "querystring": ""
 #
 # Configuration:
 #   Just put this url <HUBOT_URL>:<PORT>/hubot/jenkins-notify?room=<room> to your Jenkins
 #   Notification config. See here: https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
 #
 # Commands:
 #   None
 #
 # URLS:
 #   POST /hubot/jenkins-notify?room=<room>[&type=<type>]
 #
 # Authors:
 #   spajus
 */

var http, querystring, url;
url = require('url');
querystring = require('querystring');
http = require('http');

var IntervalMinutes = 30;
var MaxSoundsPerInterval = 2;//For any given interval, there will be no more than this number of jenkins sounds
//10 - 1 = One Sound per ten minutes

var soundsSoFar = 0;

function makeSound (urlOfSound) {
    if (!(/http/.test(urlOfSound))) {
        urlOfSound = 'http://xserve:5051/' + urlOfSound;
    }

    if (soundsSoFar >= MaxSoundsPerInterval) {
        console.log('Declining to make a sound: %s', urlOfSound);
        return;
    }
    soundsSoFar += 1;
    setTimeout(function () {
        soundsSoFar -= 1;
    }, IntervalMinutes * 60 * 1000);

    http.get(urlOfSound, function(res) {
        return console.log(res.statusCode);
    });
}

module.exports = function(robot) {

    var foo = {};

    return robot.router.post("/hubot/jenkins-notify", function(req, res) {
        var build, data, envelope, query, room;
        foo.failing = foo.failing || [];
        query = querystring.parse(url.parse(req.url).query);
        res.end('');
        envelope = {};
        envelope.user = {};
        if (query.room) {
            envelope.room = query.room;
        }
        if (query.type) {
            envelope.user.type = query.type;
        }
        room = 'dev';
        try {
            data = req.body;
            console.log("BUILD: " + data.name + " - #" + data.build.number + ": " + data.build.status);
            if (data.build.phase === 'STARTED') {
                if (data.name.match(/mothra.*qa/i)) {
                    makeSound('mothra-qa');
                }
            }
            if (data.build.phase === 'COMPLETED') {
                if (data.name.match(/.*qa.*/i) && !data.name.match(/.*selenium.*/i)) {
                   console.log("Notifying QA");
                   robot.messageRoom('#qa', "" + data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url);
                }
                if (data.build.status === 'FAILURE') {
                    console.log("Failure");
                    if (foo.failing.indexOf(data.name) >= 0) {
                        build = "is still";
                    } else {
                        build = "started";
                    }
                    robot.messageRoom(room, "" + data.name + " build #" + data.build.number + " " + build + " failing (" + (encodeURI(data.build.full_url)) + ")");
                    if (foo.failing.indexOf(data.name) < 0) {
                        foo.failing.push(data.name);
                    }
                    if (data.name.match(/mothra.*qa/i)) {
                        console.log("MOTHRA!!");
                        console.log(res.statusCode);
                        robot.messageRoom('#dev', "Mothra has the upper hand!");
                        robot.messageRoom('#dev', "http://i.imgur.com/CoqJxBx.gif");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        console.log("MECHA GODZILLA!!!!");
                        console.log(res.statusCode);
                        makeSound('mechawins');
                        robot.messageRoom('qa-chat', "Mecha Godzilla is winning!");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/LkziC7bd1yLUk/giphy.gif");
                    }
                }
                if (data.build.status === 'SUCCESS') {
                    console.log("Success");
                    if (data.name === '1stdibs.com Deploy Production PROD PROD PROD PROD') {
                        makeSound('shipit');
                        robot.messageRoom("#release", "1stdibs.com hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'Admin-v2 Deploy (PROD)') {
                        makeSound('shipit-adminv2');
                        robot.messageRoom("#release", "Admin v2 hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'Admin-v1 Deploy (PROD) (RACKSPACE)') {
                        makeSound('shipit-adminv1');
                        robot.messageRoom("#release", "Admin v1 hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'JAVA-InventoryService (Prod)') {
                        makeSound('shipit-inventory');
                        robot.messageRoom("#release", "Inventory service hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.name === 'JAVA-IdentityService (Prod)') {
                        makeSound('shipit-identity');
                        robot.messageRoom("#release", "Identity service hotfix has been release!");
                        robot.messageRoom("#release", "I hope you know what you're doing...");
                    }
                    if (data.build && data.build.parameters && data.build.parameters.SERVER_HOSTNAME === 'deathstar.1stdibs.com') {
                        makeSound('deathstar');
                        robot.messageRoom("#dev", "The Death Star is now fully armed and operational");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        console.log("MECHA GODZILLA!!!!");
                        console.log(res.statusCode);
                        makeSound('mechaloses');
                        robot.messageRoom('qa-chat', "Mecha Godzilla has been defeated!");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/33T28J1KEkRq0/giphy.gif");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/yygLBxnwBVynu/giphy.gif");
                        robot.messageRoom('qa-chat', "http://media.giphy.com/media/tEgJl9nSsfTGM/giphy.gif");
                    }
                }
            }
        } catch (error) {
            console.log("jenkins-notify error: " + error + ". Data: " + req.body);
            return console.log(error.stack);
        }
    });
};

<|endoftext|>


<commit_before>// Notifies about Jenkins build errors via Jenkins Notification Plugin
//
// Dependencies:
//   "url": ""
//   "querystring": ""
//   "colors" : ""
//
// Configuration:
//   Just put this url <HUBOT_URL>:<PORT>/hubot/jenkins-notify?room=<room> to your Jenkins
//   Notification config. See here: https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
//
// Commands:
//   None
//
// URLS:
//   POST /hubot/jenkins-notify?room=<room>[&type=<type>]
//
// Authors:
//   spajus, cmckendry, andromedado, JasonSmiley

var url = require('url');
var querystring = require('querystring');
var http = require('http');
var colors = require('colors');
var util = require('util');
var moment = require('moment');

var DeDupeSounds = true;//If True, then, for example, mothra may only place once per "IntervalMinutes"
var IntervalMinutes = 30;
var MaxSoundsPerInterval = 2;//For any given interval, there will be no more than this number of jenkins sounds
//10 - 1 = One Sound per ten minutes
//30 - 2 = For any given half hour, at most two sounds will play
var soundsSoFar = 0;
var deDuper = {};

// Extra requirements for spreadsheet auto-updater
var GoogleSpreadsheet = require('google-spreadsheet');
var async = require('async');
var doc = new GoogleSpreadsheet('1EJzQgI1JMdjM8CWF5s-4mQOuR_dTGvn7VsoGQbc8wSM');
var sheet;

// if it's not QA, Stage, or Prod, then the spreadsheet doesn't care
var important = /(?:[^A-Za-z])?(QA|Stag(e|ing)|Prod)/i;
var sanitize = /(JAVA-)|(service)|(\(.*\))|node|(1st)?dibs|deploy|\s|-|QA|Stag(e|ing)|Prod/ig;

var weeklyProdDeployables = ['.com', 'admin-v1', 'admin-v2', 'AnalyticsService', 'BossService', 'Bridgekeeper', 'CMS Dealer Storefront', 'CMS Trade Internal', 'ConfigService', 'EcomService', 'Formservice (clump)', 'GraphQL', 'IdentityService', 'Internal Customer Lookup', 'Internal Inventory Management', 'Internal OMT', 'Internal Statement', 'InventoryService', 'LogisticsService', 'MediaService', 'MessageCenterService', 'TradeService', 'UsercommService'];

var logger = (function () {
    var logger = require('./support/logger');
    logger.buildSound = function (what) {
        var args = [].slice.call(arguments);
        if (args.length > 1) {
            what = util.format.apply(util, arguments);
        }
        var str = util.format('[%d/%d Build Sounds]'.cyan, soundsSoFar, MaxSoundsPerInterval);
        console.log('%s : %s', str, what);
        if (DeDupeSounds) {
            logger.minorInfo(JSON.stringify(deDuper));
        }
    };
    return logger;
}());

function makeSound (urlOfSound) {
    if (!(/http/.test(urlOfSound))) {
        urlOfSound = 'http://xserve:5051/' + urlOfSound;
    }

    if (soundsSoFar >= MaxSoundsPerInterval) {
        logger.buildSound('No available slots for %s', urlOfSound);
        return;
    }
    if (DeDupeSounds && deDuper[urlOfSound]) {
        logger.buildSound('Enforcing de-dupe for %s', urlOfSound);
        return;
    }
    deDuper[urlOfSound] = new Date();
    soundsSoFar += 1;
    logger.buildSound('Slot taken by %s', urlOfSound);
    setTimeout(function () {
        soundsSoFar -= 1;
        deDuper[urlOfSound] = void 0;
        logger.buildSound('Slot opened up!');
    }, IntervalMinutes * 60 * 1000);

    http.get(urlOfSound, function(res) {
        return logger.requestResolution(urlOfSound, res.statusCode);
    });
}

module.exports = function(robot) {

    var foo = {};

    return robot.router.post("/hubot/jenkins-notify", function(req, res) {
        var build, data, envelope, query, room, params;
        foo.failing = foo.failing || [];
        query = querystring.parse(url.parse(req.url).query);
        res.end('');
        envelope = {};
        envelope.user = {};
        if (query.room) {
            envelope.room = query.room;
        }
        if (query.type) {
            envelope.user.type = query.type;
        }
        room = 'C02FRPJJ5';
        try {
            data = req.body;
            params = (data && data.parameters) || {};
            logger.build('%s - #%s: %s', data.name, data.build.number, (data.build.status || data.build.phase || '[unknown state]'));
            if (data.build.phase === 'STARTED') {
                //nothing here for now
            }
            if (data.build.phase === 'COMPLETED') {
                // Notify QA when QA builds complete
                if (data.name.match(/.*qa.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying QA: %s", qaMsg);
                    robot.messageRoom('C1MH5A8TU', qaMsg);
                }
                // Notify QA on certain custom builds
                if (data.name.match(/.*custom.*/i) || data.name.match(/.*any.*/i) || data.name.match(/.*statement.*/i) || data.name.match(/.*customer.*/i) || data.name.match(/.*nodegraphql.*/i) || data.name.match(/.*cmsTrade.*/i)) {
                    var params = data.build.parameters ? data.build.parameters : {};
                    var serverName = params.SERVER_HOSTNAME ? params.SERVER_HOSTNAME : params.SERVER_NAME + '.intranet.1stdibs.com';
                    var customMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    var customDetails = "↳ built " + params.BRANCH_NAME + " to " + serverName;
                    logger.minorInfo("Custom build: %s", params.SERVER_HOSTNAME);
                    logger.minorInfo("Custom build: %s", params.BRANCH_NAME);
                    robot.messageRoom('C1MH5A8TU', customMsg);
                    robot.messageRoom('C1MH5A8TU', customDetails);
                    // Notify Goods team on imperial custom builds
                 //   if (serverName.match(/.*deathstar.*/i) || serverName.match(/.*goods.*/i) || serverName.match(/.*stardestroyer.*/i)) {
                 //       robot.messageRoom('goods', customMsg);
                 //       robot.messageRoom('goods', customDetails);
                 //   }
                }
                // Notify the release channel when stage or prod get built
                var releaseRoom = 'C24UWKLR0';
                if (data.name.match(/.*stage.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }
                if (data.name.match(/.*prod.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i) && !data.name.match(/.*everything except.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }
                if (data.name.match(/.*hotfix.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }

                if (data.build.status === 'FAILURE') {
                    if (foo.failing.indexOf(data.name) >= 0) {
                        build = "is still";
                    } else {
                        build = "started";
                    }
                    robot.messageRoom(room, "" + data.name + " build #" + data.build.number + " " + build + " failing (" + (encodeURI(data.build.full_url)) + ")");
                    if (foo.failing.indexOf(data.name) < 0) {
                        foo.failing.push(data.name);
                    }
                    if (data.name.match(/mothra.*qa/i)) {
                        robot.messageRoom('C02FRPJJ5', "Mothra has the upper hand!");
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/CoqJxBx.gif");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        makeSound('mechawins');
                        robot.messageRoom('C02FRPJJ5', "Mecha Godzilla is winning!:poop::poop::poop:");
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/AoeZXir.gif");
                    }
                }
                if (data.build.status === 'SUCCESS') {
                    // Text and audio notifications
                    if (data.name === 'Weekly Production Release') {
                        makeSound('shipit');
                        robot.messageRoom('C02FZMJLL', '1stdibs weekly production release is complete!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === '1stdibs.com Deploy Production PROD PROD PROD PROD' && params.Hotfix === 'true') {
                        makeSound('shipit');
                        robot.messageRoom('C02FZMJLL', '1stdibs.com hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'Admin-v2 Deploy (PROD)' && params.Hotfix === 'true') {
                        makeSound('shipit-adminv2');
                        robot.messageRoom('C02FZMJLL', 'Admin v2 hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'Admin-v1 Deploy (PROD) (RACKSPACE)' && params.Hotfix === 'true') {
                        makeSound('shipit-adminv1');
                        robot.messageRoom('C02FZMJLL', 'Admin v1 hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'JAVA-InventoryService (Hotfix to Prod)') {
                        makeSound('shipit-inventory');
                        robot.messageRoom('C02FZMJLL', 'Inventory service hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'JAVA-IdentityService (Hotfix to Prod)') {
                        makeSound('shipit-identity');
                        robot.messageRoom('C02FZMJLL', 'Identity service hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.build && data.build.parameters && data.build.parameters.SERVER_HOSTNAME === 'deathstar.1stdibs.com') {
                        makeSound('deathstar');
                        robot.messageRoom('C02FRPJJ5', 'The Death Star is now fully armed and operational');
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        makeSound('mechaloses');
                        robot.messageRoom('C02FRPJJ5', 'Mecha Godzilla has been defeated!:excited_tomato::excited_tomato::excited_tomato:');
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/t8tLizl.gif");
                    }
                    if (data.name === 'Mothra-Ecom (QA)') {
                        makeSound('mothra-qa');
                    }
                    ///////////////////////////////////
                    // Spreadsheet auto-updater logic
                    ///////////////////////////////////
                    var params = data.build.parameters ? data.build.parameters : {};
                    var serverName = params.SERVER_HOSTNAME ? params.SERVER_HOSTNAME : params.SERVER_NAME + '.intranet.1stdibs.com';
                    if (data.name.match(important) || serverName.match(important) ) {
                        var weeklyProdJob = data.name === 'Weekly Production Release';
                        var envName = data.name.match(important) ? data.name.match(important)[1] : serverName.match(important)[1];
                        console.log('Matchy thing: ' + envName);
                        console.log('SREADSHEET -- An important build has completed!');
                        var sheet;
                        var simpleBuildName = data.name.replace(sanitize,'');
                        async.series([
                            function setAuth(step) {
                                var creds = require('/etc/pm2/google-generated-creds.json');
                                console.log(creds);
                                doc.useServiceAccountAuth(creds, step);
                                console.log('xxxxxxxx');
                            },
                            function debugLog(step) {
                                console.log('SPREADSHEET -- Debug step executing');
                                step();
                            },
                            function debugWorksheetInfo(step) {
                                console.log('SPREADSHEET -- Debug worksheet info:');
                                doc.getInfo(function (err, info) {
                                    console.log('SREADSHEET -- Loaded doc: ' + info.title + ' by ' + info.author.email);
                                    sheet = info.worksheets[0];
                                    console.log('SREADSHEET -- sheet 1: ' + sheet.title + ' ' + sheet.rowCount + 'x' + sheet.colCount);
                                    step();
                                });
                            },
                            function updateMatchingRows(step) {
                                sheet.getCells({
                                    'min-row': 1,
                                    //'max-row': 1,
                                    'return-empty': true
                                }, function (err, cells) {
                                    //console.log(cells);
                                    for (var i = 0; i < cells.length; i++) {
                                        var cell = cells[i];
                                        if (cell.col === 1 && cell.value.length > 0) {
                                            console.log('SREADSHEET -- Cell R' + cell.row + 'C' + cell.col + ' = ' + cell.value);
                                            //if (cell.value === 'Identity') {
                                            var fullName = cell.value;
                                            var simpleRowName = cell.value.replace(sanitize,'');
                                            console.log('Simplified spreadsheet name: ' + simpleRowName);
                                            console.log('Simplified build name: ' + simpleBuildName);
                                            if ((simpleRowName.toLowerCase() === (simpleBuildName.toLowerCase())) || (weeklyProdJob && (weeklyProdDeployables.indexOf(cell.value) > -1))) {
                                                var releaseStatus = cells[i + 1];
                                                var releaseTime = cells[i + 2];
                                                var localFullName = cell.value;
                                                var newReleaseTime = moment().format('YYYY-M-D HH:mm');
                                                console.log('Old release status: ' + releaseStatus.value);
                                                console.log('New release status: ' + envName);
                                                console.log('Release time: ' + newReleaseTime);
                                                releaseStatus.value = envName;
                                                releaseTime.value = newReleaseTime;
                                                console.log('SPREADSHEET -- Going to update: ' + cell.value + ' to ' + releaseStatus.value);
                                                releaseStatus.save(function () { console.log('SPREADSHEET -- Successfully updated ' + localFullName + ' to ' + releaseStatus.value); });
                                                releaseTime.save(function () { console.log('SPREADSHEET -- Successfully logged release time as ' + releaseTime.value); });
                                            }
                                        }
                                    }
                                    step();
                                });
                            }
                        ]);
                    }
                }
            }
        } catch (error) {
            logger.error(error, req.body);
        }
    });
};

<commit_msg>Spreadsheet: log build branches<commit_after>// Notifies about Jenkins build errors via Jenkins Notification Plugin
//
// Dependencies:
//   "url": ""
//   "querystring": ""
//   "colors" : ""
//
// Configuration:
//   Just put this url <HUBOT_URL>:<PORT>/hubot/jenkins-notify?room=<room> to your Jenkins
//   Notification config. See here: https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin
//
// Commands:
//   None
//
// URLS:
//   POST /hubot/jenkins-notify?room=<room>[&type=<type>]
//
// Authors:
//   spajus, cmckendry, andromedado, JasonSmiley

var url = require('url');
var querystring = require('querystring');
var http = require('http');
var colors = require('colors');
var util = require('util');
var moment = require('moment');

var DeDupeSounds = true;//If True, then, for example, mothra may only place once per "IntervalMinutes"
var IntervalMinutes = 30;
var MaxSoundsPerInterval = 2;//For any given interval, there will be no more than this number of jenkins sounds
//10 - 1 = One Sound per ten minutes
//30 - 2 = For any given half hour, at most two sounds will play
var soundsSoFar = 0;
var deDuper = {};

// Extra requirements for spreadsheet auto-updater
var GoogleSpreadsheet = require('google-spreadsheet');
var async = require('async');
var doc = new GoogleSpreadsheet('1EJzQgI1JMdjM8CWF5s-4mQOuR_dTGvn7VsoGQbc8wSM');
var sheet;

// if it's not QA, Stage, or Prod, then the spreadsheet doesn't care
var important = /(?:[^A-Za-z])?(QA|Stag(e|ing)|Prod)/i;
var sanitize = /(JAVA-)|(service)|(\(.*\))|node|(1st)?dibs|deploy|\s|-|QA|Stag(e|ing)|Prod/ig;

var weeklyProdDeployables = ['.com', 'admin-v1', 'admin-v2', 'AnalyticsService', 'BossService', 'Bridgekeeper', 'CMS Dealer Storefront', 'CMS Trade Internal', 'ConfigService', 'EcomService', 'Formservice (clump)', 'GraphQL', 'IdentityService', 'Internal Customer Lookup', 'Internal Inventory Management', 'Internal OMT', 'Internal Statement', 'InventoryService', 'LogisticsService', 'MediaService', 'MessageCenterService', 'TradeService', 'UsercommService'];

var logger = (function () {
    var logger = require('./support/logger');
    logger.buildSound = function (what) {
        var args = [].slice.call(arguments);
        if (args.length > 1) {
            what = util.format.apply(util, arguments);
        }
        var str = util.format('[%d/%d Build Sounds]'.cyan, soundsSoFar, MaxSoundsPerInterval);
        console.log('%s : %s', str, what);
        if (DeDupeSounds) {
            logger.minorInfo(JSON.stringify(deDuper));
        }
    };
    return logger;
}());

function makeSound (urlOfSound) {
    if (!(/http/.test(urlOfSound))) {
        urlOfSound = 'http://xserve:5051/' + urlOfSound;
    }

    if (soundsSoFar >= MaxSoundsPerInterval) {
        logger.buildSound('No available slots for %s', urlOfSound);
        return;
    }
    if (DeDupeSounds && deDuper[urlOfSound]) {
        logger.buildSound('Enforcing de-dupe for %s', urlOfSound);
        return;
    }
    deDuper[urlOfSound] = new Date();
    soundsSoFar += 1;
    logger.buildSound('Slot taken by %s', urlOfSound);
    setTimeout(function () {
        soundsSoFar -= 1;
        deDuper[urlOfSound] = void 0;
        logger.buildSound('Slot opened up!');
    }, IntervalMinutes * 60 * 1000);

    http.get(urlOfSound, function(res) {
        return logger.requestResolution(urlOfSound, res.statusCode);
    });
}

module.exports = function(robot) {

    var foo = {};

    return robot.router.post("/hubot/jenkins-notify", function(req, res) {
        var build, data, envelope, query, room, params;
        foo.failing = foo.failing || [];
        query = querystring.parse(url.parse(req.url).query);
        res.end('');
        envelope = {};
        envelope.user = {};
        if (query.room) {
            envelope.room = query.room;
        }
        if (query.type) {
            envelope.user.type = query.type;
        }
        room = 'C02FRPJJ5';
        try {
            data = req.body;
            params = (data && data.parameters) || {};
            logger.build('%s - #%s: %s', data.name, data.build.number, (data.build.status || data.build.phase || '[unknown state]'));
            if (data.build.phase === 'STARTED') {
                //nothing here for now
            }
            if (data.build.phase === 'COMPLETED') {
                // Notify QA when QA builds complete
                if (data.name.match(/.*qa.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying QA: %s", qaMsg);
                    robot.messageRoom('C1MH5A8TU', qaMsg);
                }
                // Notify QA on certain custom builds
                if (data.name.match(/.*custom.*/i) || data.name.match(/.*any.*/i) || data.name.match(/.*statement.*/i) || data.name.match(/.*customer.*/i) || data.name.match(/.*nodegraphql.*/i) || data.name.match(/.*cmsTrade.*/i)) {
                    var params = data.build.parameters ? data.build.parameters : {};
                    var serverName = params.SERVER_HOSTNAME ? params.SERVER_HOSTNAME : params.SERVER_NAME + '.intranet.1stdibs.com';
                    var customMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    var customDetails = "↳ built " + params.BRANCH_NAME + " to " + serverName;
                    logger.minorInfo("Custom build: %s", params.SERVER_HOSTNAME);
                    logger.minorInfo("Custom build: %s", params.BRANCH_NAME);
                    robot.messageRoom('C1MH5A8TU', customMsg);
                    robot.messageRoom('C1MH5A8TU', customDetails);
                    // Notify Goods team on imperial custom builds
                 //   if (serverName.match(/.*deathstar.*/i) || serverName.match(/.*goods.*/i) || serverName.match(/.*stardestroyer.*/i)) {
                 //       robot.messageRoom('goods', customMsg);
                 //       robot.messageRoom('goods', customDetails);
                 //   }
                }
                // Notify the release channel when stage or prod get built
                var releaseRoom = 'C24UWKLR0';
                if (data.name.match(/.*stage.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }
                if (data.name.match(/.*prod.*/i) && !data.name.match(/.*selenium.*/i) && !data.name.match(/.*godzilla.*/i) && !data.name.match(/.*everything except.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }
                if (data.name.match(/.*hotfix.*/i)) {
                    var qaMsg = data.name + " build #" + data.build.number + " : " + data.build.status + " -- " + data.build.full_url;
                    logger.minorInfo("Notifying Release Channel: %s", qaMsg);
                    robot.messageRoom(releaseRoom, qaMsg);
                }

                if (data.build.status === 'FAILURE') {
                    if (foo.failing.indexOf(data.name) >= 0) {
                        build = "is still";
                    } else {
                        build = "started";
                    }
                    robot.messageRoom(room, "" + data.name + " build #" + data.build.number + " " + build + " failing (" + (encodeURI(data.build.full_url)) + ")");
                    if (foo.failing.indexOf(data.name) < 0) {
                        foo.failing.push(data.name);
                    }
                    if (data.name.match(/mothra.*qa/i)) {
                        robot.messageRoom('C02FRPJJ5', "Mothra has the upper hand!");
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/CoqJxBx.gif");
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        makeSound('mechawins');
                        robot.messageRoom('C02FRPJJ5', "Mecha Godzilla is winning!:poop::poop::poop:");
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/AoeZXir.gif");
                    }
                }
                if (data.build.status === 'SUCCESS') {
                    // Text and audio notifications
                    if (data.name === 'Weekly Production Release') {
                        makeSound('shipit');
                        robot.messageRoom('C02FZMJLL', '1stdibs weekly production release is complete!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === '1stdibs.com Deploy Production PROD PROD PROD PROD' && params.Hotfix === 'true') {
                        makeSound('shipit');
                        robot.messageRoom('C02FZMJLL', '1stdibs.com hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'Admin-v2 Deploy (PROD)' && params.Hotfix === 'true') {
                        makeSound('shipit-adminv2');
                        robot.messageRoom('C02FZMJLL', 'Admin v2 hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'Admin-v1 Deploy (PROD) (RACKSPACE)' && params.Hotfix === 'true') {
                        makeSound('shipit-adminv1');
                        robot.messageRoom('C02FZMJLL', 'Admin v1 hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'JAVA-InventoryService (Hotfix to Prod)') {
                        makeSound('shipit-inventory');
                        robot.messageRoom('C02FZMJLL', 'Inventory service hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.name === 'JAVA-IdentityService (Hotfix to Prod)') {
                        makeSound('shipit-identity');
                        robot.messageRoom('C02FZMJLL', 'Identity service hotfix has been released!');
                        robot.messageRoom('C02FZMJLL', 'I hope you know what you\'re doing...');
                    }
                    if (data.build && data.build.parameters && data.build.parameters.SERVER_HOSTNAME === 'deathstar.1stdibs.com') {
                        makeSound('deathstar');
                        robot.messageRoom('C02FRPJJ5', 'The Death Star is now fully armed and operational');
                    }
                    if (data.name === 'MechaGodzilla .com (Prod)') {
                        makeSound('mechaloses');
                        robot.messageRoom('C02FRPJJ5', 'Mecha Godzilla has been defeated!:excited_tomato::excited_tomato::excited_tomato:');
                        robot.messageRoom('C02FRPJJ5', "http://i.imgur.com/t8tLizl.gif");
                    }
                    if (data.name === 'Mothra-Ecom (QA)') {
                        makeSound('mothra-qa');
                    }
                    ///////////////////////////////////
                    // Spreadsheet auto-updater logic
                    ///////////////////////////////////
                    var params = data.build.parameters ? data.build.parameters : {};
                    var serverName = params.SERVER_HOSTNAME ? params.SERVER_HOSTNAME : params.SERVER_NAME + '.intranet.1stdibs.com';
                    if (data.name.match(important) || serverName.match(important) ) {
                        var weeklyProdJob = data.name === 'Weekly Production Release';
                        var envName = data.name.match(important) ? data.name.match(important)[1] : serverName.match(important)[1];
                        var buildBranch = data.build.scm.branch;
                        console.log('Matchy thing: ' + envName);
                        console.log('SREADSHEET -- An important build has completed!');
                        var sheet;
                        var simpleBuildName = data.name.replace(sanitize,'');
                        async.series([
                            function setAuth(step) {
                                var creds = require('/etc/pm2/google-generated-creds.json');
                                console.log(creds);
                                doc.useServiceAccountAuth(creds, step);
                                console.log('xxxxxxxx');
                            },
                            function debugLog(step) {
                                console.log('SPREADSHEET -- Debug step executing');
                                step();
                            },
                            function debugWorksheetInfo(step) {
                                console.log('SPREADSHEET -- Debug worksheet info:');
                                doc.getInfo(function (err, info) {
                                    console.log('SREADSHEET -- Loaded doc: ' + info.title + ' by ' + info.author.email);
                                    sheet = info.worksheets[0];
                                    console.log('SREADSHEET -- sheet 1: ' + sheet.title + ' ' + sheet.rowCount + 'x' + sheet.colCount);
                                    step();
                                });
                            },
                            function updateMatchingRows(step) {
                                sheet.getCells({
                                    'min-row': 1,
                                    //'max-row': 1,
                                    'return-empty': true
                                }, function (err, cells) {
                                    //console.log(cells);
                                    for (var i = 0; i < cells.length; i++) {
                                        var cell = cells[i];
                                        if (cell.col === 1 && cell.value.length > 0) {
                                            console.log('SREADSHEET -- Cell R' + cell.row + 'C' + cell.col + ' = ' + cell.value);
                                            //if (cell.value === 'Identity') {
                                            var fullName = cell.value;
                                            var simpleRowName = cell.value.replace(sanitize,'');
                                            console.log('Simplified spreadsheet name: ' + simpleRowName);
                                            console.log('Simplified build name: ' + simpleBuildName);
                                            if ((simpleRowName.toLowerCase() === (simpleBuildName.toLowerCase())) || (weeklyProdJob && (weeklyProdDeployables.indexOf(cell.value) > -1))) {
                                                var releaseStatus = cells[i + 1];
                                                var releaseTime = cells[i + 2];
                                                var releaseBranch = cells[i + 3];
                                                var localFullName = cell.value;
                                                var newReleaseTime = moment().format('YYYY-M-D HH:mm');
                                                console.log('Old release status: ' + releaseStatus.value);
                                                console.log('New release status: ' + envName);
                                                console.log('Release time: ' + newReleaseTime);
                                                releaseStatus.value = envName;
                                                releaseTime.value = newReleaseTime;
                                                releaseBranch.value = buildBranch;
                                                console.log('SPREADSHEET -- Going to update: ' + cell.value + ' to ' + releaseStatus.value);
                                                releaseStatus.save(function () { console.log('SPREADSHEET -- Successfully updated ' + localFullName + ' to ' + releaseStatus.value); });
                                                releaseTime.save(function () { console.log('SPREADSHEET -- Successfully logged release time as ' + releaseTime.value); });
                                                releaseBranch.save(function () { console.log('SPREADSHEET -- Successfully logged release branch as ' + releaseBranch.value); });
                                            }
                                        }
                                    }
                                    step();
                                });
                            }
                        ]);
                    }
                }
            }
        } catch (error) {
            logger.error(error, req.body);
        }
    });
};

<|endoftext|>