<commit_before>// Registration
$registrationSection = $('.registration-section'),
$confirmationSection = $('.confirmation-section'),
$registerForm = $('.form.registration'),
eventCode = $('#event-code').text().toLowerCase(),
eventTitle = $('#event-name').text(), // Stripe description
eventStartDate = $('#event-start').text(),
eventDates = $('#event-dates').text(),
eventVenue = $('#event-venue').text(),
eventDepositAmount = $('#event-deposit-amount').text(),
eventDepositDate = $('#event-deposit-date').text(),
eventLodgingOptions = $('#event-lodging-options').text(),
eventLodgingPrices = $('#event-lodging-prices').text(),
eventStripe = $('#event-stripe').text()

// Event initialization
const eventButton = '.button.register',
eventFirstName = '#event-firstname',
eventLastName = '#event-lastname',
eventEmail = '#event-email',
eventMobile = '#event-mobile',
eventBirthdate = '#event-birthdate',
eventFemale = '#event-gender-female',
eventMale = '#event-gender-male',
eventOther = '#event-gender-other',
eventReferral = '#event-referral',
eventExperienceContainer = '.event-container.experience',
eventExperienceYes = '#event-experience-yes',
eventExperienceNo = '#event-experience-no',
eventExperienceDetails = '#event-experience-details',
eventDietContainer = '.event-container.diet',
eventDietYes = '#event-diet-yes',
eventDietNo = '#event-diet-no',
eventDietDetails = '#event-diet-details'
eventStatus = '#event-status',
eventPartnerContainer = '.event-container.partner',
eventPartnerName = '#event-partner-name'
eventPartnerFemale = '#event-partner-gender-female',
eventPartnerMale = '#event-partner-gender-male',
eventPartnerOther = '#event-partner-gender-other',
eventPayBoth = '#event-pay-both',
eventPayMe = '#event-pay-me',
eventLodging = '#event-lodging',
eventDepositContainer = '.event-container.deposit',
eventDepositText = '#event-deposit-text',
eventDepositFull = '#event-deposit-full',
eventDepositDeposit = '#event-deposit-deposit',
eventTerms = '#event-terms'

// SAVE FORM
function saveEvent() {
	var values = {};
	$('input, textarea, select').each(function() {
		if ($(this).is(':radio')) {
			if ($(this).is(':checked')) { values[$(this).attr('name')] = $(this).val() }
		}
		else {
			values[$(this).attr('name')] = $(this).val()
		}
	})
	localStorage.setItem('EcstaticLiving:Event', JSON.stringify(values))
}

// REPOPULATE SAVED FORM
function repopulateEvent() {
	if (localStorage.getItem('EcstaticLiving:Event')) {
		var values = JSON.parse(localStorage.getItem('EcstaticLiving:Event'))
		for (var item in values) {
			if ($('*[name=' + item + ']').is(':radio')) {
				$('input[name=' + item + '][value="' + values[item] + '"]').prop('checked', true)
			}
			else {
				$('*[name=' + item + ']').val(values[item])
			}
		}
		localStorage.removeItem('EcstaticLiving:Event')
	}
}

// PARTICIPANTS
function participants() {
	if (($(eventStatus).find('option:selected').val() === 'Couple') || ($(eventStatus).find('option:selected').val() === 'Two Singles (paired)')) {
		return 2
	} else if ($(eventStatus).find('option:selected').val() === 'Single') {
		return 1
	}
}

// FORM VALIDATION
function validationPersonal() {
	if ($(eventFirstName).val() !== '' && $(eventLastName).val() !== '' && $(eventEmail).val() !== '' && $(eventMobile).val() !== '' && $(eventBirthdate).val() !== '' &&
		($(eventFemale).is(':checked') || $(eventMale).is(':checked') || $(eventOther).is(':checked'))) {
		return true
	}
	return false
}
function validationDetails() {
	if ($(eventReferral).val() !== ''
		&& (($(eventExperienceYes).is(':checked') && $(eventExperienceDetails).val() !== '') || $(eventExperienceNo).is(':checked'))
		&& (($(eventDietYes).is(':checked') && $(eventDietDetails).val() !== '') || $(eventDietNo).is(':checked'))) {
		return true
	}
	return false
}
function validationStatus() {
	if (
		(participants() === 2
			&& $(eventPartnerName).val() !== ''
			&& ($(eventPartnerFemale).is(':checked') || $(eventPartnerMale).is(':checked') || $(eventPartnerOther).is(':checked'))
			&& ($(eventPayBoth).is(':checked') || $(eventPayMe).is(':checked')))
		|| participants() === 1
	) {
		return true
	}
	return false
}
function validationLodging() {
	if ($(eventLodging).val() !== '' && (
		$(eventDepositContainer).is(':visible') && ($(eventDepositFull).is(':checked') || $(eventDepositDeposit).is(':checked'))
	) || $(eventDepositContainer).is(':hidden')) {
		return true
	}
	return false
}
function eventValidation() {
	if (validationPersonal() && validationDetails() && validationStatus() && validationLodging() && $(eventTerms).is(':checked')) {
		console.log('*** VALID ***');
		document.getElementById('register-button').disabled = false
		$(eventButton).css({ 'background-image': 'linear-gradient(bottom left, #800000 100%, #b00000 100%)' })
		$(eventButton).css({ 'color': '#ffffff' })
	} else {
		document.getElementById('register-button').disabled = true
		$(eventButton).css({ 'background-image': '' })
		$(eventButton).css({ 'color': '#333333' })
	}
}
$(eventFirstName + ',' + eventLastName + ',' + eventEmail + ',' + eventMobile + ',' + eventBirthdate + ',' + eventFemale + ',' + eventMale + ',' + eventOther + ',' + eventReferral + ',' + eventExperienceDetails + ',' + eventDietDetails + ',' + eventStatus + ',' + eventPartnerName + ',' + eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventLodging + ',' + eventTerms).on('change', function () {
	eventValidation()
})

