<commit_before>import Phaser from 'phaser'

import Player from '../sprites/Player'
import Turret from '../sprites/Turret'

import { enableMusicForState } from '../utils.js'

export default class extends Phaser.State {
  init (fightTileMap) {
    this.fightTileMap = fightTileMap
  }

  create () {
    this.disableMusic = enableMusicForState('bigbeat', this)

    this.game.world.enableBody = true
    this.game.physics.startSystem(Phaser.Physics.ARCADE)
    this.game.curve.setPoints([50, 0, 0, 0, 50])

    this.map = this.game.add.tilemap('earth_travel')
    this.map.addTilesetImage('lofi_environment_4x', 'tiles')

    // Add both the background and ground layers. We won't be doing anything
    // with the GroundLayer though
    this.backgroundLayer = this.map.createLayer('backgroundlayer')
    this.backgroundLayer.resizeWorld()

    this.groundLayer = this.map.createLayer('groundlayer')
    this.map.setCollisionBetween(1, 1000, true, 'groundlayer')

    // Add the sprite to the game and enable arcade physics on it
    this.player = new Player(this.game, 100, 256, { canTurn: false, isFalling: true })
    this.world.add(this.player)
    this.player.body.gravity.x = 1800

    // Add turrets.
    new Array( // Use new Array instead of [] so webpack does not get confused.
      [  600, 100, {target: this.player, burst: true}],
      [ 7200, 100, {target: this.player, burst: false}],
      [ 9600, 100, {target: this.player, burst: true}],
      [10560, 300, {target: this.player, burst: true}],
      [11200, 200, {target: this.player, burst: true}],
      [11800, 300, {target: this.player, burst: true}],
      [11904, 100, {target: this.player, burst: true}],
      [14720, 100],
      [20384, 256, {target: this.player, burst: true, homing: true}]
    ).forEach(([x, y, options]) =>
      this.world.add(new Turret(this.game, this.player, x, y, 80, 179, options)))

    // Make the camera follow the sprite
    // FIXME: replaced with ugly hack to only travel on x-axis for the presenatation.
    // this.game.camera.follow(this.player)
    this.game.camera.setPosition(0, 0)

    this.game.scale.pageAlignHorizontally = true
    this.game.scale.pageAlignVertically = true
    this.game.scale.refresh()

    this.game.time.advancedTiming = true

    this.player.body.collideWorldBounds = true
    this.player.body.onWorldBounds = new Phaser.Signal()
    this.player.body.onWorldBounds.add(this.hitWorldBounds, this)
  }

  render () {
    this.game.debug.text(this.time.fps, 10, 20, '#00ff00')
    this.game.debug.text(this.game.deathCounter, 980, 20, '#00ff00')
  }

  update () {
    this.game.camera.x = this.player.x - this.game.width / 2
    this.game.physics.arcade.collide(this.player, this.groundLayer, this.player.resetWithAnimation, null, this.player)
  }

  shutdown () {
    this.disableMusic()
  }

  hitWorldBounds (sprite, up, down, left, right) {
    if (sprite === this.player && right === true) {
      this.game.state.start('Fight', true, false, this.fightTileMap)
    }
  }
}
<commit_msg>Rework player movement in Travel.<commit_after>import Phaser from 'phaser'

import Player from '../sprites/Player'
import Turret from '../sprites/Turret'

import { enableMusicForState } from '../utils.js'

export default class extends Phaser.State {
  init (fightTileMap) {
    this.fightTileMap = fightTileMap
  }

  create () {
    this.disableMusic = enableMusicForState('bigbeat', this)

    this.game.world.enableBody = true
    this.game.physics.startSystem(Phaser.Physics.ARCADE)
    this.game.curve.setPoints([50, 0, 0, 0, 50])

    this.map = this.game.add.tilemap('earth_travel')
    this.map.addTilesetImage('lofi_environment_4x', 'tiles')

    // Add both the background and ground layers. We won't be doing anything
    // with the GroundLayer though
    this.backgroundLayer = this.map.createLayer('backgroundlayer')
    this.backgroundLayer.resizeWorld()

    this.groundLayer = this.map.createLayer('groundlayer')
    this.map.setCollisionBetween(1, 1000, true, 'groundlayer')

    // Add the sprite to the game and enable arcade physics on it
    this.player = new Player(this.game, 100, 256, { canTurn: false, isFalling: true })
    this.world.add(this.player)

    // Player physics in this state.
    this.maxVelocity = 800 // Default max velocity, can be overridden by dashing.
    this.player.body.maxVelocity.x = this.maxVelocityX
    this.player.body.maxVelocity.y = this.maxVelocity
    this.player.body.gravity.x = 1800

    this.player.body.collideWorldBounds = true
    this.player.body.onWorldBounds = new Phaser.Signal()
    this.player.body.onWorldBounds.add(this.hitWorldBounds, this)

    // Add turrets.
    new Array( // Use new Array instead of [] so webpack does not get confused.
      [  600, 100, {target: this.player, burst: true}],
      [ 7200, 100, {target: this.player, burst: false}],
      [ 9600, 100, {target: this.player, burst: true}],
      [10560, 300, {target: this.player, burst: true}],
      [11200, 200, {target: this.player, burst: true}],
      [11800, 300, {target: this.player, burst: true}],
      [11904, 100, {target: this.player, burst: true}],
      [14720, 100],
      [20384, 256, {target: this.player, burst: true, homing: true}]
    ).forEach(([x, y, options]) =>
      this.world.add(new Turret(this.game, this.player, x, y, 80, 179, options)))

    // Make the camera follow the sprite
    // FIXME: replaced with ugly hack to only travel on x-axis for the presenatation.
    // this.game.camera.follow(this.player)
    this.game.camera.setPosition(0, 0)

    this.game.scale.pageAlignHorizontally = true
    this.game.scale.pageAlignVertically = true
    this.game.scale.refresh()

    this.game.time.advancedTiming = true
  }

  render () {
    this.game.debug.text(this.time.fps, 10, 20, '#00ff00')
    this.game.debug.text(this.game.deathCounter, 980, 20, '#00ff00')
  }

  update () {
    this.game.camera.x = this.player.x - this.game.width / 2
    this.game.physics.arcade.collide(this.player, this.groundLayer, this.player.resetWithAnimation, null, this.player)

    const accY = 800
    if (this.player.isMovingUp()) {
      this.player.body.velocity.y -= accY
    } else if (this.player.isMovingDown()) {
      this.player.body.velocity.y += accY
    } else {
      this.player.body.velocity.y /= 2
    }

    const accX = 360
    if (this.player.isMovingRight()) {
      this.player.body.maxVelocity.x = this.maxVelocity + accX
      this.player.body.velocity.x += accX
    } else if (this.player.isMovingLeft()) {
      this.player.body.maxVelocity.x = this.maxVelocity - accX
      this.player.body.velocity.x -= accX / 6 // Braking takes time.
    } else {
      this.player.body.maxVelocity.x = this.maxVelocity
    }
  }

  shutdown () {
    this.disableMusic()
  }

  hitWorldBounds (sprite, up, down, left, right) {
    if (sprite === this.player && right === true) {
      this.game.state.start('Fight', true, false, this.fightTileMap)
    }
  }
}
<|endoftext|>


<commit_before>const JlTransform = require('./JlTransform');
const Readable = require('stream').Readable;
const Join = require('../Join');

class Joiner extends Readable
{
	/**
	 *
	 * @param {Join} join
	 */
	constructor(join, mainValueCb, mainStreamSorted, joiningValueCb, joiningStreamSorted)
	{
		super({objectMode: true});

		this.inputType = JlTransform.ARRAYS_OF_OBJECTS;
		this.outputType = JlTransform.ARRAYS_OF_OBJECTS;

		this.join = join;
		this.mainStreamSorted = mainStreamSorted;
		this.joiningStreamSorted = joiningStreamSorted;

		this.mainValueCb = mainValueCb;
		this.joiningValueCb = joiningValueCb;

		this.currentKey = undefined;
		this.currentKeyMainRow = undefined;
		this.currentKeyBuffer = [];

		this.maxBufferSize = 16;
		this.mainBuffer = [];
		this.joiningBuffer = [];

		this.needOutput = false;

		this.mainEnded = false;
		this.joiningEnded = false;

		this.ended = false;

		mainStreamSorted.on('data', this.mainStreamData.bind(this));
		mainStreamSorted.on('end', this.mainStreamEnd.bind(this));
		joiningStreamSorted.on('data', this.joiningStreamData.bind(this));
		joiningStreamSorted.on('end', this.joiningStreamEnd.bind(this));
	}

	mainStreamData(data)
	{
		this.mainBuffer = this.mainBuffer.concat(data);

		if (this.mainBuffer.length >= this.maxBufferSize) {
			this.mainStreamSorted.pause();
		}

		this.dataChanged();
	}

	mainStreamEnd()
	{
		this.mainEnded = true;
		this.needOutput = true;

		this.dataChanged();
	}

	joiningStreamData(data)
	{
		this.joiningBuffer = this.joiningBuffer.concat(data);

		if (this.joiningBuffer.length >= this.maxBufferSize) {
			this.joiningStreamSorted.pause();
		}

		this.dataChanged();
	}

	joiningStreamEnd()
	{
		this.joiningEnded = true;

		this.dataChanged();
	}

	tryResumeAll()
	{
		if (this.mainBuffer.length < this.maxBufferSize) {
			if (this.mainStreamSorted.isPaused()) {
				this.mainStreamSorted.resume();
			}
		}

		if (this.joiningBuffer.length < this.maxBufferSize) {
			if (this.joiningStreamSorted.isPaused()) {
				this.joiningStreamSorted.resume();
			}
		}
	}

	mainKey(row)
	{
		const v = this.mainValueCb(row);
		return v === undefined ? '' : JSON.stringify(v + '');
	}

	joiningKey(row)
	{
		const v = this.joiningValueCb(row);
		return v === undefined ? '' : JSON.stringify(v + '');
	}