// PARTNERSHIP
function showPartner() {
	$(eventPartnerContainer).show()
	$(eventPartnerContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else {
		resetLodging('per person')
	}
}

function hidePartner() {
	$(eventPartnerName).val('')
	$(eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventPayBoth + ',' + eventPayMe).prop('checked', false)
	$(eventPartnerContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventPartnerContainer).hide()
	resetLodging()
}

$(eventStatus).change(function() {
	participants() === 2 ? showPartner() : hidePartner()
})

$(eventPayBoth + ',' + eventPayMe).change(function() {
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else if (participants() === 2) {
		resetLodging('per person')
	} else {
		resetLodging('')
	}
})

// PREVIOUS EXPERIENCE
function showExperience() {
	$(eventExperienceContainer).show()
	$(eventExperienceContainer).animate({
		top: 40,
		opacity: 1
	}, 200)
}

function hideExperience() {
	$(eventExperienceDetails).val('')
	$(eventExperienceContainer).animate({
		top: 0,
		opacity: 0
	}, 200)
	$(eventExperienceContainer).hide()
}

$(eventExperienceNo + ',' + eventExperienceYes).change(function() {
	if ($(eventExperienceYes).is(':checked')) showExperience()
	if ($(eventExperienceNo).is(':checked')) hideExperience()
})

// DIETARY NEEDS
function showDiet() {
	$(eventDietContainer).show()
	$(eventDietContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
}

function hideDiet() {
	$(eventDietDetails).val('')
	$(eventDietContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventDietContainer).hide()
}

$(eventDietNo + ',' + eventDietYes).change(function() {
	if ($(eventDietYes).is(':checked')) showDiet()
	if ($(eventDietNo).is(':checked')) hideDiet()
})

// LODGING
function resetLodging(paymentStatus) {
	//	Adds lodging options & prices based on CMS input
	var lodgingOptions = eventLodgingOptions.split(' | ')
	var lodgingPrices = eventLodgingPrices.split(' | ')
	$(eventLodging).empty()
	if (lodgingOptions.length > 0) {
		$(eventLodging).append($('<option>', {
			value: '',
			text: 'Event option...'
		}))
	}
	paymentStatus = paymentStatus ? paymentStatus : ''
	const paymentFactor = (paymentStatus === 'for both') ? 2 : 1
	const spacer = paymentStatus ? ' ' : ''
	const closer = (paymentStatus || paymentStatus === '') ? ')' : ''
	for (let i = 0; i < lodgingOptions.length; i++) {
		$(eventLodging).append($('<option>', {
			value: lodgingPrices[i] * paymentFactor,
			text: lodgingOptions[i] + ' ($' + lodgingPrices[i] * paymentFactor + spacer + paymentStatus + closer
		}))
	}
	eventPrice = parseInt(eventDepositAmount) * paymentFactor
	$(eventDepositText).text(`Pay deposit only ($${eventPrice}${spacer}${paymentStatus})`)
}

// SHOW REGISTRATION
function showRegistration() {
	$registrationSection.show()
	$confirmationSection.hide()
}

// SHOW CONFIRMATION
function showConfirmation() {
	$registrationSection.hide()
	$confirmationSection.show()
}

function resetEventForm() {
	showRegistration()
	$('.w-form-done').hide()
	$('.w-form-fail').hide()
	$registerForm[0].reset()
	repopulateEvent()
	resetLodging()
	if ($(eventExperienceDetails).val() === '') hideExperience()
	if ($(eventDietDetails).val() === '') hideDiet()
	if ($(eventPartnerName).val() === '') hidePartner()
	eventValidation()
	if (new Date() < new Date(eventDepositDate)) {
		$(eventDepositContainer).show()
		$(eventDepositFull).prop('checked', true)
	} else {
		$(eventDepositContainer).hide()
	}
	$registerForm.parsley()
	$registerForm.show()
	$(eventTerms).attr('checked', false)
	eventValidation()
}

// EVENT PAGE
if (window.location.href.indexOf('/events/') > -1) {
	resetEventForm()
}
<commit_msg>Integrating form into website.<commit_after>// Registration
$registrationSection = $('.registration-section'),
$confirmationSection = $('.confirmation-section'),
$registerForm = $('.form.registration'),
eventCode = $('#event-code').text().toLowerCase(),
eventTitle = $('#event-name').text(), // Stripe description
eventStartDate = $('#event-start').text(),
eventDates = $('#event-dates').text(),
eventVenue = $('#event-venue').text(),
eventDepositAmount = $('#event-deposit-amount').text(),
eventDepositDate = $('#event-deposit-date').text(),
eventLodgingOptions = $('#event-lodging-options').text(),
eventLodgingPrices = $('#event-lodging-prices').text(),
eventStripe = $('#event-stripe').text()

// Event initialization
const eventButton = '.button.register',
eventFirstName = '#event-firstname',
eventLastName = '#event-lastname',
eventEmail = '#event-email',
eventMobile = '#event-mobile',
eventBirthdate = '#event-birthdate',
eventFemale = '#event-gender-female',
eventMale = '#event-gender-male',
eventOther = '#event-gender-other',
eventReferral = '#event-referral',
eventExperienceContainer = '.event-container.experience',
eventExperienceYes = '#event-experience-yes',
eventExperienceNo = '#event-experience-no',
eventExperienceDetails = '#event-experience-details',
eventDietContainer = '.event-container.diet',
eventDietYes = '#event-diet-yes',
eventDietNo = '#event-diet-no',
eventDietDetails = '#event-diet-details'
eventStatus = '#event-status',
eventPartnerContainer = '.event-container.partner',
eventPartnerName = '#event-partner-name'
eventPartnerFemale = '#event-partner-gender-female',
eventPartnerMale = '#event-partner-gender-male',
eventPartnerOther = '#event-partner-gender-other',
eventPayBoth = '#event-pay-both',
eventPayMe = '#event-pay-me',
eventLodging = '#event-lodging',
eventDepositContainer = '.event-container.deposit',
eventDepositText = '#event-deposit-text',
eventDepositFull = '#event-deposit-full',
eventDepositDeposit = '#event-deposit-deposit',
eventTerms = '#event-terms'

// SAVE FORM
function saveEvent() {
	var values = {};
	$('input, textarea, select').each(function() {
		if ($(this).is(':radio')) {
			if ($(this).is(':checked')) { values[$(this).attr('name')] = $(this).val() }
		}
		else {
			values[$(this).attr('name')] = $(this).val()
		}
	})
	localStorage.setItem('EcstaticLiving:Event', JSON.stringify(values))
}

// REPOPULATE SAVED FORM
function repopulateEvent() {
	if (localStorage.getItem('EcstaticLiving:Event')) {
		var values = JSON.parse(localStorage.getItem('EcstaticLiving:Event'))
		for (var item in values) {
			if ($('*[name=' + item + ']').is(':radio')) {
				$('input[name=' + item + '][value="' + values[item] + '"]').prop('checked', true)
			}
			else {
				$('*[name=' + item + ']').val(values[item])
			}
		}
		localStorage.removeItem('EcstaticLiving:Event')
	}
}

// PARTICIPANTS
function participants() {
	if (($(eventStatus).find('option:selected').val() === 'Couple') || ($(eventStatus).find('option:selected').val() === 'Two Singles (paired)')) {
		return 2
	} else if ($(eventStatus).find('option:selected').val() === 'Single') {
		return 1
	}
}

// FORM VALIDATION
function validationPersonal() {
	if ($(eventFirstName).val() !== '' && $(eventLastName).val() !== '' && $(eventEmail).val() !== '' && $(eventMobile).val() !== '' && $(eventBirthdate).val() !== '' &&
		($(eventFemale).is(':checked') || $(eventMale).is(':checked') || $(eventOther).is(':checked'))) {
		return true
	}
	return false
}
function validationDetails() {
	if ($(eventReferral).val() !== ''
		&& (($(eventExperienceYes).is(':checked') && $(eventExperienceDetails).val() !== '') || $(eventExperienceNo).is(':checked'))
		&& (($(eventDietYes).is(':checked') && $(eventDietDetails).val() !== '') || $(eventDietNo).is(':checked'))) {
		return true
	}
	return false
}
function validationStatus() {
	if (
		(participants() === 2
			&& $(eventPartnerName).val() !== ''
			&& ($(eventPartnerFemale).is(':checked') || $(eventPartnerMale).is(':checked') || $(eventPartnerOther).is(':checked'))
			&& ($(eventPayBoth).is(':checked') || $(eventPayMe).is(':checked')))
		|| participants() === 1
	) {
		return true
	}
	return false
}
function validationLodging() {
	if ($(eventLodging).val() !== '' && (
		$(eventDepositContainer).is(':visible') && ($(eventDepositFull).is(':checked') || $(eventDepositDeposit).is(':checked'))
	) || $(eventDepositContainer).is(':hidden')) {
		return true
	}
	return false
}
var number = 0
function eventValidation() {
	number++
	if (validationPersonal() && validationDetails() && validationStatus() && validationLodging() && $(eventTerms).is(':checked')) {
		console.log('*** VALID ***');
		document.getElementById('register-button').disabled = false
		$(eventButton).css({ 'background-image': 'linear-gradient(bottom left, #800000 100%, #b00000 100%)' })
		$(eventButton).css({ 'color': '#ffffff' })
	} else {
		console.log(`Pass ${number}`);
		document.getElementById('register-button').disabled = true
		$(eventButton).css({ 'background-image': '' })
		$(eventButton).css({ 'color': '#333333' })
	}
}
$(eventFirstName + ',' + eventLastName + ',' + eventEmail + ',' + eventMobile + ',' + eventBirthdate + ',' + eventFemale + ',' + eventMale + ',' + eventOther + ',' + eventReferral + ',' + eventExperienceDetails + ',' + eventDietDetails + ',' + eventStatus + ',' + eventPartnerName + ',' + eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventLodging + ',' + eventTerms).on('change', function () {
	eventValidation()
})

// PARTNERSHIP
function showPartner() {
	$(eventPartnerContainer).show()
	$(eventPartnerContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else {
		resetLodging('per person')
	}
}

function hidePartner() {
	$(eventPartnerName).val('')
	$(eventPartnerFemale + ',' + eventPartnerMale + ',' + eventPartnerOther + ',' + eventPayBoth + ',' + eventPayMe).prop('checked', false)
	$(eventPartnerContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventPartnerContainer).hide()
	resetLodging()
}

$(eventStatus).change(function() {
	participants() === 2 ? showPartner() : hidePartner()
})

$(eventPayBoth + ',' + eventPayMe).change(function() {
	if ($(eventPayBoth).is(':checked')) {
		resetLodging('for both')
	} else if (participants() === 2) {
		resetLodging('per person')
	} else {
		resetLodging('')
	}
})

// PREVIOUS EXPERIENCE
function showExperience() {
	$(eventExperienceContainer).show()
	$(eventExperienceContainer).animate({
		top: 40,
		opacity: 1
	}, 200)
}

function hideExperience() {
	$(eventExperienceDetails).val('')
	$(eventExperienceContainer).animate({
		top: 0,
		opacity: 0
	}, 200)
	$(eventExperienceContainer).hide()
}

$(eventExperienceNo + ',' + eventExperienceYes).change(function() {
	if ($(eventExperienceYes).is(':checked')) showExperience()
	if ($(eventExperienceNo).is(':checked')) hideExperience()
})

// DIETARY NEEDS
function showDiet() {
	$(eventDietContainer).show()
	$(eventDietContainer).animate({
		top: 0,
		opacity: 1
	}, 200)
}

function hideDiet() {
	$(eventDietDetails).val('')
	$(eventDietContainer).animate({
		top: -40,
		opacity: 0
	}, 200)
	$(eventDietContainer).hide()
}

$(eventDietNo + ',' + eventDietYes).change(function() {
	if ($(eventDietYes).is(':checked')) showDiet()
	if ($(eventDietNo).is(':checked')) hideDiet()
})

// LODGING
function resetLodging(paymentStatus) {
	//	Adds lodging options & prices based on CMS input
	var lodgingOptions = eventLodgingOptions.split(' | ')
	var lodgingPrices = eventLodgingPrices.split(' | ')
	$(eventLodging).empty()
	if (lodgingOptions.length > 0) {
		$(eventLodging).append($('<option>', {
			value: '',
			text: 'Event option...'
		}))
	}
	paymentStatus = paymentStatus ? paymentStatus : ''
	const paymentFactor = (paymentStatus === 'for both') ? 2 : 1
	const spacer = paymentStatus ? ' ' : ''
	const closer = (paymentStatus || paymentStatus === '') ? ')' : ''
	for (let i = 0; i < lodgingOptions.length; i++) {
		$(eventLodging).append($('<option>', {
			value: lodgingPrices[i] * paymentFactor,
			text: lodgingOptions[i] + ' ($' + lodgingPrices[i] * paymentFactor + spacer + paymentStatus + closer
		}))
	}
	eventPrice = parseInt(eventDepositAmount) * paymentFactor
	$(eventDepositText).text(`Pay deposit only ($${eventPrice}${spacer}${paymentStatus})`)
}

// SHOW REGISTRATION
function showRegistration() {
	$registrationSection.show()
	$confirmationSection.hide()
}

// SHOW CONFIRMATION
function showConfirmation() {
	$registrationSection.hide()
	$confirmationSection.show()
}

function resetEventForm() {
	showRegistration()
	$('.w-form-done').hide()
	$('.w-form-fail').hide()
	$registerForm[0].reset()
	repopulateEvent()
	resetLodging()
	if ($(eventExperienceDetails).val() === '') hideExperience()
	if ($(eventDietDetails).val() === '') hideDiet()
	if ($(eventPartnerName).val() === '') hidePartner()
	eventValidation()
	if (new Date() < new Date(eventDepositDate)) {
		$(eventDepositContainer).show()
		$(eventDepositFull).prop('checked', true)
	} else {
		$(eventDepositContainer).hide()
	}
	$registerForm.parsley()
	$registerForm.show()
	$(eventTerms).attr('checked', false)
	eventValidation()
}

// EVENT PAGE
if (window.location.href.indexOf('/events/') > -1) {
	resetEventForm()
}
<|endoftext|>


<commit_before>var MtGoxClient = require("mtgox-apiv2");
var util = require('../util.js');
var _ = require('lodash');
var log = require('../log.js');
var moment = require('moment');

var Trader = function(config) {
  if(_.isObject(config)) {
    this.key = config.key;
    this.secret = config.secret;
    this.currency = config.currency || 'USD';

    this.pair = 'BTC' + this.currency;
  }
  this.name = 'Mt. Gox';

  _.bindAll(this);

  this.mtgox = new MtGoxClient(this.key, this.secret, this.pair);
}

Trader.prototype.buy = function(amount, price, callback) {
  this.mtgox.add('bid', amount, price, function(err, result) {
    this.checkUnauthorized(err);
    // if Mt. Gox is down or lagging
    if(err || result.result === 'error')
      log.error('unable to buy (', err, result, ')');

    callback(err, result.data);
  });
}

Trader.prototype.sell = function(amount, price, callback) {
  this.mtgox.add('ask', amount, price, function(err, result) {
    this.checkUnauthorized(err);
    // if Mt. Gox is down or lagging
    if(err || result.result === 'error')
      log.error('unable to sell (', err, result, ')');

    callback(err, result.data);
  });
}

Trader.prototype.getTrades = function(since, callback, descending) {
  if(since && !_.isNumber(since))
    since = util.toMicro(since);

  var args = _.toArray(arguments);
  this.mtgox.fetchTrades(since, _.bind(function(err, trades) {
    if (err || !trades)
      return this.retry(this.getTrades, args);

    trades = trades.data;
    if (trades.length === 0)
      return this.retry(this.getTrades, args);

    if(descending)
      callback(trades.reverse());
    else
      callback(trades);
  }, this));
}

// if the exchange errors we try the same call again after
// waiting 10 seconds
Trader.prototype.retry = function(method, args) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..');

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait.
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.checkUnauthorized = function(err) {
  if(err.message === 'Request failed with 403')
    throw 'It appears your ' + this.name + ' API key and secret are incorrect';
}

// calls callback with the following data structure:
//
// [
//  { name: 'BTC', amount: 10.12413123},
//  { name: 'USD', amount: 500.0241},
//  { name: 'EUR', amount: 0},
// ]
Trader.prototype.getPortfolio = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, result) {
    this.checkUnauthorized(err);
    if(err)
      return this.retry(this.getPortfolio, args);

    if(!('Wallets' in result.data))
      log.error('unable to get portfolio, do I have get_info rights?');

    var assets = [];
    _.each(result.data.Wallets, function(wallet, name) {
      var amount = parseFloat(wallet.Balance.value);
      assets.push({name: name, amount: amount});
    });
    callback(null, assets);
  };

  this.mtgox.info(_.bind(calculate, this));
}

Trader.prototype.getFee = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, result) {
    this.checkUnauthorized(err);
    if(err)
      return this.retry(this.getFee, args);

    // convert the %
    var fee = result.data.Trade_Fee / 100;
    callback(null, fee);
  };

  this.mtgox.info(_.bind(calculate, this));
}

Trader.prototype.checkOrder = function(order, callback) {
  var args = _.toArray(arguments);
  // we can't just request the order id
  // @link https://bitbucket.org/nitrous/mtgox-api/#markdown-header-moneyorderresult
  var check = function(err, result) {
    if(err)
      return this.retry(this.checkOrder, args);

    var stillThere = _.find(result.data, function(o) { return o.oid === order });
    callback(null, !stillThere);
  };

  this.mtgox.orders(_.bind(check, this));
}

Trader.prototype.cancelOrder = function(order) {
  var cancel = function(err, result) {
    if(err || result.result !== 'succes')
      log.error('unable to cancel order', order, '(', err, result, ')');
  };

  this.mtgox.cancel(order, _.bind(cancel, this));
}

Trader.prototype.getTicker = function(callback) {
  var args = _.toArray(arguments);
  var set = function(err, result) {
    if(err)
      return this.retry(this.getTicker, args);

    var ticker = {
      bid: result.data.buy.value,
      ask: result.data.sell.value
    }
    callback(err, ticker);
  };

  this.mtgox.ticker(_.bind(set, this));
}

module.exports = Trader;

<commit_msg>fixed auth check error (again)<commit_after>var MtGoxClient = require("mtgox-apiv2");
var util = require('../util.js');
var _ = require('lodash');
var log = require('../log.js');
var moment = require('moment');

var Trader = function(config) {
  if(_.isObject(config)) {
    this.key = config.key;
    this.secret = config.secret;
    this.currency = config.currency || 'USD';

    this.pair = 'BTC' + this.currency;
  }
  this.name = 'Mt. Gox';

  _.bindAll(this);

  this.mtgox = new MtGoxClient(this.key, this.secret, this.pair);
}

Trader.prototype.buy = function(amount, price, callback) {
  this.mtgox.add('bid', amount, price, function(err, result) {
    this.checkUnauthorized(err);
    // if Mt. Gox is down or lagging
    if(err || result.result === 'error')
      log.error('unable to buy (', err, result, ')');

    callback(err, result.data);
  });
}

Trader.prototype.sell = function(amount, price, callback) {
  this.mtgox.add('ask', amount, price, function(err, result) {
    this.checkUnauthorized(err);
    // if Mt. Gox is down or lagging
    if(err || result.result === 'error')
      log.error('unable to sell (', err, result, ')');

    callback(err, result.data);
  });
}

Trader.prototype.getTrades = function(since, callback, descending) {
  if(since && !_.isNumber(since))
    since = util.toMicro(since);

  var args = _.toArray(arguments);
  this.mtgox.fetchTrades(since, _.bind(function(err, trades) {
    if (err || !trades)
      return this.retry(this.getTrades, args);

    trades = trades.data;
    if (trades.length === 0)
      return this.retry(this.getTrades, args);

    if(descending)
      callback(trades.reverse());
    else
      callback(trades);
  }, this));
}

// if the exchange errors we try the same call again after
// waiting 10 seconds
Trader.prototype.retry = function(method, args) {
  var wait = +moment.duration(10, 'seconds');
  log.debug(this.name, 'returned an error, retrying..');

  var self = this;

  // make sure the callback (and any other fn)
  // is bound to Trader
  _.each(args, function(arg, i) {
    if(_.isFunction(arg))
      args[i] = _.bind(arg, self);
  });

  // run the failed method again with the same
  // arguments after wait.
  setTimeout(
    function() { method.apply(self, args) },
    wait
  );
}

Trader.prototype.checkUnauthorized = function(err) {
  if(err && err.message === 'Request failed with 403')
    throw 'It appears your ' + this.name + ' API key and secret are incorrect';
}

// calls callback with the following data structure:
//
// [
//  { name: 'BTC', amount: 10.12413123},
//  { name: 'USD', amount: 500.0241},
//  { name: 'EUR', amount: 0},
// ]
Trader.prototype.getPortfolio = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, result) {
    this.checkUnauthorized(err);
    if(err)
      return this.retry(this.getPortfolio, args);

    if(!('Wallets' in result.data))
      log.error('unable to get portfolio, do I have get_info rights?');

    var assets = [];
    _.each(result.data.Wallets, function(wallet, name) {
      var amount = parseFloat(wallet.Balance.value);
      assets.push({name: name, amount: amount});
    });
    callback(null, assets);
  };

  this.mtgox.info(_.bind(calculate, this));
}

Trader.prototype.getFee = function(callback) {
  var args = _.toArray(arguments);
  var calculate = function(err, result) {
    this.checkUnauthorized(err);
    if(err)
      return this.retry(this.getFee, args);

    // convert the %
    var fee = result.data.Trade_Fee / 100;
    callback(null, fee);
  };

  this.mtgox.info(_.bind(calculate, this));
}

Trader.prototype.checkOrder = function(order, callback) {
  var args = _.toArray(arguments);
  // we can't just request the order id
  // @link https://bitbucket.org/nitrous/mtgox-api/#markdown-header-moneyorderresult
  var check = function(err, result) {
    if(err)
      return this.retry(this.checkOrder, args);

    var stillThere = _.find(result.data, function(o) { return o.oid === order });
    callback(null, !stillThere);
  };

  this.mtgox.orders(_.bind(check, this));
}

Trader.prototype.cancelOrder = function(order) {
  var cancel = function(err, result) {
    if(err || result.result !== 'succes')
      log.error('unable to cancel order', order, '(', err, result, ')');
  };

  this.mtgox.cancel(order, _.bind(cancel, this));
}

Trader.prototype.getTicker = function(callback) {
  var args = _.toArray(arguments);
  var set = function(err, result) {
    if(err)
      return this.retry(this.getTicker, args);

    var ticker = {
      bid: result.data.buy.value,
      ask: result.data.sell.value
    }
    callback(err, ticker);
  };

  this.mtgox.ticker(_.bind(set, this));
}

module.exports = Trader;

<|endoftext|>