	dataChanged()
	{
		if (this.needOutput) {
			this._read();
		}
	}

	popOutput()
	{
		let outputBuffer = [];

		const nextMainRow = () => {
			const row = this.mainBuffer.shift();

			/*
			 * поменялась mainRow - надо сгенерить пачку смердженных строк
			 * и вернуть присоединяемые строки обратно в обработку т.к. они,
			 * возможно, будут нужны для следующей строки основного потока
			 */
			if (this.currentKeyBuffer.length) {
				return this.generateOutputFromCurrentKeyBuffer();
			} else if (this.join.type === Join.LEFT && row) {
				return [row];
			}

			return [];
		};

		while (this.mainBuffer.length && this.joiningBuffer.length) {
			const mainRow = this.mainBuffer[0];
			const joiningRow = this.joiningBuffer[0];

			const mainKey = this.mainKey(mainRow);
			const joiningKey = this.joiningKey(joiningRow);

			this.currentKeyMainRow = mainRow;

			if (this.currentKey !== mainKey) {
				this.currentKey = mainKey;

				if (this.currentKeyBuffer.length) {
					// буфер должен очищаться при завершении ключа
					throw new Error('assert');
				}
			}

			if (mainKey === joiningKey) {
				this.currentKeyBuffer.push(joiningRow);

				this.joiningBuffer.shift();

			} else if (joiningKey > mainKey) {

				outputBuffer = nextMainRow();
				if (outputBuffer.length) {
					break;
				}

			} else { // mainKey > joiningKey
				this.joiningBuffer.shift();
			}
		}

		if (!this.joiningBuffer.length && this.joiningEnded) {
			outputBuffer = outputBuffer.concat(nextMainRow());

			if (this.mainBuffer.length && this.mainEnded) {
				setImmediate(this.dataChanged.bind(this));
			}
		}

		if (!this.mainBuffer.length && this.mainEnded) {
			outputBuffer = outputBuffer.concat(this.generateOutputFromCurrentKeyBuffer());
			this.ended = true;
		}

		this.tryResumeAll();

		return outputBuffer;
	}

	_read()
	{
		const output = this.popOutput();

		if (output.length) {
			this.needOutput = false;
			this.push(output);
		} else {
			this.needOutput = true;
			this.tryResumeAll();
		}

		if (this.ended) {
			this.push(null);
			return;
		}
	}

	mergeRows(mainRow, joiningRow)
	{
		const merged = JSON.parse(JSON.stringify(mainRow));

		merged.sources[this.join.joiningDataStream.name] = joiningRow.sources[this.join.joiningDataStream.name];

		return merged;
	}

	generateOutputFromCurrentKeyBuffer()
	{
		const outputBuffer = [];

		for (const joiningRow of this.currentKeyBuffer) {
			outputBuffer.push(this.mergeRows(this.currentKeyMainRow, joiningRow));
		}

		// возвращаем для обработки обрабтно в очередь
		this.joiningBuffer = this.currentKeyBuffer.concat(this.joiningBuffer);

		this.currentKeyBuffer = [];

		return outputBuffer;
	}
}

module.exports = Joiner;
<commit_msg>Make join async even with sync input, now GC can do their work<commit_after>const JlTransform = require('./JlTransform');
const Readable = require('stream').Readable;
const Join = require('../Join');

class Joiner extends Readable
{
	/**
	 *
	 * @param {Join} join
	 */
	constructor(join, mainValueCb, mainStreamSorted, joiningValueCb, joiningStreamSorted)
	{
		super({objectMode: true});

		this.inputType = JlTransform.ARRAYS_OF_OBJECTS;
		this.outputType = JlTransform.ARRAYS_OF_OBJECTS;

		this.join = join;
		this.mainStreamSorted = mainStreamSorted;
		this.joiningStreamSorted = joiningStreamSorted;

		this.mainValueCb = mainValueCb;
		this.joiningValueCb = joiningValueCb;

		this.currentKey = undefined;
		this.currentKeyMainRow = undefined;
		this.currentKeyBuffer = [];

		this.maxBufferSize = 16;
		this.mainBuffer = [];
		this.joiningBuffer = [];

		this.needOutput = false;

		this.mainEnded = false;
		this.joiningEnded = false;

		this.ended = false;

		mainStreamSorted.on('data', this.mainStreamData.bind(this));
		mainStreamSorted.on('end', this.mainStreamEnd.bind(this));
		joiningStreamSorted.on('data', this.joiningStreamData.bind(this));
		joiningStreamSorted.on('end', this.joiningStreamEnd.bind(this));
	}

	mainStreamData(data)
	{
		this.mainBuffer = this.mainBuffer.concat(data);

		if (this.mainBuffer.length >= this.maxBufferSize) {
			this.mainStreamSorted.pause();
		}

		this.dataChanged();
	}

	mainStreamEnd()
	{
		this.mainEnded = true;
		this.needOutput = true;

		this.dataChanged();
	}

	joiningStreamData(data)
	{
		this.joiningBuffer = this.joiningBuffer.concat(data);

		if (this.joiningBuffer.length >= this.maxBufferSize) {
			this.joiningStreamSorted.pause();
		}

		this.dataChanged();
	}

	joiningStreamEnd()
	{
		this.joiningEnded = true;

		this.dataChanged();
	}

	tryResumeAll()
	{
		if (this.mainBuffer.length < this.maxBufferSize) {
			if (this.mainStreamSorted.isPaused()) {
				this.mainStreamSorted.resume();
			}
		}

		if (this.joiningBuffer.length < this.maxBufferSize) {
			if (this.joiningStreamSorted.isPaused()) {
				this.joiningStreamSorted.resume();
			}
		}
	}

	mainKey(row)
	{
		const v = this.mainValueCb(row);
		return v === undefined ? '' : JSON.stringify(v + '');
	}

	joiningKey(row)
	{
		const v = this.joiningValueCb(row);
		return v === undefined ? '' : JSON.stringify(v + '');
	}

	dataChanged()
	{
		if (this.needOutput) {
			this._read();
		}
	}

	popOutput()
	{
		let outputBuffer = [];

		const nextMainRow = () => {
			const row = this.mainBuffer.shift();

			/*
			 * поменялась mainRow - надо сгенерить пачку смердженных строк
			 * и вернуть присоединяемые строки обратно в обработку т.к. они,
			 * возможно, будут нужны для следующей строки основного потока
			 */
			if (this.currentKeyBuffer.length) {
				return this.generateOutputFromCurrentKeyBuffer();
			} else if (this.join.type === Join.LEFT && row) {
				return [row];
			}

			return [];
		};

		while (this.mainBuffer.length && this.joiningBuffer.length) {
			const mainRow = this.mainBuffer[0];
			const joiningRow = this.joiningBuffer[0];

			const mainKey = this.mainKey(mainRow);
			const joiningKey = this.joiningKey(joiningRow);

			this.currentKeyMainRow = mainRow;

			if (this.currentKey !== mainKey) {
				this.currentKey = mainKey;

				if (this.currentKeyBuffer.length) {
					// буфер должен очищаться при завершении ключа
					throw new Error('assert');
				}
			}

			if (mainKey === joiningKey) {
				this.currentKeyBuffer.push(joiningRow);

				this.joiningBuffer.shift();

			} else if (joiningKey > mainKey) {

				outputBuffer = nextMainRow();
				if (outputBuffer.length) {
					break;
				}

			} else { // mainKey > joiningKey
				this.joiningBuffer.shift();
			}
		}

		if (!this.joiningBuffer.length && this.joiningEnded) {
			outputBuffer = outputBuffer.concat(nextMainRow());

			if (this.mainBuffer.length && this.mainEnded) {
				setImmediate(this.dataChanged.bind(this));
			}
		}

		if (!this.mainBuffer.length && this.mainEnded) {
			outputBuffer = outputBuffer.concat(this.generateOutputFromCurrentKeyBuffer());
			this.ended = true;
		}

		this.tryResumeAll();

		return outputBuffer;
	}

	_read()
	{
		setImmediate(() => {
			const output = this.popOutput();

			if (output.length) {
				this.needOutput = false;
				this.push(output);
			} else {
				this.needOutput = true;
				this.tryResumeAll();
			}

			if (this.ended) {
				this.push(null);
				return;
			}
		});
	}

	mergeRows(mainRow, joiningRow)
	{
		const merged = JSON.parse(JSON.stringify(mainRow));

		merged.sources[this.join.joiningDataStream.name] = joiningRow.sources[this.join.joiningDataStream.name];

		return merged;
	}

	generateOutputFromCurrentKeyBuffer()
	{
		const outputBuffer = [];

		for (const joiningRow of this.currentKeyBuffer) {
			outputBuffer.push(this.mergeRows(this.currentKeyMainRow, joiningRow));
		}

		// возвращаем для обработки обрабтно в очередь
		this.joiningBuffer = this.currentKeyBuffer.concat(this.joiningBuffer);

		this.currentKeyBuffer = [];

		return outputBuffer;
	}
}

module.exports = Joiner;
<|endoftext|>


<commit_before>// adopted from: https://github.com/sindresorhus/plur
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) (MIT)
var contains = require('../regex/contains')

function plural (str, plur, count) {
  if (typeof plur === 'number') {
    count = plur
    plur = str.replace(/(?:s|x|z|ch|sh)$/i, '$&e')

    plur = contains(/(?:[aeiou])y$/i, plur)
      ? plur + 's'
      : plur.replace(/y$/i, 'ie') + 's'

    plur = plur.replace(/i?e?s$/i, function (m) {
        var isTailLowerCase = str.slice(-1) === str.slice(-1).toLowerCase()
        return isTailLowerCase ? m.toLowerCase() : m.toUpperCase()
      })
  }
  return count === 1 ? str : plur
}