<commit_before>(function() {

  var INSPECTION_THRESHOLD = -2000;
  var UPDATE_INTERVAL = Math.floor(1000 / 24);
  var WCA_INSPECTION_TIME = 15000;

  function Timer() {
    window.app.EventEmitter.call(this);

    this._state = Timer.STATE_NOT_RUNNING;
    this._startTime = 0;
    this._updateInterval = null;

    this._deviceTime = 0;
    this._manualTime = 0;

    this._memoTime = 0;
    this._totalTime = 0;
    this._inspectionTime = 0;

    this.reset();
  }

  Timer.prototype = Object.create(window.app.EventEmitter.prototype);

  Timer.INPUT_REGULAR = 0;
  Timer.INPUT_INSPECTION = 1;
  Timer.INPUT_BLD = 2;
  Timer.INPUT_STACKMAT = 3;
  Timer.INPUT_ENTRY = 4;

  Timer.STATE_NOT_RUNNING = 0;
  Timer.STATE_MANUAL_ENTRY = 1;
  Timer.STATE_WAITING = 2;
  Timer.STATE_INSPECTION_READY = 3;
  Timer.STATE_INSPECTION = 4;
  Timer.STATE_READY = 5;
  Timer.STATE_TIMING = 6;
  Timer.STATE_TIMING_DONE_MEMO = 7;
  Timer.STATE_DEVICE_TIMING = 8;
  Timer.STATE_DONE = 9;

  Timer.prototype.deviceTiming = function(time) {
    this._assertStates([Timer.STATE_READY, Timer.STATE_DEVICE_TIMING]);
    this._state = Timer.STATE_DEVICE_TIMING;
    this._deviceTime = time;
    this.emit('deviceTiming');
  };

  Timer.prototype.done = function() {
    this._assertStates([Timer.STATE_TIMING, Timer.STATE_DEVICE_TIMING]);
    if (this._updateInterval) {
      clearInterval(this._updateInterval);
      this._updateInterval = null;
    }
    if (this._state === Timer.STATE_TIMING) {
      this._totalTime = this.getTime();
    } else {
      this._totalTime = this.getDeviceTime();
    }
  };

  Timer.prototype.doneMemo = function() {
    this._assertState(Timer.STATE_TIMER);
    this._state = STATE_TIMING_DONE_MEMO;
    this._memoTime = this.getTime();
    this.emit('doneMemo');
  };

  Timer.prototype.getDeviceTime = function() {
    return this._deviceTime;
  };

  Timer.prototype.getInspectionTime = function() {
    switch (this._state) {
    case Timer.STATE_INSPECTION:
      var elapsed = new Date().getTime() - this._startTime;
      return WCA_INSPECTION_TIME - elapsed;
    case Timer.STATE_DONE:
      return this._inspectionTime;
    default:
      return 0;
    }
  };

  Timer.prototype.getManualTime = function() {
    return this._manualTime;
  };

  Timer.prototype.getState = function() {
    return this._state;
  };

  Timer.prototype.getTime = function() {
    switch (this._state) {
    case Timer.STATE_TIMING:
    case Timer.STATE_TIMING_AFTER_MEMO:
      return new Date().getTime() - this._startTime;
    case Timer.STATE_DONE:
      return this._totalTime;
    default:
      return 0;
    }
  };

  Timer.prototype.inspection = function() {
    this._assertState(Timer.STATE_INSPECTION_READY);

    this._startTime = new Date().getTime();
    this._updateInterval = setInterval(function() {
      if (this.getInspectionTime() < INSPECTION_THRESHOLD) {
        this.timing();
      } else {
        this.emit('inspection');
      }
    }.bind(this), UPDATE_INTERVAL);

    this._state = Timer.STATE_INSPECTION;
    this.emit('inspection');
  };

  Timer.prototype.inspectionReady = function() {
    this._assertState(Timer.STATE_NOT_RUNNING);
    this._state = Timer.STATE_INSPECTION_READY;
    this.emit('inspectionReady');
  };

  Timer.prototype.manualTime = function(time) {
    this._assertState(Timer.STATE_MANUAL_ENTRY);
    this._manualTime = time;
    this.emit('manualTime');
  };

  Timer.prototype.ready = function() {
    this._assertStates([Timer.STATE_NOT_RUNNING, Timer.STATE_WAITING]);
    this._state = Timer.STATE_READY;
    this.emit('ready');
  };

  Timer.prototype.reset = function() {
    if (window.app.store.getActivePuzzle().timerInput === Timer.INPUT_ENTRY) {
      this._state = Timer.STATE_MANUAL_ENTRY;
    } else {
      this._state = Timer.STATE_NOT_RUNNING;
    }
    this._startTime = 0;
    this._deviceTime = 0;
    this._manualTime = 0;
    this._memoTime = 0;
    this._totalTime = 0;
    this._inspectionTime = 0;
    this.emit('reset');
  };

  Timer.prototype.timing = function() {
    this._assertStates([Timer.STATE_INSPECTION, Timer.STATE_READY]);

    if (this._updateInterval !== null) {
      clearInterval(this._updateInterval);
    }

    var now = new Date().getTime();

    if (this._state === Timer.STATE_INSPECTION) {
      this._inspectionTime = now - this._startTime;
    }

    this._startTime = now;
    this._state = Timer.STATE_TIMING;
    this.emit('timing');

    this._updateInterval = setInterval(this.emit.bind(this, 'timing'),
      UPDATE_INTERVAL);
  };

  Timer.prototype.waiting = function() {
    this._assertState(Timer.STATE_NOT_RUNNING);
    this._state = Timer.STATE_WAITING;
    this.emit('waiting');
  };

  Timer.prototype._assertState = function(state) {
    if (this._state !== state) {
      throw new Error('invalid state: ' + state);
    }
  };

  Timer.prototype._assertStates = function(states) {
    if (states.indexOf(this._state) < 0) {
      throw new Error('invalid state: ' + state);
    }
  };

})();
<commit_msg>added generateSolve() method<commit_after>(function() {

  var INSPECTION_THRESHOLD = -2000;
  var UPDATE_INTERVAL = Math.floor(1000 / 24);
  var WCA_INSPECTION_TIME = 15000;

  function Timer() {
    window.app.EventEmitter.call(this);

    // Create the hidden class before calling this.reset().
    this._updateInterval = null;
    this._state = Timer.STATE_NOT_RUNNING;
    this._startTime = 0;
    this._deviceTime = 0;
    this._manualTime = 0;
    this._memoTime = -1;
    this._totalTime = 0;
    this._inspectionTime = 0;

    this.reset();
  }

  Timer.prototype = Object.create(window.app.EventEmitter.prototype);

  Timer.INPUT_REGULAR = 0;
  Timer.INPUT_INSPECTION = 1;
  Timer.INPUT_BLD = 2;
  Timer.INPUT_STACKMAT = 3;
  Timer.INPUT_ENTRY = 4;

  Timer.STATE_NOT_RUNNING = 0;
  Timer.STATE_MANUAL_ENTRY = 1;
  Timer.STATE_WAITING = 2;
  Timer.STATE_INSPECTION_READY = 3;
  Timer.STATE_INSPECTION = 4;
  Timer.STATE_READY = 5;
  Timer.STATE_TIMING = 6;
  Timer.STATE_TIMING_DONE_MEMO = 7;
  Timer.STATE_DEVICE_TIMING = 8;
  Timer.STATE_DONE = 9;

  Timer.prototype.deviceTiming = function(time) {
    this._assertStates([Timer.STATE_READY, Timer.STATE_DEVICE_TIMING]);
    this._state = Timer.STATE_DEVICE_TIMING;
    this._deviceTime = time;
    this.emit('deviceTiming');
  };

  Timer.prototype.done = function() {
    this._assertStates([Timer.STATE_TIMING, Timer.STATE_DEVICE_TIMING]);
    if (this._updateInterval) {
      clearInterval(this._updateInterval);
      this._updateInterval = null;
    }
    if (this._state === Timer.STATE_TIMING) {
      this._totalTime = this.getTime();
    } else {
      this._totalTime = this.getDeviceTime();
    }
  };

  Timer.prototype.doneMemo = function() {
    this._assertState(Timer.STATE_TIMER);
    this._state = STATE_TIMING_DONE_MEMO;
    this._memoTime = this.getTime();
    this.emit('doneMemo');
  };

  Timer.prototype.generateSolve = function() {
    // TODO: here, have an actual scramble.
    return {
      date: new Date().getTime(),
      dnf: false,
      inspection: this._inspectionTime,
      memo: this._memoTime,
      notes: '',
      plus2: false,
      time: this._totalTime,
      scramble: 'No scrambles yet'
    };
  };

  Timer.prototype.getDeviceTime = function() {
    return this._deviceTime;
  };

  Timer.prototype.getInspectionTime = function() {
    switch (this._state) {
    case Timer.STATE_INSPECTION:
      var elapsed = new Date().getTime() - this._startTime;
      return WCA_INSPECTION_TIME - elapsed;
    case Timer.STATE_DONE:
      return this._inspectionTime;
    default:
      return 0;
    }
  };

  Timer.prototype.getManualTime = function() {
    return this._manualTime;
  };

  Timer.prototype.getState = function() {
    return this._state;
  };

  Timer.prototype.getTime = function() {
    switch (this._state) {
    case Timer.STATE_TIMING:
    case Timer.STATE_TIMING_AFTER_MEMO:
      return new Date().getTime() - this._startTime;
    case Timer.STATE_DONE:
      return this._totalTime;
    default:
      return 0;
    }
  };

  Timer.prototype.inspection = function() {
    this._assertState(Timer.STATE_INSPECTION_READY);

    this._startTime = new Date().getTime();
    this._updateInterval = setInterval(function() {
      if (this.getInspectionTime() < INSPECTION_THRESHOLD) {
        this.timing();
      } else {
        this.emit('inspection');
      }
    }.bind(this), UPDATE_INTERVAL);

    this._state = Timer.STATE_INSPECTION;
    this.emit('inspection');
  };

  Timer.prototype.inspectionReady = function() {
    this._assertState(Timer.STATE_NOT_RUNNING);
    this._state = Timer.STATE_INSPECTION_READY;
    this.emit('inspectionReady');
  };

  Timer.prototype.manualTime = function(time) {
    this._assertState(Timer.STATE_MANUAL_ENTRY);
    this._manualTime = time;
    this.emit('manualTime');
  };

  Timer.prototype.ready = function() {
    this._assertStates([Timer.STATE_NOT_RUNNING, Timer.STATE_WAITING]);
    this._state = Timer.STATE_READY;
    this.emit('ready');
  };

  Timer.prototype.reset = function() {
    if (window.app.store.getActivePuzzle().timerInput === Timer.INPUT_ENTRY) {
      this._state = Timer.STATE_MANUAL_ENTRY;
    } else {
      this._state = Timer.STATE_NOT_RUNNING;
    }
    this._startTime = 0;
    this._deviceTime = 0;
    this._manualTime = 0;
    this._memoTime = -1;
    this._totalTime = 0;
    this._inspectionTime = 0;
    this.emit('reset');
  };

  Timer.prototype.timing = function() {
    this._assertStates([Timer.STATE_INSPECTION, Timer.STATE_READY]);

    if (this._updateInterval !== null) {
      clearInterval(this._updateInterval);
    }

    var now = new Date().getTime();

    if (this._state === Timer.STATE_INSPECTION) {
      this._inspectionTime = now - this._startTime;
    }

    this._startTime = now;
    this._state = Timer.STATE_TIMING;
    this.emit('timing');

    this._updateInterval = setInterval(this.emit.bind(this, 'timing'),
      UPDATE_INTERVAL);
  };

  Timer.prototype.waiting = function() {
    this._assertState(Timer.STATE_NOT_RUNNING);
    this._state = Timer.STATE_WAITING;
    this.emit('waiting');
  };

  Timer.prototype._assertState = function(state) {
    if (this._state !== state) {
      throw new Error('invalid state: ' + state);
    }
  };

  Timer.prototype._assertStates = function(states) {
    if (states.indexOf(this._state) < 0) {
      throw new Error('invalid state: ' + state);
    }
  };

})();
<|endoftext|>


<commit_before>'use strict';

import React, { Component } from 'react';
import classNames from 'classnames';
import Qs from 'qs';
import { result, find, template, clone } from 'lodash';
import BuildPicker from './BuildPicker';
import QrModal from './qr_modal';
import Switch from './Switch';