module.exports = plural
<commit_msg>update string/plural<commit_after>// adopted from: https://github.com/sindresorhus/plur
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) (MIT)
var irregularPlurals = require('./IRREGULAR-PLURALS')

function plural (str, plur, count) {
  if (typeof plur === 'number') count = plur

  if (str in irregularPlurals) plur = irregularPlurals[str]
  else if (typeof plur !== 'string') {
    plur = (str.replace(/(?:s|x|z|ch|sh)$/i, '$&e')
      .replace(/([^aeiou])y$/i, '$1ie') + 's')
      .replace(/i?e?s$/i, function (m) {
        var isTailLowerCase = str.slice(-1) === str.slice(-1).toLowerCase()
        return isTailLowerCase ? m.toLowerCase() : m.toUpperCase()
      })
  }

  return count === 1 ? str : plur
}

module.exports = plural
<|endoftext|>


<commit_before>import ExtendableError from 'es6-error';

export default class MeaningError extends ExtendableError {
  constructor(message = 'Server Error') {
    super(message);

    this.message = message;

    if (!this.code) {
      this.code = 500;
    }
  }

  getCode() {
    return this.code;
  }

  getMessage() {
    return this.message;
  }
}
<commit_msg>Fix not use message from inheritance class<commit_after>import ExtendableError from 'es6-error';

export default class MeaningError extends ExtendableError {
  constructor(message = 'Server Error') {
    super(message);

    this._message = message;

    if (!this.code) {
      this.code = 500;
    }
  }

  getCode() {
    return this.code;
  }

  getMessage() {
    return this._message;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
// English - root strings
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_CUT_NAME"                    : "Cut",
    "RIGHT_CLICK_MENU_COPY_NAME"                   : "Copy",
    "RIGHT_CLICK_MENU_PASTE_NAME"                  : "Paste",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"              : "Uppercase",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"              : "lowercase",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"              : "camelCase",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME"           : "Toggle Block Comment",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"            : "Toggle Line Comment",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"                : "Save All",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"              : "Convert To",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME"      : "Encode HTML Entity",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "Encode Named HTML Entity",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME"      : "Decode HTML Entity",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME"             : "Encode URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME"             : "Decode URI",
    "RIGHT_CLICK_MENU_UNDO_NAME"                   : "Undo",
    "RIGHT_CLICK_MENU_REMOVE_EMPTY_LINES_NAME"     : "Remove empty lines"
});
<commit_msg>Update strings.js<commit_after>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
// English - root strings
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_CUT_NAME"                    : "Cut",
    "RIGHT_CLICK_MENU_COPY_NAME"                   : "Copy",
    "RIGHT_CLICK_MENU_PASTE_NAME"                  : "Paste",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"              : "Uppercase",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"              : "lowercase",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"              : "camelCase",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME"           : "Toggle Block Comment",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"            : "Toggle Line Comment",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"                : "Save All",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"              : "Convert To",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME"      : "Encode HTML Entity",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "Encode Named HTML Entity",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME"      : "Decode HTML Entity",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME"             : "Encode URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME"             : "Decode URI",
    "RIGHT_CLICK_MENU_UNDO_NAME"                   : "Undo",
    "RIGHT_CLICK_MENU_REMOVE_EMPTY_LINES_NAME"     : "Remove empty lines",
    "TOGGLESYNC_COMMAND_NAME"                      : "Sync Split View Toggle"
});
<|endoftext|>


<commit_before>/*
 * Copyright 2005-2013 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Script specific to lookup views.
 *
 * @author Kuali Rice Team (rice.collab@kuali.org)
 */

var returnByScriptHidden = "returnByScript";

/*
    There is an issue with jQuery re-running document ready twice. This happens when the innerHTML gets
    updated. Ref: http://shout.setfive.com/2010/02/22/javascript-document-ready-getting-called-twice-heres-why/

    This variable is a local solution within krad.lookup to prevent the updateSelectLineCount to be called only
    once onChange, as enabling/disabling 'return selected' depends on increment/decrement of a counter in its logic that
     gets corrupted by multiple calls for the same event.
 */
var _DONE = false;

jQuery(document).ready(function () {
    if(_DONE === true) { return;}

       _DONE = true;

    // multi value select handler to enable/disable return selected button for checkboxes with uif-select-line
    jQuery(document).on("change", "#" + kradVariables.LOOKUP_COLLECTION_ID + " input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS, function (e) {
       updateSelectLineCount(this);
    });

    // event handler for return links on lookups
    jQuery(document).on("click", "a[" + kradVariables.ATTRIBUTES.DATA_RETURN + "]", function (e) {
        e.preventDefault();

        // determine if the results should be returned through script
        var returnByScript = coerceValue(returnByScriptHidden);

        if (returnByScript) {
            returnLookupResultsByScript(this);
        }
        else {
            returnLookupResultReload(this);
        }
    });
});

/**
 * Registers the onChange event on the input element inside of the lookup results collection
 * by updating the selection count depending on whether the checkbox has been checked or not
 *
 * @param selectControl  select control the change event occurred on
 */
function updateSelectLineCount(selectControl) {
    input = jQuery(selectControl);

    // Fetch current selectLineCount
    var lookupResultsDiv = jQuery("#" + kradVariables.LOOKUP_COLLECTION_ID);
    var selectlinecount = lookupResultsDiv.data('selectedlinecount');

    if(input.attr('checked')) {
        lookupResultsDiv.data('selectedlinecount', selectlinecount + 1);
    }  else if(selectlinecount > 0) {
        lookupResultsDiv.data('selectedlinecount', selectlinecount - 1);
    }

    setMultivalueLookupReturnButton("#" + kradVariables.LOOKUP_COLLECTION_ID);
}

/**
 * Enables the return selected button on the multi value lookup when at least one item is selected.
 *
 * @param selectControl select control the change event occurred on
 */
function setMultivalueLookupReturnButton(selectControl) {

    var lookupResultsDiv = jQuery(selectControl);

    var checked = lookupResultsDiv.data('selectedlinecount') > 0;

    if (checked) {
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).removeAttr('disabled');
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).removeClass('disabled');
    } else {
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).attr('disabled', 'disabled');
    }
}
/**
 * Select all checkboxes within the datatable/non datatable (all pages) that are marked with class 'uif-select-line'
 * (used for multi-value select collections)
 *
 * @param collectionId - id for the collection to select checkboxes for
 */
function selectAllLines(collectionId) {
    var query = "input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS;
    var lookupCollectionDiv = jQuery("#" + collectionId);

    // If results are displayed using dataTable
    if(jQuery('table.dataTable').length > 0) {

        // get a handle on the datatables plugin object for the results collection
        var oTable = getDataTableHandle(lookupCollectionDiv.find("table").attr('id'));

        jQuery(query, oTable.fnGetNodes()).each(function( index ) {
            this.checked = true;
        });
    }  else {
        jQuery(lookupCollectionDiv.find(query)).each(function (index) {
            jQuery(this).attr('checked', true);
        });
    }

    // Reset data attribute selectedlinecount to number of results in the lookup
    var lookupResultCount = lookupCollectionDiv.data('lookupresultscount');
    lookupCollectionDiv.data('selectedlinecount', lookupResultCount);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Deselects all checkboxes within the datatable/non datatable (all pages) that are marked with class 'uif-select-line'
 * (used for multi-value select collections)
 *
 * @param collectionId - id for the collection to deselect checkboxes for
 */
function deselectAllLines(collectionId) {
    // get a handle on the datatables plugin object for the results collection
    var oTable = getDataTableHandle(jQuery("#" + collectionId).find("table").attr('id'));
    var query = "input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS;

    if(jQuery('table.dataTable').length > 0) {
        jQuery(query, oTable.fnGetNodes()).prop('checked', false);
    }

    // reset selectedlinecount to 0
    var lookupCollectionDiv = jQuery('#' + collectionId);
    lookupCollectionDiv.data('selectedlinecount', 0);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Select all checkboxes within the collection div that are marked with class 'uif-select-line' (used
 * for multi-value select collections) on the current page and updates the selectedlinecount
 *
 * @param collectionId - id for the collection to select checkboxes for
 */
function selectAllPageLines(collectionId) {
   // jQuery("#" + collectionId + " input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS).attr('checked', true);
    var selectedLineCount = 0;
    jQuery( "#" + collectionId ).find("input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS).each( function (index) {
        if (jQuery(this).attr('checked') != true) {
            jQuery(this).attr('checked',true);
            selectedLineCount = selectedLineCount+1;
        }
    });
    var lookupCollectionDiv = jQuery('#' + collectionId);
    lookupCollectionDiv.data('selectedlinecount', selectedLineCount);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));

}

/**
 * Deselects all checkboxes within the collection div that are marked with class 'uif-select-line' (used
 * for multi-value select collections) on the current page and updates the selectedlinecount
 *
 * @param collectionId - id for the collection to deselect checkboxes for
 */
function deselectAllPageLines(collectionId) {
    var selectedLineCount = jQuery('#' + collectionId).data('selectedlinecount');
    jQuery("#" + collectionId).find("input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS).each(function (index) {
        jQuery(this).attr('checked', false);
        if (selectedLineCount > 0) {
            selectedLineCount = selectedLineCount - 1;
        }
    });

    jQuery('#' + collectionId).data('selectedlineCount',selectedLineCount);
    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Function that returns results field values when a return link is invoked
 *
 * @param returnLink link that was selected
 */
function returnLookupResultsByScript(returnLink) {
    var jqReturnLink = jQuery(returnLink);

    var returnData = jqReturnLink.attr(kradVariables.ATTRIBUTES.DATA_RETURN);
    var returnFieldValues = jQuery.parseJSON(returnData);

    var returnField;
    for (var returnFieldName in returnFieldValues) {
        if (!returnFieldValues.hasOwnProperty(returnFieldName)) {
            continue;
        }

        var returnFieldValue = returnFieldValues[returnFieldName];

        returnField = findElement('[name="' + escapeName(returnFieldName) + '"]');

        if (!returnField.length) {
            continue;
        }

        returnField.val(returnFieldValue);

        // trigger any ajax queries with the blur event
        returnField.focus();
        returnField.blur();

        returnField.change();
    }

    // set focus to last returned field
    if (returnField) {
        returnField.focus();
    }

    closeLightbox();
}