// Sample appetize URL
// https://appetize.io/embed/u702ejhe26p438rp73c74uyxur?device=iphone5s&scale=75&orientation=portrait&screenOnly=false&xdocMsg=true&autoapp=false&deviceColor=white&debug=true&params=%7B%22bundleUrl%22:%22http://rnplay-jsierles.ngrok.io/app_js/cUJ22A/index.ios.bundle%22,%22moduleName%22:%22SampleApp%22,%22RCTDevMenu%22:%7B%22liveReloadEnabled%22:true%7D,%22route%22:%22%22%7D

export default class Simulator extends Component {

  constructor(props) {
    super(props);
    this.state = {
      qrModalIsVisible: null
    };
  }

  appetizeUrlFor(platform) {

    var appetizeOptions = {
      embed: true,
      screenOnly: false,
      device: platform == 'ios' ? 'iphone5' : 'nexus5',
      launchUrl: `exp://rnplay.org/apps/${this.props.app.urlToken}`,
      xdocMsg: true,
      deviceColor: 'white',
      xDocMsg: true,
      orientation: 'portrait',
      debug: true
    }

    var bundlePath = platform == 'android' ? this.props.app.bundlePath : this.props.app.bundlePath+"/index.ios.bundle";
    var build = this.buildFor(platform, this.props.build.name);
    var appetizeId = build.appetize_id;

    var appParams = {
      moduleName: this.props.app.moduleName,
      packagerRoot: template(this.props.app.packagerRoot)({buildShortName: build.short_name}),
      bundleUrl: template(this.props.app.packagerUrlTemplate)({bundlePath: bundlePath, buildShortName: build.short_name}) + `?platform=${platform}`
    }

    if (platform == 'ios') {
      appParams["RCTDevMenu"] = { "liveReloadEnabled": true }
    } else {
      appParams['jsMainModuleName'] = `${bundlePath}/index.android`
    }

    var url = `https://appetize.io/embed/${appetizeId}?${Qs.stringify(appetizeOptions)}&params=${encodeURIComponent(JSON.stringify(appParams))}`
    return url;
  }

  showQRModal = (e) => {
    e.preventDefault();
    this.setState({qrModalIsVisible: true});
  }

  hideQRModal = (e) => {
    e.preventDefault();
    this.setState({qrModalIsVisible: false});
  }

  renderQRModal() {
    return (
      <QrModal urlToken={this.props.app.urlToken}
               onClickBackdrop={this.hideQRModal}
               isOpen={this.state.qrModalIsVisible} />
    )
  }

  renderQRLink = () => {
    return (

         Run on your device

    )
  }

  renderControls() {
    if (this.props.currentUserIsAdmin()) {
      return (

          Save screenshot
          Dev menu
           this.props.rotate('Left')}>Rotate left

      )
    }

    return null;
  }

  onSelectSupportedPlatform = (event) => {
    const { name, checked } = event.target;
    this.props.onSelectSupportedPlatform(name, checked);
    if (!checked) {
      this.props.onUpdateBuild(this.buildFor(name == 'ios' ? 'android' : 'ios', this.props.build.name).id);
    }
  }

  onSwitchPlatform = (name) => {
    this.props.onUpdateBuild(this.buildFor(name, this.props.build.name));
  }

  onUpdateBuild = (name) => {
    this.props.onUpdateBuild(this.buildFor(this.props.build.platform, name));
  }

  buildFor = (platform, version) => {
    return find(this.props.builds, (build) => {
      return build.platform == platform && build.name == version;
    });
  }

  renderSwitch() {
    if (this.props.ios && this.props.android) {
      return (
        <Switch
          onChange={this.onSwitchPlatform}
          defaultValue={this.props.build.platform}
          name="platform">
          iOS
          Android
        </Switch>
      )
    } else {
      return null;
    }
  }

  renderSupportedPlatforms() {
    if (!this.props.belongsToCurrentUser()) {
      return null;
    }

    return (

        Supported

          <input type="checkbox"
            defaultChecked={this.props.ios}
            onChange={this.onSelectSupportedPlatform}
            name="ios"
            id="ios"
            value="on"/>
          iOS

          <input type="checkbox"
            defaultChecked={this.props.android}
            onChange={this.onSelectSupportedPlatform}
            name="android"
            id="android"
            value="on" />
          Android

    );
  }
  render() {
    const {
      // useDarkTheme,
      builds,
      buildId
    } = this.props;

    const classesSimulator = classNames({
      'editor-simulator-container__simulator': true,
      // 'editor-simulator-container--dark': useDarkTheme,
    });

    const classesBuildPicker = classNames({
      'editor-simulator-container__settings--single': !this.props.belongsToCurrentUser()
    });

    return (

          {this.renderQRLink()}

        {this.renderControls()}

          {this.renderSupportedPlatforms()}

            Version
            <BuildPicker
              onChange={this.onUpdateBuild}
              builds={builds}
              selectedBuildName={this.props.build.name}
            />

        {this.renderSwitch()}

        {this.renderQRModal()}

    );
  }
}
<commit_msg>Pass in appetize params with the URL<commit_after>'use strict';

import React, { Component } from 'react';
import classNames from 'classnames';
import Qs from 'qs';
import { result, find, template, clone } from 'lodash';
import BuildPicker from './BuildPicker';
import QrModal from './qr_modal';
import Switch from './Switch';

// Sample appetize URL
// https://appetize.io/embed/u702ejhe26p438rp73c74uyxur?device=iphone5s&scale=75&orientation=portrait&screenOnly=false&xdocMsg=true&autoapp=false&deviceColor=white&debug=true&params=%7B%22bundleUrl%22:%22http://rnplay-jsierles.ngrok.io/app_js/cUJ22A/index.ios.bundle%22,%22moduleName%22:%22SampleApp%22,%22RCTDevMenu%22:%7B%22liveReloadEnabled%22:true%7D,%22route%22:%22%22%7D

export default class Simulator extends Component {

  constructor(props) {
    super(props);
    this.state = {
      qrModalIsVisible: null
    };
  }

  appetizeUrlFor(platform) {
    let manifestUrl = `rnplay://rnplay.org/apps/${this.props.app.urlToken}`;

    var appetizeOptions = {
      embed: true,
      screenOnly: false,
      device: platform == 'ios' ? 'iphone5' : 'nexus5',
      launchUrl: platform === 'android' ? manifestUrl : undefined,
      xdocMsg: true,
      deviceColor: 'white',
      xDocMsg: true,
      orientation: 'portrait',
      debug: true,
    }

    var build = this.buildFor(platform, this.props.build.name);
    var appetizeId = build.appetize_id;

    var appParams = {
      "EXKernelLaunchUrlDefaultsKey": manifestUrl,
    }

    var url = `https://appetize.io/embed/${appetizeId}?${Qs.stringify(appetizeOptions)}&params=${encodeURIComponent(JSON.stringify(appParams))}`
    return url;
  }

  showQRModal = (e) => {
    e.preventDefault();
    this.setState({qrModalIsVisible: true});
  }

  hideQRModal = (e) => {
    e.preventDefault();
    this.setState({qrModalIsVisible: false});
  }

  renderQRModal() {
    return (
      <QrModal urlToken={this.props.app.urlToken}
               onClickBackdrop={this.hideQRModal}
               isOpen={this.state.qrModalIsVisible} />
    )
  }

  renderQRLink = () => {
    return (

         Run on your device

    )
  }

  renderControls() {
    if (this.props.currentUserIsAdmin()) {
      return (

          Save screenshot
          Dev menu
           this.props.rotate('Left')}>Rotate left

      )
    }

    return null;
  }

  onSelectSupportedPlatform = (event) => {
    const { name, checked } = event.target;
    this.props.onSelectSupportedPlatform(name, checked);
    if (!checked) {
      this.props.onUpdateBuild(this.buildFor(name == 'ios' ? 'android' : 'ios', this.props.build.name).id);
    }
  }

  onSwitchPlatform = (name) => {
    this.props.onUpdateBuild(this.buildFor(name, this.props.build.name));
  }

  onUpdateBuild = (name) => {
    this.props.onUpdateBuild(this.buildFor(this.props.build.platform, name));
  }

  buildFor = (platform, version) => {
    return find(this.props.builds, (build) => {
      return build.platform == platform && build.name == version;
    });
  }

  renderSwitch() {
    if (this.props.ios && this.props.android) {
      return (
        <Switch
          onChange={this.onSwitchPlatform}
          defaultValue={this.props.build.platform}
          name="platform">
          iOS
          Android
        </Switch>
      )
    } else {
      return null;
    }
  }

  renderSupportedPlatforms() {
    if (!this.props.belongsToCurrentUser()) {
      return null;
    }

    return (

        Supported

          <input type="checkbox"
            defaultChecked={this.props.ios}
            onChange={this.onSelectSupportedPlatform}
            name="ios"
            id="ios"
            value="on"/>
          iOS

          <input type="checkbox"
            defaultChecked={this.props.android}
            onChange={this.onSelectSupportedPlatform}
            name="android"
            id="android"
            value="on" />
          Android

    );
  }
  render() {
    const {
      // useDarkTheme,
      builds,
      buildId
    } = this.props;

    const classesSimulator = classNames({
      'editor-simulator-container__simulator': true,
      // 'editor-simulator-container--dark': useDarkTheme,
    });

    const classesBuildPicker = classNames({
      'editor-simulator-container__settings--single': !this.props.belongsToCurrentUser()
    });

    return (

          {this.renderQRLink()}

        {this.renderControls()}

          {this.renderSupportedPlatforms()}

            Version
            <BuildPicker
              onChange={this.onUpdateBuild}
              builds={builds}
              selectedBuildName={this.props.build.name}
            />

        {this.renderSwitch()}

        {this.renderQRModal()}

    );
  }
}
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require select2
//= require hubstats/bootstrap
//= require bootstrap-datepicker
//= require_tree .

$(document).ready( function() {
  $('.input-daterange').datepicker({
    "todayHighlight": true,
    "endDate": "Today",
    "todayBtn": true
  });
  setDateRange();
});