/**
 * Reload page with lookup result URL
 */
function returnLookupResultReload(returnLink) {
    var jqReturnLink = jQuery(returnLink);

    var href = jqReturnLink.attr("href");
    var target = jqReturnLink.attr("target");

    var closedLightboxNeeded = true;

    if (parent.jQuery('iframe[id*=easyXDM_]').length > 0) {
        // portal and content on same domain
        top.jQuery('iframe[id*=easyXDM_]').contents().find('#' + kradVariables.PORTAL_IFRAME_ID).attr('src', href);
    } else if (parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).length > 0) {
        // portal and content on different domain
        parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).attr('src', href);
    } else {
        window.open(href, target);

        if (!target || (target === "_self")) {
            closedLightboxNeeded = false;
        }
    }

    if (closedLightboxNeeded) {
        closeLightbox();
    }
}

/**
 * Sets form target for the multi-value return and closes the lightbox
 */
function setupMultiValueReturn() {
    if ((parent.jQuery('iframe[id*=easyXDM_]').length > 0) || (parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).length > 0)) {
        jQuery('#' + kradVariables.KUALI_FORM).attr('target', kradVariables.PORTAL_IFRAME_ID);
    }
    else {
        jQuery('#' + kradVariables.KUALI_FORM).attr('target', '_parent');
    }

    // Data table only retains elements on the visible page within the DOM.
    // To be able to preserve selections from hidden pages, we need to extract
    // those elements from the datatable and re-insert them back into the form
    if(jQuery('table.dataTable').length > 0) {
        // Find all the input type: hidden elements in the data table
        var oTable = jQuery('.dataTable').dataTable();
        var sData = jQuery('input:hidden', oTable.fnGetNodes()).serializeArray();

        // For each hidden element insert it back to the form
        jQuery.each(sData, function(i, field){

            jQuery('<input>').attr({
                type: 'hidden',
                id: field.id,
                name: field.name,
                value: field.value
            }).appendTo('#'+kradVariables.KUALI_FORM);    });
    }
    closeLightbox();
}

<commit_msg>KULRICE-11214 MultiValue Lookup - select only on this page and then deselect only on this page the return select button stays clickable.<commit_after>/*
 * Copyright 2005-2013 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Script specific to lookup views.
 *
 * @author Kuali Rice Team (rice.collab@kuali.org)
 */

var returnByScriptHidden = "returnByScript";

/*
    There is an issue with jQuery re-running document ready twice. This happens when the innerHTML gets
    updated. Ref: http://shout.setfive.com/2010/02/22/javascript-document-ready-getting-called-twice-heres-why/

    This variable is a local solution within krad.lookup to prevent the updateSelectLineCount to be called only
    once onChange, as enabling/disabling 'return selected' depends on increment/decrement of a counter in its logic that
     gets corrupted by multiple calls for the same event.
 */
var _DONE = false;

jQuery(document).ready(function () {
    if(_DONE === true) { return;}

       _DONE = true;

    // multi value select handler to enable/disable return selected button for checkboxes with uif-select-line
    jQuery(document).on("change", "#" + kradVariables.LOOKUP_COLLECTION_ID + " input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS, function (e) {
       updateSelectLineCount(this);
    });

    // event handler for return links on lookups
    jQuery(document).on("click", "a[" + kradVariables.ATTRIBUTES.DATA_RETURN + "]", function (e) {
        e.preventDefault();

        // determine if the results should be returned through script
        var returnByScript = coerceValue(returnByScriptHidden);

        if (returnByScript) {
            returnLookupResultsByScript(this);
        }
        else {
            returnLookupResultReload(this);
        }
    });
});

/**
 * Registers the onChange event on the input element inside of the lookup results collection
 * by updating the selection count depending on whether the checkbox has been checked or not
 *
 * @param selectControl  select control the change event occurred on
 */
function updateSelectLineCount(selectControl) {
    input = jQuery(selectControl);

    // Fetch current selectLineCount
    var lookupResultsDiv = jQuery("#" + kradVariables.LOOKUP_COLLECTION_ID);
    var selectlinecount = lookupResultsDiv.data('selectedlinecount');

    if(input.attr('checked')) {
        lookupResultsDiv.data('selectedlinecount', selectlinecount + 1);
    }  else if(selectlinecount > 0) {
        lookupResultsDiv.data('selectedlinecount', selectlinecount - 1);
    }

    setMultivalueLookupReturnButton("#" + kradVariables.LOOKUP_COLLECTION_ID);
}

/**
 * Enables the return selected button on the multi value lookup when at least one item is selected.
 *
 * @param selectControl select control the change event occurred on
 */
function setMultivalueLookupReturnButton(selectControl) {

    var lookupResultsDiv = jQuery(selectControl);

    var checked = lookupResultsDiv.data('selectedlinecount') > 0;

    if (checked) {
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).removeAttr('disabled');
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).removeClass('disabled');
    } else {
        jQuery(':button.' + kradVariables.RETURN_SELECTED_ACTION_CLASS).attr('disabled', 'disabled');
    }
}
/**
 * Select all checkboxes within the datatable/non datatable (all pages) that are marked with class 'uif-select-line'
 * (used for multi-value select collections)
 *
 * @param collectionId - id for the collection to select checkboxes for
 */
function selectAllLines(collectionId) {
    var query = "input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS;
    var lookupCollectionDiv = jQuery("#" + collectionId);

    // If results are displayed using dataTable
    if(jQuery('table.dataTable').length > 0) {

        // get a handle on the datatables plugin object for the results collection
        var oTable = getDataTableHandle(lookupCollectionDiv.find("table").attr('id'));

        jQuery(query, oTable.fnGetNodes()).each(function( index ) {
            this.checked = true;
        });
    }  else {
        jQuery(lookupCollectionDiv.find(query)).each(function (index) {
            jQuery(this).attr('checked', true);
        });
    }

    // Reset data attribute selectedlinecount to number of results in the lookup
    var lookupResultCount = lookupCollectionDiv.data('lookupresultscount');
    lookupCollectionDiv.data('selectedlinecount', lookupResultCount);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Deselects all checkboxes within the datatable/non datatable (all pages) that are marked with class 'uif-select-line'
 * (used for multi-value select collections)
 *
 * @param collectionId - id for the collection to deselect checkboxes for
 */
function deselectAllLines(collectionId) {
    // get a handle on the datatables plugin object for the results collection
    var oTable = getDataTableHandle(jQuery("#" + collectionId).find("table").attr('id'));
    var query = "input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS;

    if(jQuery('table.dataTable').length > 0) {
        jQuery(query, oTable.fnGetNodes()).prop('checked', false);
    }

    // reset selectedlinecount to 0
    var lookupCollectionDiv = jQuery('#' + collectionId);
    lookupCollectionDiv.data('selectedlinecount', 0);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Select all checkboxes within the collection div that are marked with class 'uif-select-line' (used
 * for multi-value select collections) on the current page and updates the selectedlinecount
 *
 * @param collectionId - id for the collection to select checkboxes for
 */
function selectAllPageLines(collectionId) {
    var selectedLineCount = jQuery('#' + collectionId).data('selectedlinecount');
    jQuery( "#" + collectionId ).find("input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS).each( function (index) {
        if (jQuery(this).attr('checked') != true) {
            jQuery(this).attr('checked',true);
            selectedLineCount = selectedLineCount+1;
        }
    });
    var lookupCollectionDiv = jQuery('#' + collectionId);
    lookupCollectionDiv.data('selectedlinecount', selectedLineCount);

    setMultivalueLookupReturnButton(jQuery("#" + collectionId));

}

/**
 * Deselects all checkboxes within the collection div that are marked with class 'uif-select-line' (used
 * for multi-value select collections) on the current page and updates the selectedlinecount
 *
 * @param collectionId - id for the collection to deselect checkboxes for
 */
function deselectAllPageLines(collectionId) {
    var selectedLineCount = jQuery('#' + collectionId).data('selectedlinecount');
    jQuery("#" + collectionId).find("input:checkbox." + kradVariables.SELECT_FIELD_STYLE_CLASS).each(function (index) {
        jQuery(this).attr('checked', false);
        if (selectedLineCount > 0) {
            selectedLineCount = selectedLineCount - 1;
        }
    });

    jQuery('#' + collectionId).data('selectedlinecount',selectedLineCount);
    setMultivalueLookupReturnButton(jQuery("#" + collectionId));
}

/**
 * Function that returns results field values when a return link is invoked
 *
 * @param returnLink link that was selected
 */
function returnLookupResultsByScript(returnLink) {
    var jqReturnLink = jQuery(returnLink);

    var returnData = jqReturnLink.attr(kradVariables.ATTRIBUTES.DATA_RETURN);
    var returnFieldValues = jQuery.parseJSON(returnData);

    var returnField;
    for (var returnFieldName in returnFieldValues) {
        if (!returnFieldValues.hasOwnProperty(returnFieldName)) {
            continue;
        }

        var returnFieldValue = returnFieldValues[returnFieldName];

        returnField = findElement('[name="' + escapeName(returnFieldName) + '"]');

        if (!returnField.length) {
            continue;
        }

        returnField.val(returnFieldValue);

        // trigger any ajax queries with the blur event
        returnField.focus();
        returnField.blur();

        returnField.change();
    }

    // set focus to last returned field
    if (returnField) {
        returnField.focus();
    }

    closeLightbox();
}

/**
 * Reload page with lookup result URL
 */
function returnLookupResultReload(returnLink) {
    var jqReturnLink = jQuery(returnLink);

    var href = jqReturnLink.attr("href");
    var target = jqReturnLink.attr("target");

    var closedLightboxNeeded = true;

    if (parent.jQuery('iframe[id*=easyXDM_]').length > 0) {
        // portal and content on same domain
        top.jQuery('iframe[id*=easyXDM_]').contents().find('#' + kradVariables.PORTAL_IFRAME_ID).attr('src', href);
    } else if (parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).length > 0) {
        // portal and content on different domain
        parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).attr('src', href);
    } else {
        window.open(href, target);

        if (!target || (target === "_self")) {
            closedLightboxNeeded = false;
        }
    }

    if (closedLightboxNeeded) {
        closeLightbox();
    }
}