function setDateRange() {
  var dates;
  var submitButton;
  var datesArray = [];
  var start_input;
  var end_input;

  var cookie = readCookie("hubstats_dates");

  if (cookie === null || cookie.indexOf("null") > -1) {
    dates = getDefaultDateRange();
  } else {
    dates = readCookie("hubstats_dates");
  }
  submitButton = document.getElementById("submitDateRange");
  datesArray = dates.split("~~");

  start_input = $('.input-daterange').find('[name="start"]');
  end_input = $('.input-daterange').find('[name="end"]');

  start_input.datepicker('update', new Date(datesArray[0]));
  end_input.datepicker('update', new Date(datesArray[1]));

  submitButton.onclick = function() {
    var start_date;
    var end_date;
    start_date = start_input.datepicker('getDate');
    end_date = end_input.datepicker('getDate');
    createCookie("hubstats_dates", start_date + "~~" + end_date, 1);
    window.location.reload();
  };
};

function createCookie(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else var expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
};

function readCookie(name) {
  var cookieName = name + "=";
  var cookieData = document.cookie.split(';');
  for(var i=0;i < cookieData.length;i++) {
    var c = cookieData[i];
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(cookieName) == 0) return c.substring(cookieName.length,c.length);
  }
  return null;
};

function eraseCookie(name) {
  createCookie(name,"",-1);
};

function getDefaultDateRange() {
  var today;
  var twoWeeksAgo;
  today = new Date();
  today.setHours(0,0,0,0);
  twoWeeksAgo = new Date(today);
  twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14);
  return twoWeeksAgo + '~~' + today;
};
<commit_msg>assigning variables and declaring in same line<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require select2
//= require hubstats/bootstrap
//= require bootstrap-datepicker
//= require_tree .

$(document).ready( function() {
  $('.input-daterange').datepicker({
    "todayHighlight": true,
    "endDate": "Today",
    "todayBtn": true
  });
  setDateRange();
});

function setDateRange() {
  var cookie = readCookie("hubstats_dates");

  if (cookie === null || cookie.indexOf("null") > -1) {
    var dates = getDefaultDateRange();
  } else {
    var dates = readCookie("hubstats_dates");
  }
  var submitButton = document.getElementById("submitDateRange");
  var datesArray = dates.split("~~");

  var start_input = $('.input-daterange').find('[name="start"]');
  var end_input = $('.input-daterange').find('[name="end"]');

  start_input.datepicker('update', new Date(datesArray[0]));
  end_input.datepicker('update', new Date(datesArray[1]));

  submitButton.onclick = function() {
    var start_date = start_input.datepicker('getDate');
    var end_date = end_input.datepicker('getDate');
    createCookie("hubstats_dates", start_date + "~~" + end_date, 1);
    window.location.reload();
  };
};

function createCookie(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else var expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
};

function readCookie(name) {
  var cookieName = name + "=";
  var cookieData = document.cookie.split(';');
  for(var i=0;i < cookieData.length;i++) {
    var c = cookieData[i];
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(cookieName) == 0) return c.substring(cookieName.length,c.length);
  }
  return null;
};

function eraseCookie(name) {
  createCookie(name,"",-1);
};

function getDefaultDateRange() {
  var today = new Date();
  today.setHours(0,0,0,0);
  var twoWeeksAgo = new Date(today);
  twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14);
  return twoWeeksAgo + '~~' + today;
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {
  // Load all Grunt tasks matching the `grunt-*` pattern
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Load Bower dependencies
  var dependencies = require('wiredep')();

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    watch: {
      bower: {
        files: ['bower.json']
      , tasks: ['bowerInstall']
      }
    , js: {
        files: ['js/src/**/*.js']
      , tasks: ['jshint', 'concat']
      }
    , gruntfile: {
        files: ['Gruntfile.js']
      }<% if (extension === 'less') { %>
    , less: {
        files: ['less/**/*.less']
      , tasks: ['less', 'autoprefixer', 'csslint']
      }<% } else if (extension === 'scss') { %>
    , sass: {
        files: ['scss/**/*.scss']
      , tasks: ['sass', 'autoprefixer', 'csslint']
      }<% } %>
    , livereload: {
        options: {
          livereload: true
        }
      , files: [
          'design/**/*.css'
        , 'design/images/**/*'
        , 'js/**/*.js'
        , 'views/**/*.tpl'
        ]
      }
    },<% if (extension === 'less') { %>

    less: {
      dist: {
        options: {
          strictMath: true
        , sourceMap: true
        , sourceMapURL: 'custom.css.map'
        , sourceMapFilename: 'design/custom.css.map'
        }
      , files: {
          'design/custom.css': '<%= extension %>/*.<%= extension %>'
        }
      }
    },<% } else if (extension === 'scss') { %>

    sass: {
      dist: {
        options: {
          sourceComments: 'map'
        }
      , files: {
          'design/custom.css': '<%= extension %>/*.<%= extension %>'
        }
      }
    },<% } %>

    autoprefixer: {
      dist: {
        src: ['design/**/*.css']
      }
    },

    jshint: {
      options: {
        jshintrc: 'js/.jshintrc'
      }
    , all: ['js/src/**/*.js']
    },

    csslint: {
      options: {
        csslintrc: 'design/.csslintrc'
      }
    , all: ['design/custom.css']
    },

    concat: {
      dist: {
        src: (dependencies.js || []).concat([
          'js/src/main.js'
        ])
      , dest: 'js/custom.js'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'design/images',
          src: '**/*.{gif,jpeg,jpg,png}',
          dest: 'design/images'
        }]
      }
    },

    bowerInstall: {
      dist: {
        src: ['<%= extension %>/**/*.<%= extension %>']
      }
    }

  });

  grunt.registerTask('default', [
    'bowerInstall'<% if (extension === 'less') { %>
  , 'less'<% } else if (extension === 'scss') { %>
  , 'sass'<% } %>
  , 'autoprefixer'
  , 'concat'
  , 'jshint'
  , 'csslint'
  , 'imagemin'
  ]);
};
<commit_msg>Fix stylesheet glob transpiling<commit_after>'use strict';

module.exports = function (grunt) {
  // Load all Grunt tasks matching the `grunt-*` pattern
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Load Bower dependencies
  var dependencies = require('wiredep')();

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    watch: {
      bower: {
        files: ['bower.json']
      , tasks: ['bowerInstall']
      }
    , js: {
        files: ['js/src/**/*.js']
      , tasks: ['jshint', 'concat']
      }
    , gruntfile: {
        files: ['Gruntfile.js']
      }<% if (extension === 'less') { %>
    , less: {
        files: ['less/**/*.less']
      , tasks: ['less', 'autoprefixer', 'csslint']
      }<% } else if (extension === 'scss') { %>
    , sass: {
        files: ['scss/**/*.scss']
      , tasks: ['sass', 'autoprefixer', 'csslint']
      }<% } %>
    , livereload: {
        options: {
          livereload: true
        }
      , files: [
          'design/**/*.css'
        , 'design/images/**/*'
        , 'js/**/*.js'
        , 'views/**/*.tpl'
        ]
      }
    },<% if (extension === 'less') { %>

    less: {
      dist: {
        options: {
          strictMath: true
        , sourceMap: true
        , sourceMapURL: 'custom.css.map'
        , sourceMapFilename: 'design/custom.css.map'
        }
      , files: [{
          expand: true
        , cwd: '<%= extension %>/'
        , src: ['*.<%= extension %>']
        , dest: 'design/'
        , ext: '.css'
       }]
      }
    },<% } else if (extension === 'scss') { %>

    sass: {
      dist: {
        options: {
          sourceComments: 'map'
        }
      , files: [{
          expand: true
        , cwd: '<%= extension %>/'
        , src: [
            '*.<%= extension %>'
          , '!_*.<%= extension %>'
          ]
        , dest: 'design/'
        , ext: '.css'
       }]
      }
    },<% } %>

    autoprefixer: {
      dist: {
        src: ['design/**/*.css']
      }
    },

    jshint: {
      options: {
        jshintrc: 'js/.jshintrc'
      }
    , all: ['js/src/**/*.js']
    },

    csslint: {
      options: {
        csslintrc: 'design/.csslintrc'
      }
    , all: ['design/custom.css']
    },

    concat: {
      dist: {
        src: (dependencies.js || []).concat([
          'js/src/main.js'
        ])
      , dest: 'js/custom.js'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'design/images',
          src: '**/*.{gif,jpeg,jpg,png}',
          dest: 'design/images'
        }]
      }
    },

    bowerInstall: {
      dist: {
        src: ['<%= extension %>/**/*.<%= extension %>']
      }
    }

  });

  grunt.registerTask('default', [
    'bowerInstall'<% if (extension === 'less') { %>
  , 'less'<% } else if (extension === 'scss') { %>
  , 'sass'<% } %>
  , 'autoprefixer'
  , 'concat'
  , 'jshint'
  , 'csslint'
  , 'imagemin'
  ]);
};
<|endoftext|>