/**
 * Sets form target for the multi-value return and closes the lightbox
 */
function setupMultiValueReturn() {
    if ((parent.jQuery('iframe[id*=easyXDM_]').length > 0) || (parent.parent.jQuery('#' + kradVariables.PORTAL_IFRAME_ID).length > 0)) {
        jQuery('#' + kradVariables.KUALI_FORM).attr('target', kradVariables.PORTAL_IFRAME_ID);
    }
    else {
        jQuery('#' + kradVariables.KUALI_FORM).attr('target', '_parent');
    }

    // Data table only retains elements on the visible page within the DOM.
    // To be able to preserve selections from hidden pages, we need to extract
    // those elements from the datatable and re-insert them back into the form
    if(jQuery('table.dataTable').length > 0) {
        // Find all the input type: hidden elements in the data table
        var oTable = jQuery('.dataTable').dataTable();
        var sData = jQuery('input:hidden', oTable.fnGetNodes()).serializeArray();

        // For each hidden element insert it back to the form
        jQuery.each(sData, function(i, field){

            jQuery('<input>').attr({
                type: 'hidden',
                id: field.id,
                name: field.name,
                value: field.value
            }).appendTo('#'+kradVariables.KUALI_FORM);    });
    }
    closeLightbox();
}

<|endoftext|>


<commit_before>#!/usr/bin/env node

var config = require('./config.json');
var fs = require('fs');
var express = require('express');
var app = express();
var async = require('async');
var spawn = require('child_process').spawn;
var email = require('emailjs/email');
var mailer = email.server.connect(config.email);
var crypto = require('crypto');

// Create Task Queue for Request handling
var tasks = async.queue(handleRequest, 1);

app.use(express.bodyParser({
  verify: function(req, res, buffer) {
    if (!req.headers['x-hub-signature']) {
      return;
    }

    if (!config.secret || config.secret === "") {
      console.log("Recieved a X-Hub-Signature header, but cannot validate as no secret is configured");
      return;
    }

    var hmac = crypto.createHmac('sha1', config.secret);
    var recieved_sig = req.headers['x-hub-signature'].split('=')[1];
    var computed_sig = hmac.update(buffer).digest('hex');

    if (recieved_sig != computed_sig) {
      console.warn('Recieved an invalid HMAC: calculated:' + computed_sig + ' != recieved:' + recieved_sig);
      var err = new Error('Invalid Signature');
      err.status = 403;
      throw err;
    }
  }

}));

// Receive webhook post
app.post('/hooks/jekyll/:branch', function(req, res) {

  // Ensure that we return 200 Ok on ping and an error on other requests that
  // aren't 'push'
  var ghEvent = req.get('X-GitHub-Event');
  if (ghEvent == 'ping') {
    console.log('Received ping.');
    res.send(200);
    return;
  } else if (ghEvent != 'push') {
    console.log('Received unsupported event: ' + ghEvent);
    res.send(400);
    return;
  }

  // Close connection
  res.send(202);

  // Queue request handler
  tasks.push({
    req: req,
    res: res
  });
});

// Start server
var port = process.env.PORT || config.listen || 8080;
app.listen(port);
console.log('Listening on port ' + port);

function run(file, params, cb) {
  var process = spawn(file, params);

  process.stdout.on('data', function(data) {
    console.log('' + data);
  });

  process.stderr.on('data', function(data) {
    console.warn('' + data);
  });

  process.on('exit', function(code) {
    if (typeof cb === 'function') cb(code !== 0);
  });
}

function handleRequest(task, cb) {
  var req = task.req;
  var res = task.res;
  var data = req.body;
  var branch = req.params[0];
  var params = [];

  // Parse webhook data for internal variables
  data.repo = data.repository.name;
  data.branch = data.ref.replace('refs/heads/', '');
  data.owner = data.repository.owner.name;

  // End early if not permitted account
  if (config.accounts.indexOf(data.owner) === -1) {
    console.log(data.owner + ' is not an authorized account.');
    if (typeof cb === 'function') cb();
    return;
  }

  // End early if not permitted branch
  if (data.branch !== branch) {
    console.log('Not ' + branch + ' branch.');
    if (typeof cb === 'function') cb();
    return;
  }

  // Process webhook data into params for scripts
  /* repo   */
  params.push(data.repo);
  /* branch */
  params.push(data.branch);
  /* owner  */
  params.push(data.owner);

  /* giturl */
  if (config.public_repo) {
    params.push('https://' + config.gh_server + '/' + data.owner + '/' + data.repo + '.git');
  } else {
    params.push('git@' + config.gh_server + ':' + data.owner + '/' + data.repo + '.git');
  }

  /* source */
  params.push(config.temp + '/' + data.owner + '/' + data.repo + '/' + data.branch + '/' + 'code');
  /* build  */
  params.push(config.temp + '/' + data.owner + '/' + data.repo + '/' + data.branch + '/' + 'site');

  // Script by branch.
  var build_script = null;
  try {
    build_script = config.scripts[data.branch].build;
  } catch (err) {
    try {
      build_script = config.scripts['#default'].build;
    } catch (err) {
      throw new Error('No default build script defined.');
    }
  }

  var publish_script = null;
  try {
    publish_script = config.scripts[data.branch].publish;
  } catch (err) {
    try {
      publish_script = config.scripts['#default'].publish;
    } catch (err) {
      throw new Error('No default publish script defined.');
    }
  }

  // Run build script
  run(build_script, params, function(err) {
    if (err) {
      console.log('Failed to build: ' + data.owner + '/' + data.repo);
      send('Your website at ' + data.owner + '/' + data.repo + ' failed to build.', 'Error building site', data);

      if (typeof cb === 'function') cb();
      return;
    }

    // Run publish script
    run(publish_script, params, function(err) {
      if (err) {
        console.log('Failed to publish: ' + data.owner + '/' + data.repo);
        send('Your website at ' + data.owner + '/' + data.repo + ' failed to publish.', 'Error publishing site', data);

        if (typeof cb === 'function') cb();
        return;
      }

      // Done running scripts
      console.log('Successfully rendered: ' + data.owner + '/' + data.repo);
      send('Your website at ' + data.owner + '/' + data.repo + ' was successfully published.', 'Successfully published site', data);

      if (typeof cb === 'function') cb();
      return;
    });
  });
}

function send(body, subject, data) {
  if (config.email && config.email.isActivated && data.pusher.email) {
    var message = {
      text: body,
      from: config.email.user,
      to: data.pusher.email,
      subject: subject
    };
    mailer.send(message, function(err) {
      if (err) console.warn(err);
    });
  }
}<commit_msg>Refractor to match jshin guidelines<commit_after>#!/usr/bin/env node

var config = require('./config.json');
var express = require('express');
var app = express();
var async = require('async');
var spawn = require('child_process').spawn;
var email = require('emailjs/email');
var mailer = email.server.connect(config.email);
var crypto = require('crypto');

function run(file, params, cb) {
  var process = spawn(file, params);

  process.stdout.on('data', function(data) {
    console.log('' + data);
  });

  process.stderr.on('data', function(data) {
    console.warn('' + data);
  });

  process.on('exit', function(code) {
    if (typeof cb === 'function') {
      cb(code !== 0);
    }
  });
}

function send(body, subject, data) {
  if (config.email && config.email.isActivated && data.pusher.email) {
    var message = {
      text: body,
      from: config.email.user,
      to: data.pusher.email,
      subject: subject
    };
    mailer.send(message, function(err) {
      if (err) {
        console.warn(err);
      }
    });
  }
}

function handleRequest(task, cb) {
  var req = task.req;
  var data = req.body;
  var branch = req.params[0];
  var params = [];

  // Parse webhook data for internal variables
  data.repo = data.repository.name;
  data.branch = data.ref.replace('refs/heads/', '');
  data.owner = data.repository.owner.name;

  // End early if not permitted account
  if (config.accounts.indexOf(data.owner) === -1) {
    console.log(data.owner + ' is not an authorized account.');
    if (typeof cb === 'function') {
      cb();
    }
    return;
  }

  // End early if not permitted branch
  if (data.branch !== branch) {
    console.log('Not ' + branch + ' branch.');
    if (typeof cb === 'function') {
      cb();
    }
    return;
  }

  // Process webhook data into params for scripts
  /* repo   */
  params.push(data.repo);
  /* branch */
  params.push(data.branch);
  /* owner  */
  params.push(data.owner);

  /* giturl */
  if (config.public_repo) {
    params.push('https://' + config.gh_server + '/' + data.owner + '/' + data.repo + '.git');
  } else {
    params.push('git@' + config.gh_server + ':' + data.owner + '/' + data.repo + '.git');
  }

  /* source */
  params.push(config.temp + '/' + data.owner + '/' + data.repo + '/' + data.branch + '/' + 'code');
  /* build  */
  params.push(config.temp + '/' + data.owner + '/' + data.repo + '/' + data.branch + '/' + 'site');

  // Script by branch.
  var build_script = null;
  try {
    build_script = config.scripts[data.branch].build;
  } catch (err) {
    try {
      build_script = config.scripts['#default'].build;
    } catch (err) {
      throw new Error('No default build script defined.');
    }
  }

  var publish_script = null;
  try {
    publish_script = config.scripts[data.branch].publish;
  } catch (err) {
    try {
      publish_script = config.scripts['#default'].publish;
    } catch (err) {
      throw new Error('No default publish script defined.');
    }
  }

  // Run build script
  run(build_script, params, function(err) {
    if (err) {
      console.log('Failed to build: ' + data.owner + '/' + data.repo);
      send('Your website at ' + data.owner + '/' + data.repo + ' failed to build.', 'Error building site', data);

      if (typeof cb === 'function') {
        cb();
      }
      return;
    }

    // Run publish script
    run(publish_script, params, function(err) {
      if (err) {
        console.log('Failed to publish: ' + data.owner + '/' + data.repo);
        send('Your website at ' + data.owner + '/' + data.repo + ' failed to publish.', 'Error publishing site', data);

        if (typeof cb === 'function') {
          cb();
        }
        return;
      }

      // Done running scripts
      console.log('Successfully rendered: ' + data.owner + '/' + data.repo);
      send('Your website at ' + data.owner + '/' + data.repo + ' was successfully published.', 'Successfully published site', data);

      if (typeof cb === 'function') {
        cb();
      }
      return;
    });
  });
}