<commit_before>(function () {
    registerAction(function (node) {
        if (!settings["replyLinks"] || !settings["withAvatars"]) return;
        if (node === undefined) {
            var styleEl = document.head.appendChild(document.createElement('style'));
            styleEl.type = 'text/css';
            styleEl.title = 'avatars';
            style = styleEl.sheet;
            console.log(styleEl, style)
        }
        node = node || document.body;

        toArray(node.querySelectorAll(".entry:not(.with-avatars)"))
            .forEach(function (node) { node.classList.add("with-avatars"); });

        toArray(node.querySelectorAll(".comments > .comment:not(.ffco-with-avatar) .quote"))
            .forEach(function (node) {
                var comment = node.parentNode;
                comment.classList.add("ffco-with-avatar");
                var login = comment.dataset["author"];
                if (login && !(login in avatars)) {
                    avatars[login] = true;
                    fetchAvatar(login);
                }
            });
    });

    var style = null,
        avatars = {};

    var fetchAvatar = function (login) {
        var a = document.querySelector("a[href='/" + login + "']");
        if (a) {
            var img = document.querySelector("img[src*='" + a.getAttribute("sid") + "']");
            if (img) {
                var url = img.src.replace(/-(\w+)-(\d+)$/, "-small-$2");
                style.insertRule(".comment-from-" + login + " > .quote { background-image: url(" + url + "); }", 0);
                return;
            }
        }
        var xhr = new XMLHttpRequest();
        xhr.open('GET', "http://friendfeed-api.com/v2/picture/" + login + "?size=small");
        xhr.responseType = "blob";
        xhr.onload = function () {
            if (this.status != 200) return;
            var url = URL.createObjectURL(this.response);
            style.insertRule(".comment-from-" + login + " > .quote { background-image: url(" + url + "); }", 0);
            setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
        };
        xhr.send();
    };
})();
<commit_msg>Не уничтожаем URL-ы аватарок<commit_after>(function () {
    registerAction(function (node) {
        if (!settings["replyLinks"] || !settings["withAvatars"]) return;
        if (node === undefined) {
            var styleEl = document.head.appendChild(document.createElement('style'));
            styleEl.type = 'text/css';
            styleEl.title = 'avatars';
            style = styleEl.sheet;
            console.log(styleEl, style)
        }
        node = node || document.body;

        toArray(node.querySelectorAll(".entry:not(.with-avatars)"))
            .forEach(function (node) { node.classList.add("with-avatars"); });

        toArray(node.querySelectorAll(".comments > .comment:not(.ffco-with-avatar) .quote"))
            .forEach(function (node) {
                var comment = node.parentNode;
                comment.classList.add("ffco-with-avatar");
                var login = comment.dataset["author"];
                if (login && !(login in avatars)) {
                    avatars[login] = true;
                    fetchAvatar(login);
                }
            });
    });

    var style = null,
        avatars = {};

    var fetchAvatar = function (login) {
        var a = document.querySelector("a[href='/" + login + "']");
        if (a) {
            var img = document.querySelector("img[src*='" + a.getAttribute("sid") + "']");
            if (img) {
                var url = img.src.replace(/-(\w+)-(\d+)$/, "-small-$2");
                style.insertRule(".comment-from-" + login + " > .quote { background-image: url(" + url + "); }", 0);
                return;
            }
        }
        var xhr = new XMLHttpRequest();
        xhr.open('GET', "http://friendfeed-api.com/v2/picture/" + login + "?size=small");
        xhr.responseType = "blob";
        xhr.onload = function () {
            if (this.status != 200) return;
            var url = URL.createObjectURL(this.response);
            style.insertRule(".comment-from-" + login + " > .quote { background-image: url(" + url + "); }", 0);
        };
        xhr.send();
    };
})();
<|endoftext|>