// Create Task Queue for Request handling
var tasks = async.queue(handleRequest, 1);

app.use(express.bodyParser({
  verify: function(req, res, buffer) {
    if (!req.headers['x-hub-signature']) {
      return;
    }

    if (!config.secret || config.secret === "") {
      console.log("Recieved a X-Hub-Signature header, but cannot validate as no secret is configured");
      return;
    }

    var hmac = crypto.createHmac('sha1', config.secret);
    var recieved_sig = req.headers['x-hub-signature'].split('=')[1];
    var computed_sig = hmac.update(buffer).digest('hex');

    if (recieved_sig !== computed_sig) {
      console.warn('Recieved an invalid HMAC: calculated:' + computed_sig + ' != recieved:' + recieved_sig);
      var err = new Error('Invalid Signature');
      err.status = 403;
      throw err;
    }
  }

}));

// Receive webhook post
app.post('/hooks/jekyll/:branch', function(req, res) {

  // Ensure that we return 200 Ok on ping and an error on other requests that
  // aren't 'push'
  var ghEvent = req.get('X-GitHub-Event');
  if (ghEvent === 'ping') {
    console.log('Received ping.');
    res.send(200);
    return;
  } else if (ghEvent !== 'push') {
    console.log('Received unsupported event: ' + ghEvent);
    res.send(400);
    return;
  }

  // Close connection
  res.send(202);

  // Queue request handler
  tasks.push({
    req: req
  });
});

// Start server
var port = process.env.PORT || config.listen || 8080;
app.listen(port);
console.log('Listening on port ' + port);<|endoftext|>


<commit_before><commit_msg>Removed unnecessary checks<commit_after><|endoftext|>


<commit_before><commit_msg>Fix loaded event in delayed callback<commit_after><|endoftext|>


<commit_before>module.exports = {
  roots: ['<rootDir>/app/src/', '<rootDir>/app/test/'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  testMatch: ['**/unit/**/*-test.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  setupFiles: [
    '<rootDir>/app/test/globals.ts',
    '<rootDir>/app/test/unit-test-env.ts',
  ],
  setupTestFrameworkScriptFile: '<rootDir>/app/test/setup-test-framework.ts',
  collectCoverageFrom: [
    'app/src/**/*.{js,jsx,ts,tsx}',
    '!**/node_modules/**',
    '!**/vendor/**',
    '!**/*.d.*',
    // not focused on testing these areas currently
    '!app/src/ask-pass/**/*',
    '!app/src/cli/**/*',
    '!app/src/crash/**/*',
    '!app/src/highlighter/**/*',
    // ignore index files
    '!**/index.ts',
  ],
  coverageReporters: ['text-summary', 'json'],
  globals: {
    'ts-jest': {
      useBabelrc: true,
    },
  },
}
<commit_msg>add tsx files to jest<commit_after>module.exports = {
  roots: ['<rootDir>/app/src/', '<rootDir>/app/test/'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  testMatch: ['**/unit/**/*-test.ts{,x}'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  setupFiles: [
    '<rootDir>/app/test/globals.ts',
    '<rootDir>/app/test/unit-test-env.ts',
  ],
  setupTestFrameworkScriptFile: '<rootDir>/app/test/setup-test-framework.ts',
  collectCoverageFrom: [
    'app/src/**/*.{js,jsx,ts,tsx}',
    '!**/node_modules/**',
    '!**/vendor/**',
    '!**/*.d.*',
    // not focused on testing these areas currently
    '!app/src/ask-pass/**/*',
    '!app/src/cli/**/*',
    '!app/src/crash/**/*',
    '!app/src/highlighter/**/*',
    // ignore index files
    '!**/index.ts',
  ],
  coverageReporters: ['text-summary', 'json'],
  globals: {
    'ts-jest': {
      useBabelrc: true,
    },
  },
}
<|endoftext|>


<commit_before>/**
 * ingestion.js
 * expects:
 * 1. path of directory (target)
 * 2. parentpid
 * 3. namespace
 * 4. model
 *   (note: basic image,large image,audio,video, collection, pdf, binary -- all require
 * the "ibsp" in the command string, book requires the "ibbp" part in the drush command.)
 * output:
 *  log of drush run
 * errors:
 *  if parameters missing
 *  if first command did not run
 *  if first command did run but did not prep ingest
 *  if first command ran with a good ingest but second command did not run
 *   (only if first command ran successfully)if second ran but did not ingest
 *
 * @param target directory path
 * @param parentpid
 * @param namespace
 * @param model
 * @return $message
 *
 */
// for testing
//
var param = process.argv;
console.log('hi');
target = String(param[3]);
parentpid = String(param[4]);
namespace = String(param[5]);
model = String(param[6]);

var status=[];

function ingestion(target,parentpid,namespace,model) {
  // build command pieces
  // serveruri is the location of the drupal_home on the drupal server
  var drupalhome = '/vhosts/dlwork/web/collections';
  console.log('drupalhome = ',drupalhome);
  var serveruri = 'http://dlwork.lib.utk.edu/dev/';
  console.log('serveruri = ',serveruri);
  console.log('parentpid = ',parentpid);
  // namespace
  console.log('namespace = ',namespace);
  // target is the local directory holding the ingest files
  console.log('target = ',target);
  // make mongo connection
  /*
  var mongoose = require('mongoose');
  mongoose.connect('mongodb://localhost/ibu');
  var conn = mongoose.connection;
  */
  //
  var $message = 'ingest did not happen';
  var contentmodel = '';
  if ((model)&& (model==='basic')) {
    contentmodel = 'islandora:sp_basic_image';
  }
  if ((model)&&(model==='large')) {
    contentmodel = 'islandora:sp_Large_image';
  }
  console.log('model = ',model);
  // execute first drush command
  var exec = require('child_process').exec;
  var cmd = String('drush -r '+drupalhome+'-v -u=1 --uri='+serveruri+' ibsp --content_models='+contentmodel+' --type=directory --parent='+parentpid+' --namespace='+namespace+' --target='+target );
  // show assembled command
  console.log('cmd=',cmd);
  if ((target !='')&&(contentmodel !='')&&(parentpid !='')&&(namespace !='')) {
    exec(cmd, function(error, stdout, stderr) {
     // command output is in stdout
     console.log(stdout);
     // test command log for success indication
     // test for substr in stdout
     var cmd1bad = 1;
     if (cmd1bad) {
       $message = 'first ingest command failed!';
       console.log($message);
       return $message;
     }
     else {
       $message = 'ingest prep drush command success';
       console.log($message);
       status.push("$message");
       return $message;
     }//end else
    });// end exec
  }// end if
  else {
     console.log('parameters for first command missing, ingest not started.\n');
     $message = 'parameters for first command missing, ingest not started.';
     return $message;
  }
  // exec second drush command
  var cmd2 = String('drush -r '+drupalhome+'-v -u=1 --uri='+serveruri+' islandora_batch_ingest');
  console.log('cmd2=',cmd2);
  if ($message = 'ingest prep drush command success') {
    exec(cmd2, function(error, stdout, stderr) {
     // command output is in stdout
     console.log(stdout);
     // test command log for success indication
     // test for substr in stdout
     $message = 'ingest drush command success';
     console.log($message);
     status.push($message);
    });
  }// end if
  return $message;
}// end function
//export default ingestion;
ingestion(target,parentpid,namespace,model);

<commit_msg>add status push several more places to maybe return something<commit_after>/**
 * ingestion.js
 * expects:
 * 1. path of directory (target)
 * 2. parentpid
 * 3. namespace
 * 4. model
 *   (note: basic image,large image,audio,video, collection, pdf, binary -- all require
 * the "ibsp" in the command string, book requires the "ibbp" part in the drush command.)
 * output:
 *  log of drush run
 * errors:
 *  if parameters missing
 *  if first command did not run
 *  if first command did run but did not prep ingest
 *  if first command ran with a good ingest but second command did not run
 *   (only if first command ran successfully)if second ran but did not ingest
 *
 * @param target directory path
 * @param parentpid
 * @param namespace
 * @param model
 * @return $message
 *
 */
// for testing
//
var param = process.argv;
console.log('hi');
target = String(param[3]);
parentpid = String(param[4]);
namespace = String(param[5]);
model = String(param[6]);

var status=[];

function ingestion(target,parentpid,namespace,model) {
  // build command pieces
  // serveruri is the location of the drupal_home on the drupal server
  var drupalhome = '/vhosts/dlwork/web/collections';
  console.log('drupalhome = ',drupalhome);
  var serveruri = 'http://dlwork.lib.utk.edu/dev/';
  console.log('serveruri = ',serveruri);
  console.log('parentpid = ',parentpid);
  // namespace
  console.log('namespace = ',namespace);
  // target is the local directory holding the ingest files
  console.log('target = ',target);
  // make mongo connection
  /*
  var mongoose = require('mongoose');
  mongoose.connect('mongodb://localhost/ibu');
  var conn = mongoose.connection;
  */
  //
  var $message = 'ingest did not happen';
  var contentmodel = '';
  if ((model)&& (model==='basic')) {
    contentmodel = 'islandora:sp_basic_image';
  }
  if ((model)&&(model==='large')) {
    contentmodel = 'islandora:sp_Large_image';
  }
  console.log('model = ',model);
  // execute first drush command
  var exec = require('child_process').exec;
  var cmd = String('drush -r '+drupalhome+'-v -u=1 --uri='+serveruri+' ibsp --content_models='+contentmodel+' --type=directory --parent='+parentpid+' --namespace='+namespace+' --target='+target );
  // show assembled command
  console.log('cmd=',cmd);
  if ((target !='')&&(contentmodel !='')&&(parentpid !='')&&(namespace !='')) {
    exec(cmd, function(error, stdout, stderr) {
     // command output is in stdout
     console.log(stdout);
     // test command log for success indication
     // test for substr in stdout
     var cmd1bad = 1;
     if (cmd1bad) {
       $message = 'first ingest command failed!';
       console.log($message);
       status.push("$message");
       return $message;
     }
     else {
       $message = 'ingest prep drush command success';
       console.log($message);
       status.push("$message");
       return $message;
     }//end else
    });// end exec
  }// end if
  else {
     console.log('parameters for first command missing, ingest not started.\n');
     $message = 'parameters for first command missing, ingest not started.';
     status.push("$message");
     return $message;
  }
  // exec second drush command
  var cmd2 = String('drush -r '+drupalhome+'-v -u=1 --uri='+serveruri+' islandora_batch_ingest');
  console.log('cmd2=',cmd2);
  if ($message = 'ingest prep drush command success') {
    exec(cmd2, function(error, stdout, stderr) {
     // command output is in stdout
     console.log(stdout);
     // test command log for success indication
     // test for substr in stdout
     $message = 'ingest drush command success';
     console.log($message);
     status.push($message);
    });
  }// end if
  return $message;
}// end function
//export default ingestion;
ingestion(target,parentpid,namespace,model);

<|endoftext|>


<commit_before>/* ============================================================
 * node.bittrex.api
 * https://github.com/n0mad01/node.bittrex.api
 *
 * ============================================================
 * Copyright 2014-2015, Adrian Soluch - http://soluch.us/
 * Released under the MIT License
 * ============================================================ */
var NodeBittrexApi = function() {

  'use strict';

  var request = require('request'),
    hmac_sha512 = require('./hmac-sha512.js'),
    JSONStream = require('JSONStream'),
    es = require('event-stream'),
    jsonic = require('jsonic'),
    signalR = require('signalr-client');

  var start,
    request_options = {
      method: 'GET',
      agent: false,
      headers: {
        'User-Agent': 'Mozilla/4.0 (compatible; Node Bittrex API)',
        'Content-type': 'application/x-www-form-urlencoded'
      }
    };

  var opts = {
    baseUrl: 'https://bittrex.com/api/v1.1',
    websockets_baseurl: 'wss://socket.bittrex.com/signalr',
    websockets_hubs: ['CoreHub'],
    apikey: 'APIKEY',
    apisecret: 'APISECRET',
    verbose: false,
    cleartext: false,
    stream: false,
  };

  var getNonce = function() {
    return Math.floor(new Date().getTime() / 1000);
  };

  var extractOptions = function(options) {

    var o = Object.keys(options),
      i;
    for (i = 0; i < o.length; i++) {
      opts[o[i]] = options[o[i]];
    }
  };

  var apiCredentials = function(uri) {

    var options = {
      apikey: opts.apikey,
      nonce: getNonce()
    };

    return setRequestUriGetParams(uri, options);
  };

  var setRequestUriGetParams = function(uri, options) {

    var op;
    if (typeof(uri) === 'object') {
      op = uri;
      uri = op.uri;
    } else {
      op = request_options;
    }

    var o = Object.keys(options),
      i;
    for (i = 0; i < o.length; i++) {
      uri = updateQueryStringParameter(uri, o[i], options[o[i]]);
    }

    op.headers.apisign = hmac_sha512.HmacSHA512(uri, opts.apisecret); // setting the HMAC hash `apisign` http header
    op.uri = uri;

    return op;
  };

  var updateQueryStringParameter = function(uri, key, value) {

      var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
      var separator = uri.indexOf('?') !== -1 ? "&" : "?";

      if (uri.match(re)) {
          uri = uri.replace(re, '$1' + key + "=" + value + '$2');
      } else {
          uri = uri + separator + key + "=" + value;
      }

      return uri;
  };

  var sendRequestCallback = function(callback, op) {

    start = Date.now();

    switch (opts.stream) {
      case true:
        request(op)
          .pipe(JSONStream.parse('*'))
          .pipe(es.mapSync(function(data) {
            callback(data);
            ((opts.verbose) ? console.log("streamed from " + op.uri + " in: %ds", (Date.now() - start) / 1000) : '');
          }));
        break;
      case false:
        request(op, function(error, result, body) {
          if (!body || !result || result.statusCode != 200) {
            callback({error : error, result : result});
          } else {
            callback(((opts.cleartext) ? body : JSON.parse(body)));
            ((opts.verbose) ? console.log("requested from " + result.request.href + " in: %ds", (Date.now() - start) / 1000) : '');
          }
        });
        break;
    }
  };

  var connectws = function(callback) {

    var client = new signalR.client(
      opts.websockets_baseurl,
      opts.websockets_hubs
    );
    client.serviceHandlers = {
      bound: function() {
        ((opts.verbose) ? console.log('Websocket bound') : '');
      },
      connectFailed: function(error) {
        ((opts.verbose) ? console.log('Websocket connectFailed: ', error) : '');
      },
      connected: function(connection) {
        ((opts.verbose) ? console.log('Websocket connected') : '');
      },
      disconnected: function() {
        ((opts.verbose) ? console.log('Websocket disconnected') : '');
      },
      onerror: function (error) {
        ((opts.verbose) ? console.log('Websocket onerror: ', error) : '');
      },
      bindingError: function (error) {
        ((opts.verbose) ? console.log('Websocket bindingError: ', error) : '');
      },
      connectionLost: function (error) {
        ((opts.verbose) ? console.log('Connection Lost: ', error) : '');
      },
      reconnecting: function (retry) {
        ((opts.verbose) ? console.log('Websocket Retrying: ', retry) : '');
        // change to false to stop retrying
        return true;
      },
      messageReceived: function (message) {
        try {
          var data = jsonic(message.utf8Data);
          if (data && data.M) {
            data.M.forEach(function(M) {
              callback(M);
            })
          } else {
            // ((opts.verbose) ? console.log('Unhandled data', data) : '');
            callback({'unhandled_data' : data});
          }
        } catch (e) {
          ((opts.verbose) ? console.error(e) : '');
        }
        return false;
      }
    };
  }

  return {
    options: function(options) {
      extractOptions(options);
    },
    websockets: function(callback) {
      connectws(callback);
    },
    sendCustomRequest: function(request_string, callback, credentials) {
      var op;

      if (credentials === true) {
        op = apiCredentials(request_string);
      } else {
        op = request_options;
        op.uri = request_string;
      }
      sendRequestCallback(callback, op);
    },
    getmarkets: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getmarkets';
      sendRequestCallback(callback, op);
    },
    getcurrencies: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getcurrencies';
      sendRequestCallback(callback, op);
    },
    getticker: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getticker', options);
      sendRequestCallback(callback, op);
    },
    getmarketsummaries: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getmarketsummaries';
      sendRequestCallback(callback, op);
    },
    getmarketsummary: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getmarketsummary', options);
      sendRequestCallback(callback, op);
    },
    getorderbook: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getorderbook', options);
      sendRequestCallback(callback, op);
    },
    getmarkethistory: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getmarkethistory', options);
      sendRequestCallback(callback, op);
    },
    buylimit: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/buylimit'), options);
      sendRequestCallback(callback, op);
    },
    buymarket: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/buymarket'), options);
      sendRequestCallback(callback, op);
    },
    selllimit: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/selllimit'), options);
      sendRequestCallback(callback, op);
    },
    sellmarket: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/sellmarket'), options);
      sendRequestCallback(callback, op);
    },
    cancel: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/cancel'), options);
      sendRequestCallback(callback, op);
    },
    getopenorders: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/getopenorders'), options);
      sendRequestCallback(callback, op);
    },
    getbalances: function(callback) {
      var op = apiCredentials(opts.baseUrl + '/account/getbalances');
      sendRequestCallback(callback, op);
    },
    getbalance: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getbalance'), options);
      sendRequestCallback(callback, op);
    },
    getwithdrawalhistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getwithdrawalhistory'), options);
      sendRequestCallback(callback, op);
    },
    getdepositaddress: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getdepositaddress'), options);
      sendRequestCallback(callback, op);
    },
    getdeposithistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getdeposithistory'), options);
      sendRequestCallback(callback, op);
    },
    getorderhistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getorderhistory'), options);
      sendRequestCallback(callback, op);
    },
    getorder: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getorder'), options);
      sendRequestCallback(callback, op);
    },
    withdraw: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/withdraw'), options);
      sendRequestCallback(callback, op);
    }
  };
}();

module.exports = NodeBittrexApi;
<commit_msg>subscribe to market for websockets added<commit_after>/* ============================================================
 * node.bittrex.api
 * https://github.com/n0mad01/node.bittrex.api
 *
 * ============================================================
 * Copyright 2014-2017, Adrian Soluch - http://soluch.us/
 * Released under the MIT License
 * ============================================================ */