<commit_before>module.exports = {

    //---------------------------------------------------------------------
    // Action Name
    //
    // This is the name of the action displayed in the editor.
    //---------------------------------------------------------------------

    name: "File Control",

    //---------------------------------------------------------------------
    // Action Section
    //
    // This is the section the action will fall into.
    //---------------------------------------------------------------------

    section: "File Stuff",

    //---------------------------------------------------------------------
        // DBM Mods Manager Variables (Optional but nice to have!)
        //
        // These are variables that DBM Mods Manager uses to show information
        // about the mods for people to see in the list.
    //---------------------------------------------------------------------

        // Who made the mod (If not set, defaults to "DBM Mods")
        author: "Danno3187", //Original Idea by EliteArtz

        // The version of the mod (Defaults to 1.0.0)
        version: "1.8.7", //Added in 1.8.7

        // A short description to show on the mod line for this mod (Must be on a single line)
        short_description: "Allows a user to interact with 'Files'",

    //---------------------------------------------------------------------
        // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

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

    //---------------------------------------------------------------------
    // Action Subtitle
    //
    // This function generates the subtitle displayed next to the name.
    //---------------------------------------------------------------------

    subtitle: function(data) {
        const filetasks = ['Create', 'Write', 'Append', 'Delete'];
        return `${filetasks[parseInt(data.filetask)]} ${data.filename}${data.format}`;
    },

    //---------------------------------------------------------------------
    // Action Fields
    //
    // These are the fields for the action. These fields are customized
    // by creating elements with corresponding IDs in the HTML. These
    // are also the names of the fields stored in the action's JSON data.
    //---------------------------------------------------------------------

    fields: ["input", "format", "filename", "filepath", "filetask"],

    //---------------------------------------------------------------------
    // Command HTML
    //
    // This function returns a string containing the HTML used for
    // editting actions.
    //
    // The "isEvent" parameter will be true if this action is being used
    // for an event. Due to their nature, events lack certain information,
    // so edit the HTML to reflect this.
    //
    // The "data" parameter stores constants for select elements to use.
    // Each is an array: index 0 for commands, index 1 for events.
    // The names are: sendTargets, members, roles, channels,
    //                messages, servers, variables
    //---------------------------------------------------------------------

    html: function(isEvent, data) {
        return `

        Mod Info

        Made by Danno3817, EliteArtz & EGGSY

                File Format:

                <select id="format" class="round">
                <option value=".json">JSON</option>
                <option value=".txt">TXT</option>
                <option value=".js">JS</option>
                <option value=".log" selected>LOG</option>
                </select>

                File Task:

                <select id="filetask" class="round">
                <option value="0" selected>Create</option>
                <option value="1">Write</option>
                <option value="2">Append</option>
                <option value="3">Delete</option>
                </select>

                File Name:

                <textarea id="filename" placeholder="Insert File Name Here..." class="round" style="width 50%; resize: none; padding: 4px 0px;" type="textarea" rows="1" cols="25";></textarea>

                File Path:

                <textarea id="filepath" placeholder="Insert Path Here... Example Below" class="round" style="width99%; resize: none;" type="textarea" rows="1" cols="60"></textarea>

            Input Text:

            <textarea id="input" placeholder="Leave Blank For None." class="round" style="width: 99%; resize: 1;" type="textarea" rows="8" cols="35"></textarea>

Important info:

            If you want to delete something in current directory, you can add '.' (dot) before '/':

            e.g:

            My bot directory is: "/root/myBot/"

            I want to delete: "/root/myBot/delete.txt"

            Then I need to write "./delete.txt" in the field.

            Please be careful while using this mod. Don't forget there is no turning back after deleting the file.

`
    },

    //---------------------------------------------------------------------
    // Action Editor Init Code
    //
    // When the HTML is first applied to the action editor, this code
    // is also run. This helps add modifications or setup reactionary
    // functions for the DOM elements.
    //---------------------------------------------------------------------

    init: function() {},

    //---------------------------------------------------------------------
    // Action Bot Function
    //
    // This is the function for the action within the Bot's Action class.
    // Keep in mind event calls won't have access to the "msg" parameter,
    // so be sure to provide checks for variable existance.
    //---------------------------------------------------------------------

    action: function (cache) {
        const data = cache.actions[cache.index];

        const fileNAME = this.evalMessage(data.filename, cache);
        const filePATH = this.evalMessage(data.filepath, cache);
        const FullFile = filePATH + fileNAME + `${data.format}`;
        const fs = require('fs');

        const task = parseInt(data.filetask);

        const inputtext = this.evalMessage(data.input, cache);

        switch(task){
            case 0: //Create
            console.log("Create File Activated");
            try {
                if (filePATH && fileNAME){
                    fs.writeFileSync(FullFile,"");
                }else{
                console.log("File name or File path is missing.");
                }
            }catch (err){
            console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 1: //Write
            try{
                if (filePATH && fileNAME) {
                    fs.writeFileSync(FullFile, inputtext, console.log(`${data.filename}${data.format} File was written.`));
                } else {
                console.log(`File name or File path is missing.`);
                }
            } catch (err) {
                console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 2: //Append
            try {
                if (filePATH && fileNAME){
                    fs.appendFileSync(FullFile, inputtext + '\r\n' );
                }else{
                console.log("File name or File path is missing.");
                }
            }catch (err){
            console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 3: //Delete
            try {
                if (filePATH && fileNAME) {
                    fs.exists(`${FullFile}`, function(exists) {
                        if(exists) {
                            fs.unlink(FullFile, (err) => {
                                if (err) return console.log(`Something went wrong while deleting: [${err}]`);
                                console.log(`Sucessfully deleted [${FullFile}].`);
                              });
                        } else {
                            console.log('File not found, nothing to delete.');
                        }
                      });
                } else {
                console.log(`File path is missing.`);
                }
            } catch (err) {
                console.log("ERROR!" + err.stack ? err.stack : err);
            }
            this.callNextAction(cache);
            break;

        }
        this.callNextAction(cache);
    },

    //---------------------------------------------------------------------
    // Action Bot Mod
    //
    // Upon initialization of the bot, this code is run. Using the bot's
    // DBM namespace, one can add/modify existing functions if necessary.
    // In order to reduce conflictions between mods, be sure to alias
    // functions you wish to overwrite.
    //---------------------------------------------------------------------

    mod: function(DBM) {
    }

    }; // End of module
<commit_msg>Added better error log for File Control - Danno<commit_after>module.exports = {

    //---------------------------------------------------------------------
    // Action Name
    //
    // This is the name of the action displayed in the editor.
    //---------------------------------------------------------------------

    name: "File Control",

    //---------------------------------------------------------------------
    // Action Section
    //
    // This is the section the action will fall into.
    //---------------------------------------------------------------------

    section: "File Stuff",

    //---------------------------------------------------------------------
        // DBM Mods Manager Variables (Optional but nice to have!)
        //
        // These are variables that DBM Mods Manager uses to show information
        // about the mods for people to see in the list.
    //---------------------------------------------------------------------

        // Who made the mod (If not set, defaults to "DBM Mods")
        author: "Danno3187", //Original Idea by EliteArtz

        // The version of the mod (Defaults to 1.0.0)
        version: "1.8.7", //Added in 1.8.7

        // A short description to show on the mod line for this mod (Must be on a single line)
        short_description: "Allows a user to interact with 'Files'",

    //---------------------------------------------------------------------
        // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

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

    //---------------------------------------------------------------------
    // Action Subtitle
    //
    // This function generates the subtitle displayed next to the name.
    //---------------------------------------------------------------------

    subtitle: function(data) {
        const filetasks = ['Create', 'Write', 'Append', 'Delete'];
        return `${filetasks[parseInt(data.filetask)]} ${data.filename}${data.format}`;
    },

    //---------------------------------------------------------------------
    // Action Fields
    //
    // These are the fields for the action. These fields are customized
    // by creating elements with corresponding IDs in the HTML. These
    // are also the names of the fields stored in the action's JSON data.
    //---------------------------------------------------------------------

    fields: ["input", "format", "filename", "filepath", "filetask"],

    //---------------------------------------------------------------------
    // Command HTML
    //
    // This function returns a string containing the HTML used for
    // editting actions.
    //
    // The "isEvent" parameter will be true if this action is being used
    // for an event. Due to their nature, events lack certain information,
    // so edit the HTML to reflect this.
    //
    // The "data" parameter stores constants for select elements to use.
    // Each is an array: index 0 for commands, index 1 for events.
    // The names are: sendTargets, members, roles, channels,
    //                messages, servers, variables
    //---------------------------------------------------------------------

    html: function(isEvent, data) {
        return `

        Mod Info

        Made by Danno3817, EliteArtz & EGGSY

                File Format:

                <select id="format" class="round">
                <option value=".json">JSON</option>
                <option value=".txt">TXT</option>
                <option value=".js">JS</option>
                <option value=".log" selected>LOG</option>
                </select>

                File Task:

                <select id="filetask" class="round">
                <option value="0" selected>Create</option>
                <option value="1">Write</option>
                <option value="2">Append</option>
                <option value="3">Delete</option>
                </select>

                File Name:

                <textarea id="filename" placeholder="Insert File Name Here..." class="round" style="width 50%; resize: none; padding: 4px 0px;" type="textarea" rows="1" cols="25";></textarea>

                File Path:

                <textarea id="filepath" placeholder="Insert Path Here... Example Below" class="round" style="width99%; resize: none;" type="textarea" rows="1" cols="60"></textarea>

            Input Text:

            <textarea id="input" placeholder="Leave Blank For None." class="round" style="width: 99%; resize: 1;" type="textarea" rows="8" cols="35"></textarea>

Important info:

            You'll need a '/' at the end of the Path '\\\' for windows users.

            If you want to delete something in current directory, you can add '.' (dot) before '/':

            e.g:

            My bot directory is: "/root/myBot/"

            I want to delete: "/root/myBot/delete.txt"

            Then I need to write "./delete.txt" in the field.

            Please be careful while using this mod. Don't forget there is no turning back after deleting the file.

`
    },

    //---------------------------------------------------------------------
    // Action Editor Init Code
    //
    // When the HTML is first applied to the action editor, this code
    // is also run. This helps add modifications or setup reactionary
    // functions for the DOM elements.
    //---------------------------------------------------------------------

    init: function() {},

    //---------------------------------------------------------------------
    // Action Bot Function
    //
    // This is the function for the action within the Bot's Action class.
    // Keep in mind event calls won't have access to the "msg" parameter,
    // so be sure to provide checks for variable existance.
    //---------------------------------------------------------------------

    action: function (cache) {
        const data = cache.actions[cache.index];

        const fileNAME = this.evalMessage(data.filename, cache);
        const filePATH = this.evalMessage(data.filepath, cache);
        const FullFile = filePATH + fileNAME + `${data.format}`;
        const fs = require('fs');

        const task = parseInt(data.filetask);

        const inputtext = this.evalMessage(data.input, cache);

        switch(task){
            case 0: //Create
            console.log("Create File Activated");
            try {
                if (filePATH){
                    if (fileNAME) {
                        fs.writeFileSync(FullFile,"");
                    }else {
                        console.log("File name is missing.");
                    }
                }else{
                console.log("File path is missing.");
                }
            }catch (err){
                console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 1: //Write
            try{
                if (filePATH){
                    if (fileNAME) {
                        fs.writeFileSync(FullFile, inputtext);
                    }else {
                        console.log("File name is missing.");
                    }
                }else{
                console.log("File path is missing.");
                }
            } catch (err) {
                console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 2: //Append
            try {
                if (filePATH && fileNAME){
                    fs.appendFileSync(FullFile, inputtext + '\r\n' );
                }else{
                console.log("File name or File path is missing.");
                }
            }catch (err){
                console.log("ERROR!" + err.stack ? err.stack : err);
            }this.callNextAction(cache);
            break;

            case 3: //Delete
            try {
                if (filePATH) {
                    fs.exists(`${FullFile}`, function(exists) {
                        if(exists) {
                            fs.unlink(FullFile, (err) => {
                                if (err) return console.log(`Something went wrong while deleting: [${err}]`);
                              });
                        } else {
                            console.log('File not found, nothing to delete.');
                        }
                      });
                } else {
                console.log(`File path is missing.`);
                }
            } catch (err) {
                console.log("ERROR!" + err.stack ? err.stack : err);
            }
            this.callNextAction(cache);
            break;

        }
        this.callNextAction(cache);
    },

    //---------------------------------------------------------------------
    // Action Bot Mod
    //
    // Upon initialization of the bot, this code is run. Using the bot's
    // DBM namespace, one can add/modify existing functions if necessary.
    // In order to reduce conflictions between mods, be sure to alias
    // functions you wish to overwrite.
    //---------------------------------------------------------------------

    mod: function(DBM) {
    }

    }; // End of module
<|endoftext|>


<commit_before>// manages behavior of popups
define(['util'],function(util) {
  'use strict';

		// PRIVATE PROPERTIES
		var popups; // array of popups on the page
		var lastPopup; // the last popup to be shown
		var lastTrigger;

		// PUBLIC METHODS
		function init()
		{
			popups = document.querySelectorAll(".popup-trigger");

			var curr;
			for (var p=0; p < popups.length; p++)
			{
				curr = popups[p];
				curr.addEventListener("click", _popupHandler, false);
				curr.classList.add('active');
			}
		}

		// PRIVATE METHODS
		function _popupHandler(evt)
		{
			evt.preventDefault();

			var trigger = evt.target;
			var thisPopup = document.querySelector( trigger.hash );

			_show(thisPopup,trigger);

			window.addEventListener("resize", _resizeHandler, true);

			return false;
		}

		function _resizeHandler(evt)
		{
			_show(lastPopup,lastTrigger);
		}

		function _show(popup,trigger)
		{
			lastTrigger = trigger;

			var container = popup.parentNode;
			var arrow = container.children[0];

			// get the window dimensions
			var winDim = util.getWindowRect();

			var offset = util.getOffset(trigger);
			var offsetY = (offset.top+trigger.offsetHeight);
			var offsetX = (offset.left);

			arrow.style.top = (offsetY)+"px";
			arrow.style.left = (offsetX-10+(trigger.offsetWidth/2))+"px";

			popup.style.top = (offsetY+10)+"px";

			var cssWidth = util.getStyle(popup,"width");
			if ( (offsetX+Number(cssWidth.substring(0,cssWidth.length-2))) > winDim.width)
			{
				popup.style.right = "10px";
			}
			else
			{
				popup.style.left = (offsetX)+"px";
			}

			if (lastPopup && lastPopup != popup) lastPopup.parentNode.classList.add("hide");
			lastPopup = popup;
			lastPopup.parentNode.classList.toggle("hide");

			// set height to default in order to check against window height effectively
			popup.style.height = "auto";
			if (offsetY+popup.offsetHeight > winDim.height)
			{
				popup.style.height = (winDim.height-offsetY-20)+"px";
			}
			else
			{
				popup.style.height = "auto";
			}

			popup.style.zIndex = "9999";
			arrow.style.zIndex = "10000";

			// attach to content element, as document directly doesn't work correctly on Mobile Safari
			document.getElementById("content").addEventListener("mousedown", _closeHandler, true);
		}

		function _closeHandler(evt)
		{
			if (evt.target.attributes["href"] == undefined &&
				!evt.target.classList.contains("popup-trigger") &&
				!evt.target.parentNode.classList.contains("popup-container"))
			{
				lastPopup.parentNode.classList.add("hide");
				document.getElementById("content").removeEventListener("mousedown", _closeHandler, true);
			}
		}

	return {
		init:init
	};
});<commit_msg>Fixes popup resizing error<commit_after>// manages behavior of popups
define(['util'],function(util) {
  'use strict';

		// PRIVATE PROPERTIES
		var popups; // array of popups on the page
		var lastPopup; // the last popup to be shown
		var lastTrigger;

		// PUBLIC METHODS
		function init()
		{
			popups = document.querySelectorAll(".popup-trigger");

			var curr;
			for (var p=0; p < popups.length; p++)
			{
				curr = popups[p];
				curr.addEventListener("click", _popupHandler, false);
				curr.classList.add('active');
			}
		}

		// PRIVATE METHODS
		function _popupHandler(evt)
		{
			evt.preventDefault();

			var trigger = evt.target;
			var thisPopup = document.querySelector( trigger.hash );

			_show(thisPopup,trigger);

			window.addEventListener("resize", _resizeHandler, true);

			return false;
		}

		function _resizeHandler(evt)
		{
			_show(lastPopup,lastTrigger);
		}

		function _show(popup,trigger)
		{
			lastTrigger = trigger;

			var container = popup.parentNode;
			var arrow = container.children[0];

			// get the window dimensions
			var winDim = util.getWindowRect();

			var offset = util.getOffset(trigger);
			var offsetY = (offset.top+trigger.offsetHeight);
			var offsetX = (offset.left);

			arrow.style.top = (offsetY)+"px";
			arrow.style.left = (offsetX-10+(trigger.offsetWidth/2))+"px";

			popup.style.top = (offsetY+10)+"px";

			var cssWidth = util.getStyle(popup,"width");
			if ( (offsetX+Number(cssWidth.substring(0,cssWidth.length-2))) > winDim.width)
			{
				popup.style.right = "10px";
			}
			else
			{
				popup.style.left = (offsetX)+"px";
			}

			if (lastPopup && lastPopup != popup) lastPopup.parentNode.classList.add("hide");
			lastPopup = popup;
			lastPopup.parentNode.classList.toggle("hide");

			// set height to default in order to check against window height effectively
			popup.style.height = "auto";
			var padding = 20;
			if ( (offsetY+popup.offsetHeight+padding) > winDim.height)
			{
				popup.style.height = (winDim.height-offsetY-padding)+"px";
			}
			else
			{
				popup.style.height = "auto";
			}

			popup.style.zIndex = "9999";
			arrow.style.zIndex = "10000";

			// attach to content element, as document directly doesn't work correctly on Mobile Safari
			document.getElementById("content").addEventListener("mousedown", _closeHandler, true);
		}

		function _closeHandler(evt)
		{
			if (evt.target.attributes["href"] == undefined &&
				!evt.target.classList.contains("popup-trigger") &&
				!evt.target.parentNode.classList.contains("popup-container"))
			{
				lastPopup.parentNode.classList.add("hide");
				document.getElementById("content").removeEventListener("mousedown", _closeHandler, true);
			}
		}

	return {
		init:init
	};
});<|endoftext|>