var NodeBittrexApi = function() {

  'use strict';

  var request = require('request'),
    hmac_sha512 = require('./hmac-sha512.js'),
    JSONStream = require('JSONStream'),
    es = require('event-stream'),
    jsonic = require('jsonic'),
    signalR = require('signalr-client'),
    wsclient;

  var start,
    request_options = {
      method: 'GET',
      agent: false,
      headers: {
        'User-Agent': 'Mozilla/4.0 (compatible; Node Bittrex API)',
        'Content-type': 'application/x-www-form-urlencoded'
      }
    };

  var opts = {
    baseUrl: 'https://bittrex.com/api/v1.1',
    websockets_baseurl: 'wss://socket.bittrex.com/signalr',
    websockets_hubs: ['CoreHub'],
    apikey: 'APIKEY',
    apisecret: 'APISECRET',
    verbose: false,
    cleartext: false,
    stream: false,
  };

  var getNonce = function() {
    return Math.floor(new Date().getTime() / 1000);
  };

  var extractOptions = function(options) {

    var o = Object.keys(options),
      i;
    for (i = 0; i < o.length; i++) {
      opts[o[i]] = options[o[i]];
    }
  };

  var apiCredentials = function(uri) {

    var options = {
      apikey: opts.apikey,
      nonce: getNonce()
    };

    return setRequestUriGetParams(uri, options);
  };

  var setRequestUriGetParams = function(uri, options) {

    var op;
    if (typeof(uri) === 'object') {
      op = uri;
      uri = op.uri;
    } else {
      op = request_options;
    }

    var o = Object.keys(options),
      i;
    for (i = 0; i < o.length; i++) {
      uri = updateQueryStringParameter(uri, o[i], options[o[i]]);
    }

    op.headers.apisign = hmac_sha512.HmacSHA512(uri, opts.apisecret); // setting the HMAC hash `apisign` http header
    op.uri = uri;

    return op;
  };

  var updateQueryStringParameter = function(uri, key, value) {

      var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
      var separator = uri.indexOf('?') !== -1 ? "&" : "?";

      if (uri.match(re)) {
          uri = uri.replace(re, '$1' + key + "=" + value + '$2');
      } else {
          uri = uri + separator + key + "=" + value;
      }

      return uri;
  };

  var sendRequestCallback = function(callback, op) {

    start = Date.now();

    switch (opts.stream) {
      case true:
        request(op)
          .pipe(JSONStream.parse('*'))
          .pipe(es.mapSync(function(data) {
            callback(data);
            ((opts.verbose) ? console.log("streamed from " + op.uri + " in: %ds", (Date.now() - start) / 1000) : '');
          }));
        break;
      case false:
        request(op, function(error, result, body) {
          if (!body || !result || result.statusCode != 200) {
            callback({error : error, result : result});
          } else {
            callback(((opts.cleartext) ? body : JSON.parse(body)));
            ((opts.verbose) ? console.log("requested from " + result.request.href + " in: %ds", (Date.now() - start) / 1000) : '');
          }
        });
        break;
    }
  };

  var connectws = function(callback) {

    wsclient = new signalR.client(
      opts.websockets_baseurl,
      opts.websockets_hubs
    );
    wsclient.serviceHandlers = {
      bound: function() {
        ((opts.verbose) ? console.log('Websocket bound') : '');
      },
      connectFailed: function(error) {
        ((opts.verbose) ? console.log('Websocket connectFailed: ', error) : '');
      },
      disconnected: function() {
        ((opts.verbose) ? console.log('Websocket disconnected') : '');
      },
      onerror: function (error) {
        ((opts.verbose) ? console.log('Websocket onerror: ', error) : '');
      },
      bindingError: function (error) {
        ((opts.verbose) ? console.log('Websocket bindingError: ', error) : '');
      },
      connectionLost: function (error) {
        ((opts.verbose) ? console.log('Connection Lost: ', error) : '');
      },
      reconnecting: function (retry) {
        ((opts.verbose) ? console.log('Websocket Retrying: ', retry) : '');
        // change to false to stop retrying
        return true;
      }
    };
  };

  var setMessageReceivedWs = function(callback) {

    wsclient.serviceHandlers.messageReceived = function (message) {
      try {
        var data = jsonic(message.utf8Data);
        if (data && data.M) {
          data.M.forEach(function(M) {
            callback(M);
          })
        } else {
          // ((opts.verbose) ? console.log('Unhandled data', data) : '');
          callback({'unhandled_data' : data});
        }
      } catch (e) {
        ((opts.verbose) ? console.error(e) : '');
      }
      return false;
    }
  };

  var setConnectedWs = function(markets) {
    wsclient.serviceHandlers.connected = function(connection) {
      markets.forEach(function(market) {
        wsclient.call('CoreHub', 'SubscribeToExchangeDeltas', market).done(function(err, result) {
          if (result === true) {
            ((opts.verbose) ? console.log('Subscribed to ' + market) : '');
          }
        });
      });
      ((opts.verbose) ? console.log('Websocket connected') : '');
    }
  };

  return {
    options : function(options) {
      extractOptions(options);
    },
    websockets : {
      listen : function(callback) {
        connectws();
        setMessageReceivedWs(callback);
      },
      subscribe : function(markets, callback) {
        connectws();
        setConnectedWs(markets);
        setMessageReceivedWs(callback);
      }
    },
    sendCustomRequest : function(request_string, callback, credentials) {
      var op;

      if (credentials === true) {
        op = apiCredentials(request_string);
      } else {
        op = request_options;
        op.uri = request_string;
      }
      sendRequestCallback(callback, op);
    },
    getmarkets: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getmarkets';
      sendRequestCallback(callback, op);
    },
    getcurrencies: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getcurrencies';
      sendRequestCallback(callback, op);
    },
    getticker: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getticker', options);
      sendRequestCallback(callback, op);
    },
    getmarketsummaries: function(callback) {
      var op = request_options;
      op.uri = opts.baseUrl + '/public/getmarketsummaries';
      sendRequestCallback(callback, op);
    },
    getmarketsummary: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getmarketsummary', options);
      sendRequestCallback(callback, op);
    },
    getorderbook: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getorderbook', options);
      sendRequestCallback(callback, op);
    },
    getmarkethistory: function(options, callback) {
      var op = setRequestUriGetParams(opts.baseUrl + '/public/getmarkethistory', options);
      sendRequestCallback(callback, op);
    },
    buylimit: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/buylimit'), options);
      sendRequestCallback(callback, op);
    },
    buymarket: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/buymarket'), options);
      sendRequestCallback(callback, op);
    },
    selllimit: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/selllimit'), options);
      sendRequestCallback(callback, op);
    },
    sellmarket: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/sellmarket'), options);
      sendRequestCallback(callback, op);
    },
    cancel: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/cancel'), options);
      sendRequestCallback(callback, op);
    },
    getopenorders: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/market/getopenorders'), options);
      sendRequestCallback(callback, op);
    },
    getbalances: function(callback) {
      var op = apiCredentials(opts.baseUrl + '/account/getbalances');
      sendRequestCallback(callback, op);
    },
    getbalance: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getbalance'), options);
      sendRequestCallback(callback, op);
    },
    getwithdrawalhistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getwithdrawalhistory'), options);
      sendRequestCallback(callback, op);
    },
    getdepositaddress: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getdepositaddress'), options);
      sendRequestCallback(callback, op);
    },
    getdeposithistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getdeposithistory'), options);
      sendRequestCallback(callback, op);
    },
    getorderhistory: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getorderhistory'), options);
      sendRequestCallback(callback, op);
    },
    getorder: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/getorder'), options);
      sendRequestCallback(callback, op);
    },
    withdraw: function(options, callback) {
      var op = setRequestUriGetParams(apiCredentials(opts.baseUrl + '/account/withdraw'), options);
      sendRequestCallback(callback, op);
    }
  };
}();

module.exports = NodeBittrexApi;
<|endoftext|>


<commit_before>const _ = require('lodash');
const {getNumber, getCollection} = require('./file');

class Merge {
  constructor(filename) {
    this.filename = filename;
  }

  async* merge() {
    const findMin = (values) => {
      let minIdx = undefined;
      for (const idx of _.range(number)) {
        const v = values[idx];
        if (_.isUndefined(v)) {
          continue;
        }
        minIdx = minIdx === undefined ? idx : minIdx;
        if (v < values[minIdx]) {
          minIdx = idx;
        }
      }
      return minIdx;
    };

    const number = await getNumber(this.filename);
    const collections = _.map(_.range(number), (i) => {
      return getCollection(this.filename, i);
    });
    const next = (i) => collections[i].next().then((x) => x.value);

    const initialValues = function* () {
      for (const i of _.range(number)) {
        yield next(i);
      }
    };
    const values = await Promise.all(initialValues());

    while (true) {
      if (_.every(values, (v) => _.isUndefined(v))) {
        break;
      }

      const minIdx = findMin(values);
      yield values[minIdx];
      values[minIdx] = await next(minIdx);
    }
  }
}

exports.Merge = Merge;
<commit_msg>use lodash fp<commit_after>const fp = require('lodash/fp');
const {getNumber, getCollection} = require('./file');

class Merge {
  constructor(filename) {
    this.filename = filename;
  }

  async* merge() {
    const findMin = (values) => {
      let minIdx = undefined;
      for (const idx of fp.range(0, number)) {
        const v = values[idx];
        if (fp.isUndefined(v)) {
          continue;
        }
        minIdx = minIdx === undefined ? idx : minIdx;
        if (v < values[minIdx]) {
          minIdx = idx;
        }
      }
      return minIdx;
    };

    const number = await getNumber(this.filename);
    const collections = fp.map((i) => getCollection(this.filename, i))(fp.range(0, number));
    const next = (i) => collections[i].next().then((x) => x.value);

    const initialValues = function* () {
      for (const i of fp.range(0,number)) {
        yield next(i);
      }
    };
    const values = await Promise.all(initialValues());

    while (true) {
      if (fp.every(fp.isUndefined)(values)) {
        break;
      }

      const minIdx = findMin(values);
      yield values[minIdx];
      values[minIdx] = await next(minIdx);
    }
  }
}

exports.Merge = Merge;
<|endoftext|>