<commit_before>$(function () {
  $('.has-chevron').on('click', rotateChevron)

  $('input[type=radio][name=tokenType]').click(updateTokenizeCheckbox)

  updateTokenizeCheckbox()

  $('input[type=radio][name=normalizeType]').click(updateNorm)

  updateNorm()

  $('input[type=checkbox][name=mfwcheckbox]').click(updateMFWinput)

  updateMFWinput()

  $('input[type=checkbox][name=cullcheckbox]').click(updatecullinput)

  updatecullinput()

  $(window).scroll(changeSubmitDivPosition())

  $(window).scroll() // Call a dummy scroll event after everything is loaded.
})

/**
 * Update tokenize checkbox for selecting documents
 */
function updateTokenizeCheckbox () {
  if ($('#tokenByWords').is(':checked')) {
    $('#inWordsOnly').hide()
  } else {
    $('#inWordsOnly').show()
  }
}

/**
 *
 */
function updateNorm () {
  if ($('#normalizeTypeRaw').is(':checked') || $('#normalizeTypeFreq').is(':checked')) {
    $('#tfidfspan').hide()
  } else {
    $('#tfidfspan').show()
  }
}

function updateMFWinput () {
  if ($('#MFW').is(':checked')) {
    $('span[id=mfwnumber-input]').show()
    if ($('#culling').is(':checked')) {
      $('#temp-label-div').css('max-height', '221px')
      $('#modifylabels').css('max-height', '160px')
    } else {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    }
  } else {
    if ($('#culling').is(':checked')) {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    } else {
      $('#temp-label-div').css('max-height', '161px')
      $('#modifylabels').css('max-height', '100px')
    }
    $('span[id=mfwnumber-input]').hide()
  }
}

function updatecullinput () {
  if ($('#culling').is(':checked')) {
    $('span[id=cullnumber-input]').show()
    if ($('#MFW').is(':checked')) {
      $('#temp-label-div').css('max-height', '221px')
      $('#modifylabels').css('max-height', '160px')
    } else {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    }
  } else {
    if ($('#MFW').is(':checked')) {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    } else {
      $('#temp-label-div').css('max-height', '161px')
      $('#modifylabels').css('max-height', '100px')
    }
    $('span[id=cullnumber-input]').hide()
  }
}

function rotateChevron () {
  $(this).find('span').toggleClass('down')

  // Nasty hack because find("span") does not work in kmeans
  $(this).find('#kmeansAdvancedChev').toggleClass('down')
  $(this).find('#kmeansSilhouetteChev').toggleClass('down')
  $(this).find('#cullingOptsChev').toggleClass('down')

  $(this).next().collapse('toggle')
}

function changeSubmitDivPosition () {
  // Change position of submit div while scrolling the window
  let timer
  // Timer stuff
  if (timer) {
    clearTimeout(timer)
  }
  // Timer to throttle the scroll event so it doesn't happen too often
  timer = setTimeout(throttleScrollTimer(), 10)
}

function throttleScrollTimer () {
  let buttonsFixed = false
  let buttons = $('#analyze-submit')
  let scrollBottom = $(window).scrollTop() + $(window).height()

  // if bottom of scroll window at the footer, allow buttons to rejoin page as it goes by
  if ((buttonsFixed && (scrollBottom >= ($('footer').offset().top)))) {
    // console.log("Scroll bottom hit footer! On the way down");
    buttons.removeClass('fixed')
    buttonsFixed = false
  }

  // if bottom of scroll window at the footer, fix button to the screen
  if (!buttonsFixed && (scrollBottom < ($('footer').offset().top))) {
    // console.log("Scroll bottom hit footer! On the way up");
    buttons.addClass('fixed')
    buttonsFixed = true
  }
}
<commit_msg>added documentation to functions<commit_after>$(function () {
  $('.has-chevron').on('click', rotateChevron)

  $('input[type=radio][name=tokenType]').click(updateTokenizeCheckbox)

  updateTokenizeCheckbox()

  $('input[type=radio][name=normalizeType]').click(updateNorm)

  updateNorm()

  $('input[type=checkbox][name=mfwcheckbox]').click(updateMFWinput)

  updateMFWinput()

  $('input[type=checkbox][name=cullcheckbox]').click(updatecullinput)

  updatecullinput()

  $(window).scroll(changeSubmitDivPosition())

  $(window).scroll() // Call a dummy scroll event after everything is loaded.
})

/**
 * Update tokenize checkbox for selecting documents
 * @returns {void}
 */
function updateTokenizeCheckbox () {
  if ($('#tokenByWords').is(':checked')) {
    $('#inWordsOnly').hide()
  } else {
    $('#inWordsOnly').show()
  }
}

/**
 * Show the options for weighted counts normalization if selected and hide
 * these options when another normalization technique is selected
 * @returns {void}
 */
function updateNorm () {
  if ($('#normalizeTypeRaw').is(':checked') || $('#normalizeTypeFreq').is(':checked')) {
    $('#tfidfspan').hide()
  } else {
    $('#tfidfspan').show()
  }
}

/**
 * Change CSS to make room for most frequent words number input when most
 * frequent words is checked
 * @returns {void}
 */
function updateMFWinput () {
  // If most frequent words is checked
  if ($('#MFW').is(':checked')) {
    // Show top number of words input
    $('span[id=mfwnumber-input]').show()
    // If culling is checked
    if ($('#culling').is(':checked')) {
      // Change CSS to make room
      $('#temp-label-div').css('max-height', '221px')
      $('#modifylabels').css('max-height', '160px')
    } else {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    }
  } else {
    if ($('#culling').is(':checked')) {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    } else {
      $('#temp-label-div').css('max-height', '161px')
      $('#modifylabels').css('max-height', '100px')
    }
    // Hide most frequent words input if MFW is not checked
    $('span[id=mfwnumber-input]').hide()
  }
}

/**
 * Change CSS to make room for must be in x documents number input when culling
 * is checked
 * @returns {void}
 */
function updatecullinput () {
  // If culling is checked
  if ($('#culling').is(':checked')) {
    // Show documents number input
    $('span[id=cullnumber-input]').show()
    // If most frequent words is checked
    if ($('#MFW').is(':checked')) {
      // Change CSS to make room
      $('#temp-label-div').css('max-height', '221px')
      $('#modifylabels').css('max-height', '160px')
    } else {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    }
  } else {
    if ($('#MFW').is(':checked')) {
      $('#temp-label-div').css('max-height', '191px')
      $('#modifylabels').css('max-height', '130px')
    } else {
      $('#temp-label-div').css('max-height', '161px')
      $('#modifylabels').css('max-height', '100px')
    }
    // Hide culling input if culling is not checked
    $('span[id=cullnumber-input]').hide()
  }
}

/**
 * Toggle chevron class in order to handle chevron drop down button rotate
 * animation
 * @returns {void}
 */
function rotateChevron () {
  $(this).find('span').toggleClass('down')

  // Nasty hack because find("span") does not work in kmeans
  $(this).find('#kmeansAdvancedChev').toggleClass('down')
  $(this).find('#kmeansSilhouetteChev').toggleClass('down')
  $(this).find('#cullingOptsChev').toggleClass('down')

  $(this).next().collapse('toggle')
}

/**
 * Change position of submit div while scrolling the window
 * Unnecessary function?
 * @returns {void}
 */
function changeSubmitDivPosition () {
  let timer
  // Timer stuff
  if (timer) {
    clearTimeout(timer)
  }
  // Timer to throttle the scroll event so it doesn't happen too often
  timer = setTimeout(throttleScrollTimer(), 10)
}

/**
 * Throttle the scroll event so it doesn't happen too often
 * Unnecessary function?
 * @returns {void}
 */
function throttleScrollTimer () {
  let buttonsFixed = false
  let buttons = $('#analyze-submit')
  let scrollBottom = $(window).scrollTop() + $(window).height()

  // if bottom of scroll window at the footer, allow buttons to rejoin page as it goes by
  if ((buttonsFixed && (scrollBottom >= ($('footer').offset().top)))) {
    // console.log("Scroll bottom hit footer! On the way down");
    buttons.removeClass('fixed')
    buttonsFixed = false
  }

  // if bottom of scroll window at the footer, fix button to the screen
  if (!buttonsFixed && (scrollBottom < ($('footer').offset().top))) {
    // console.log("Scroll bottom hit footer! On the way up");
    buttons.addClass('fixed')
    buttonsFixed = true
  }
}
<|endoftext|>


<commit_before>exports.config = {
  allScriptsTimeout: 11000,

  specs: [
    'e2e/*.js'
  ],

  capabilities: {
    'browserName': 'chrome'
  },

  baseUrl: 'http://localhost:8000/app/',

  framework: 'jasmine',

  jasmineNodeOpts: {
    defaultTimeoutInterval: 30000
  }
};
<commit_msg>edited protractor test<commit_after>exports.config = {
  allScriptsTimeout: 11000,

  specs: [
    'e2e/*.js'
  ],

  capabilities: {
    'browserName': 'chrome'
  },

  baseUrl: 'http://localhost/app/',

  framework: 'jasmine',

  jasmineNodeOpts: {
    defaultTimeoutInterval: 30000
  }
};
<|endoftext|>


<commit_before>'use strict';

module.exports = defineRules;

var bubbleJobTitles = [
    'guru', 'gurus',
    'ninja', 'ninjas',
    'rock star', 'rockstars', 'rock stars', 'rockstar',
    'superstar', 'superstars'
];

var temptations = [
    'beer', 'beers', 'brewski', 'brewskis', 'pint', 'pints', 'happy hour', 'happy-hour', 'keg', 'kegs', 'kegerator', 'kegerators',
    'nerf gun', 'nerf guns',
    'ping pong', 'pingpong',
    'pizza', 'pizzas',
    'pool table', 'pool', 'pooltable',
    'table tennis', 'tabletennis',
    'table football', 'foosball'
];

function defineRules (linter) {

    // Job title fails
    linter.addRule(function (spec, result) {
        var bubbleJobMentions = spec.containsAnyOfPhrases(bubbleJobTitles);
        if (bubbleJobMentions.length > 0) {
            result.addWarning('Tech people are not ninjas, rock stars, gurus or superstars');
            result.addCultureFailPoints(bubbleJobMentions.length / 2);
            result.addRealismFailPoints(1);
        }
    });

    // Temptations
    linter.addRule(function (spec, result) {
        var temptationMentions = spec.containsAnyOfPhrases(temptations);
        if (temptationMentions.length > 0) {
            result.addWarning(
                'Attempt to attract candidates with hollow benefits: ' +
                temptationMentions.join(', ')
            );
            result.addCultureFailPoints(1);
            result.addRecruiterFailPoints(temptationMentions.length / 2);
        }
    });

}
<commit_msg>add more temptations<commit_after>'use strict';

module.exports = defineRules;

var bubbleJobTitles = [
    'guru', 'gurus',
    'ninja', 'ninjas',
    'rock star', 'rockstars', 'rock stars', 'rockstar',
    'superstar', 'superstars'
];

var temptations = [
    'beer', 'beers', 'brewski', 'brewskis', 'pint', 'pints', 'happy hour', 'happy-hour', 'keg', 'kegs', 'kegerator', 'kegerators',
    'nerf gun', 'nerf guns',
    'ping pong', 'pingpong',
    'pizza', 'pizzas',
    'pool table', 'pool', 'pooltable',
    'table tennis', 'tabletennis',
    'table football', 'foosball',
    'fifa', 'xbox', 'rock wall'
];

function defineRules (linter) {

    // Job title fails
    linter.addRule(function (spec, result) {
        var bubbleJobMentions = spec.containsAnyOfPhrases(bubbleJobTitles);
        if (bubbleJobMentions.length > 0) {
            result.addWarning('Tech people are not ninjas, rock stars, gurus or superstars');
            result.addCultureFailPoints(bubbleJobMentions.length / 2);
            result.addRealismFailPoints(1);
        }
    });

    // Temptations
    linter.addRule(function (spec, result) {
        var temptationMentions = spec.containsAnyOfPhrases(temptations);
        if (temptationMentions.length > 0) {
            result.addWarning(
                'Attempt to attract candidates with hollow benefits: ' +
                temptationMentions.join(', ')
            );
            result.addCultureFailPoints(1);
            result.addRecruiterFailPoints(temptationMentions.length / 2);
        }
    });

}
<|endoftext|>


<commit_before>'use strict';

exports.config = (function() {

    var env,
        profile;

    env = process.env;
    profile = env.PROTRACTOR_PROFILE;

    console.log('protractor profile: ' + profile);

    // function makeMultiCapabilities(base, caps) {
    //
    // }

    var extra;
    // See the following for documentation of the possible browserName,
    // version, and platform values:
    // https://code.google.com/p/selenium/wiki/DesiredCapabilities
    switch (profile) {
        case undefined:
            extra = {
                multiCapabilities: [{
                    browserName: 'chrome'
                }, {
                    browserName: 'firefox'
                }]
            };
            break;
        case 'chrome':
            extra = {
                capabilities: {
                    browserName: 'chrome'
                },
                chromeOnly: true
            };
            break;
        case 'phantomjs':
            extra = {
                capabilities: {
                   browserName: 'phantomjs',
                   'phantomjs.binary.path': './node_modules/karma-phantomjs-launcher/node_modules/phantomjs/bin/phantomjs'
                }
            };
            break;
        case 'travis':
            // Travis has Firefox installed.  The GUI emulator xvfb
            // (X Virtual Framebuffer) needs to be started prior to running
            // Protractor.
            extra = {
                capabilities: {
                    browserName: 'firefox'
                }
            };
            break;
        case 'travis-phantom':
            // Travis has phantomjs on the PATH.
            extra = {
                capabilities: {
                    browserName: 'phantomjs'
                }
            };
            break;
        case 'travis-sauce':
            extra = {
                sauceUser: env.SAUCE_USERNAME,
                sauceKey: env.SAUCE_ACCESS_KEY,
                capabilities: {
                    'tunnel-identifier': env.TRAVIS_JOB_NUMBER,
                    build: env.TRAVIS_BUILD_NUMBER,
                    platform: 'Windows 8',
                    browserName: 'internet explorer',
                    version: '10'
                }
            };
            break;
        default:
            throw 'invalid protractor profile: ' + profile;
    }

    var config = {
      allScriptsTimeout: 11000,

      specs: [
        'e2e/*.js'
      ],

      baseUrl: 'http://localhost:9000/',

      framework: 'jasmine',

      jasmineNodeOpts: {
        defaultTimeoutInterval: 30000
      }
    };

    for (var key in extra) {
        config[key] = extra[key];
    }

    return config;
}());
<commit_msg>Prep for adding multiple sauce browsers.<commit_after>'use strict';

exports.config = (function() {

    var env,
        profile;

    env = process.env;
    profile = env.PROTRACTOR_PROFILE;

    console.log('protractor profile: ' + profile);

    // Naive implementation of angular.extend():
    // https://docs.angularjs.org/api/ng/function/angular.extend
    function extend(dst, src) {
        for (var key in src) {
            dst[key] = src[key];
        }
        return dst;
    }

    function makeMultiCapabilities(base, caps) {
        var newCap,
            multiCaps = [];
        for (var i = 0, len = caps.length; i < len; i++) {
            newCap = extend({}, base);
            extend(newCap, caps[i]);
            multiCaps.push(newCap);
        }
        return multiCaps;
    }

    var extra;
    // See the following for documentation of the possible browserName,
    // version, and platform values:
    // https://code.google.com/p/selenium/wiki/DesiredCapabilities
    switch (profile) {
        case undefined:
            extra = {
                multiCapabilities: [{
                    browserName: 'chrome'
                }, {
                    browserName: 'firefox'
                }]
            };
            break;
        case 'chrome':
            extra = {
                capabilities: {
                    browserName: 'chrome'
                },
                chromeOnly: true
            };
            break;
        case 'phantomjs':
            extra = {
                capabilities: {
                   browserName: 'phantomjs',
                   'phantomjs.binary.path': './node_modules/karma-phantomjs-launcher/node_modules/phantomjs/bin/phantomjs'
                }
            };
            break;
        case 'travis':
            // Travis has Firefox installed.  The GUI emulator xvfb
            // (X Virtual Framebuffer) needs to be started prior to running
            // Protractor.
            extra = {
                capabilities: {
                    browserName: 'firefox'
                }
            };
            break;
        case 'travis-phantom':
            // Travis has phantomjs on the PATH.
            extra = {
                capabilities: {
                    browserName: 'phantomjs'
                }
            };
            break;
        case 'travis-sauce':
            var baseCaps = {
                'tunnel-identifier': env.TRAVIS_JOB_NUMBER,
                build: env.TRAVIS_BUILD_NUMBER
            };
            var multiCaps = makeMultiCapabilities(baseCaps, [{
                platform: 'Windows 8',
                browserName: 'internet explorer',
                version: '10'
            }]);
            extra = {
                sauceUser: env.SAUCE_USERNAME,
                sauceKey: env.SAUCE_ACCESS_KEY,
                multiCapabilities: multiCaps
            };
            break;
        default:
            throw 'invalid protractor profile: ' + profile;
    }

    var config = {
      allScriptsTimeout: 11000,

      specs: [
        'e2e/*.js'
      ],

      baseUrl: 'http://localhost:9000/',

      framework: 'jasmine',

      jasmineNodeOpts: {
        defaultTimeoutInterval: 30000
      }
    };

    extend(config, extra);

    return config;
}());
<|endoftext|>


<commit_before>describe('Creating a session',function() {

	var session_name;

	it('should add a new session and show on the list of my sessions', function() {
		// Add a session in main browser
		session_name = "Demo" + Date.now();
		element(by.id('new_session_name')).click();
		element(by.id('new_session_name')).sendKeys(session_name);
		element(by.id('add_session')).click();
		console.log("Adding session...");

		// Check that it appears in the list of sessions
		var session_link = element(by.linkText(session_name));
		expect(session_link).not.toBe(null);
		console.log("...success");

	});

	it('should not appear on another users list of sessions', function() {
		browser2.get('http://localhost:4072/');
		var session_link = element2(by.linkText(session_name));
		expect(session_link).not.toBe(null);
	});
});

describe('Loading of a session with existing cards', function() {

	var session_name;
	var session_url;

	beforeAll(function() {
		browser.get('http://localhost:4072/');

		// Create a session
		session_name = "Demo" + Date.now();
		element(by.id('new_session_name')).sendKeys(session_name);
		element(by.id('add_session')).click();

		// Go to that session
		var session_link = element(by.linkText(session_name));
		session_link.getAttribute('href').then(function(attr) {
			session_url = attr;
		});

		browser.actions().mouseMove(session_link).click().perform();
	});

	it('should show the session name in the first browser',function() {
		expect(element(by.id('session_name')).getText()).toEqual(session_name);
	});

	it('should add a question card in the first browser',function() {
		element(by.id("question")).click();
		var cards = element.all(by.repeater('card in session.cards'));
		expect(cards.count()).toEqual(1);
	});

	//TODO: Should these tests have their own set up?
	it('should load the session in the second browser',function() {
		browser2.get(session_url);

		// Check the correct number of cards have appeared
		var cards = element2.all(by.repeater('card in session.cards'));
		expect(cards.count()).toEqual(1);

		// Check we're on the session by reading the <h1> tag
		expect(element(by.id('session_name')).getText()).toEqual(session_name);
	});
});
<commit_msg>Added logging<commit_after>describe('Creating a session',function() {

	var session_name;

	it('should add a new session and show on the list of my sessions', function() {
		// Add a session in main browser
		console.log("Populating new session name");
		session_name = "Demo" + Date.now();
		element(by.id('new_session_name')).click();
		element(by.id('new_session_name')).sendKeys(session_name);
		element(by.id('add_session')).click();
		console.log("Adding session...");

		// Check that it appears in the list of sessions
		var session_link = element(by.linkText(session_name));
		expect(session_link).not.toBe(null);
		console.log("...success");

	});

	it('should not appear on another users list of sessions', function() {
		browser2.get('http://localhost:4072/');
		var session_link = element2(by.linkText(session_name));
		expect(session_link).not.toBe(null);
	});
});

describe('Loading of a session with existing cards', function() {

	var session_name;
	var session_url;

	beforeAll(function() {
		browser.get('http://localhost:4072/');

		// Create a session
		session_name = "Demo" + Date.now();
		element(by.id('new_session_name')).sendKeys(session_name);
		element(by.id('add_session')).click();

		// Go to that session
		var session_link = element(by.linkText(session_name));
		session_link.getAttribute('href').then(function(attr) {
			session_url = attr;
		});

		browser.actions().mouseMove(session_link).click().perform();
	});

	it('should show the session name in the first browser',function() {
		expect(element(by.id('session_name')).getText()).toEqual(session_name);
	});

	it('should add a question card in the first browser',function() {
		element(by.id("question")).click();
		var cards = element.all(by.repeater('card in session.cards'));
		expect(cards.count()).toEqual(1);
	});

	//TODO: Should these tests have their own set up?
	it('should load the session in the second browser',function() {
		browser2.get(session_url);

		// Check the correct number of cards have appeared
		var cards = element2.all(by.repeater('card in session.cards'));
		expect(cards.count()).toEqual(1);

		// Check we're on the session by reading the <h1> tag
		expect(element(by.id('session_name')).getText()).toEqual(session_name);
	});
});
<|endoftext|>


<commit_before>describe('rules.href_type', function () {
    var rule = require('../lib/rules/href_type'),
		htmllint = require('../'),
        Parser = require('../lib/parser'),
		parser = null;

    describe('process', function () {
        var Parser = require('../lib/parser'),
            parser = null;

        it('should return an array', function () {
            var output = rule.process([]);

            expect(output).to.be.an.instanceOf(Array);
        });
        //this code is for if the flag is set to absolute
        it('should not match absolute links given absolute option', function () {

            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'absolute'});

            expect(output).to.have.length(0);
        });

        it('should match relative links given absolute option', function () {
            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'absolute'});

            expect(output).to.have.length(1);
        });

        it('should not match relative links given relative option', function () {

            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'relative'});

            expect(output).to.have.length(0);
        });

        it('should match absolute links given relative option', function () {
            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'relative'});

            expect(output).to.have.length(1);
        });
    });
});
<commit_msg>Test false option in href-type<commit_after>describe('rules.href_type', function () {
    var rule = require('../lib/rules/href_type'),
		htmllint = require('../'),
        Parser = require('../lib/parser'),
		parser = null;

    describe('process', function () {
        var Parser = require('../lib/parser'),
            parser = null;

        it('should return an array', function () {
            var output = rule.process([]);

            expect(output).to.be.an.instanceOf(Array);
        });
        //this code is for if the flag is set to absolute
        it('should not match absolute links given absolute option', function () {

            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'absolute'});

            expect(output).to.have.length(0);
        });

        it('should match relative links given absolute option', function () {
            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'absolute'});

            expect(output).to.have.length(1);
        });

        it('should not match relative links given relative option', function () {

            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'relative'});

            expect(output).to.have.length(0);
        });

        it('should match absolute links given relative option', function () {
            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':'relative'});

            expect(output).to.have.length(1);
        });

        it('should not match any links given false option', function () {
            var parser = new Parser(),
                dom = parser.parse(''),
                output = rule.process(dom, {'href-type':false});

            expect(output).to.have.length(0);
        });
    });
});
<|endoftext|>


<commit_before>const Command = require('../Command');
const ChannelConfig = require('../../Models/ChannelConfig');
const Gitlab = require('../../Gitlab');
const GitlabUrlParser = require('../../Gitlab/GitlabRepoParser');

class GitlabInitCommand extends Command {

  constructor(bot) {
    super(bot);

    this.props.help = {
      name: 'init',
      summary: 'Initialize repo events on the channel.',
      description: 'Initialize repo events on the channel.\nInsert "private" as 2nd argument if the repo is private',
      usage: 'init <repo> [private]',
      examples: [
        'init datitisev/OhPlease-Yappy',
        'init https://gitlab.com/datitisev/DiscordBot-Yappy',
        'init Private/Repo private',
      ],
    };

    this.setConf({
      permLevel: 1,
      aliases: ['initialize'],
    });
  }

  async run(msg, args) {
    let channelid = msg.channel.id;
    let repo = args[0];
    let isPrivate = args[1] && (args[1].toLowerCase() === 'private');

    msg.channel.sendMessage('⚙ Working...');

    if (msg.member && !msg.member.permissions.hasPermission('ADMINISTRATOR') && !msg.author.id !== this.bot.config.owner) {
      return msg.channel.sendMessage('❌ Insuficient permissions! You must have administrator permissions to initialize repository events!');
    }

    let repository = GitlabUrlParser.Parse(repo) || {};

    let repoName = repository.name;
    let repoUser = repository.owner;
    if (!repository || !repoName || !repoUser) return this.errorUsage(msg);
    let repoFullName = repository.repo && repository.repo.toLowerCase();

    if (isPrivate) {
      // GitlabCache.add(repository.repo);
      let conf = ChannelConfig.FindByChannel(channelid);
      let doc = conf && conf.repos ? conf.repos.includes(repoFullName) : false;
      if (doc) return this.commandError(msg, `Repository \`${repository.repo}\` is already initialized in this channel`);
      return ChannelConfig.AddRepoToChannel(channelid, repoFullName)
      .then(() => {
        let message = this._successMessage(repository.repo);
        return msg.channel.sendMessage(message);
      });
    }

    Gitlab.getRepo(repoUser, repoName).then(repoInfo => {
      const repoActualName = repoInfo.path_with_namespace;
      const conf = ChannelConfig.FindByChannel(channelid);
      const doc = conf && conf.repos ? conf.repos.includes(repoActualName) : false;
      if (doc) return this.commandError(msg, `Repository \`${repoActualName}\` is already initialized in this channel`);
      return ChannelConfig.AddRepoToChannel(channelid, repoFullName)
      .then(() => {
        let message = this._successMessage(repoActualName);
        return msg.channel.sendMessage(message);
      });
    }).catch(err => {
      let errorMessage = err && err.name ? err.name : err || null;
      if (errorMessage && errorMessage !== 'Gitlab404Error') return this.commandError(msg, `Unable to get repository info for \`${repo}\`\n${err}`);
      return this.commandError(msg, `Unable to initialize! The repository \`${repository.repo}\` doesn't exist or is private!`);
    });
  }
  _successMessage(repo) {
    return [
      `✅ Successfully initialized repository events in this channel for **${repo}**.`,
      `The repository must a webhook pointing to <http://discordjsrewritetrello-datitisev.rhcloud.com/gitlab>`,
      `To use embeds to have a nicer GitLab log, say \`GL! conf enable embed\` in this channel to enable embeds for the current channel.`,
    ];
  }

}

module.exports = GitlabInitCommand;
<commit_msg>perf(command): remove `async` from init command<commit_after>const Command = require('../Command');
const ChannelConfig = require('../../Models/ChannelConfig');
const Gitlab = require('../../Gitlab');
const GitlabUrlParser = require('../../Gitlab/GitlabRepoParser');

class GitlabInitCommand extends Command {

  constructor(bot) {
    super(bot);

    this.props.help = {
      name: 'init',
      summary: 'Initialize repo events on the channel.',
      description: 'Initialize repo events on the channel.\nInsert "private" as 2nd argument if the repo is private',
      usage: 'init <repo> [private]',
      examples: [
        'init datitisev/OhPlease-Yappy',
        'init https://gitlab.com/datitisev/DiscordBot-Yappy',
        'init Private/Repo private',
      ],
    };

    this.setConf({
      permLevel: 1,
      aliases: ['initialize'],
    });
  }

  run(msg, args) {
    let channelid = msg.channel.id;
    let repo = args[0];
    let isPrivate = args[1] && (args[1].toLowerCase() === 'private');

    msg.channel.sendMessage('⚙ Working...');

    if (msg.member && !msg.member.permissions.hasPermission('ADMINISTRATOR') && !msg.author.id !== this.bot.config.owner) {
      return msg.channel.sendMessage('❌ Insuficient permissions! You must have administrator permissions to initialize repository events!');
    }

    let repository = GitlabUrlParser.Parse(repo) || {};

    let repoName = repository.name;
    let repoUser = repository.owner;
    if (!repository || !repoName || !repoUser) return this.errorUsage(msg);
    let repoFullName = repository.repo && repository.repo.toLowerCase();

    if (isPrivate) {
      // GitlabCache.add(repository.repo);
      let conf = ChannelConfig.FindByChannel(channelid);
      let doc = conf && conf.repos ? conf.repos.includes(repoFullName) : false;
      if (doc) return this.commandError(msg, `Repository \`${repository.repo}\` is already initialized in this channel`);
      return ChannelConfig.AddRepoToChannel(channelid, repoFullName)
      .then(() => {
        let message = this._successMessage(repository.repo);
        return msg.channel.sendMessage(message);
      });
    }

    Gitlab.getRepo(repoUser, repoName).then(repoInfo => {
      const repoActualName = repoInfo.path_with_namespace;
      const conf = ChannelConfig.FindByChannel(channelid);
      const doc = conf && conf.repos ? conf.repos.includes(repoActualName) : false;
      if (doc) return this.commandError(msg, `Repository \`${repoActualName}\` is already initialized in this channel`);
      return ChannelConfig.AddRepoToChannel(channelid, repoFullName)
      .then(() => {
        let message = this._successMessage(repoActualName);
        return msg.channel.sendMessage(message);
      });
    }).catch(err => {
      let errorMessage = err && err.name ? err.name : err || null;
      if (errorMessage && errorMessage !== 'Gitlab404Error') return this.commandError(msg, `Unable to get repository info for \`${repo}\`\n${err}`);
      return this.commandError(msg, `Unable to initialize! The repository \`${repository.repo}\` doesn't exist or is private!`);
    });
  }
  _successMessage(repo) {
    return [
      `✅ Successfully initialized repository events in this channel for **${repo}**.`,
      `The repository must a webhook pointing to <http://discordjsrewritetrello-datitisev.rhcloud.com/gitlab>`,
      `To use embeds to have a nicer GitLab log, say \`GL! conf enable embed\` in this channel to enable embeds for the current channel.`,
    ];
  }

}

module.exports = GitlabInitCommand;
<|endoftext|>


<commit_before>'use strict'
const {custom} = require('util').inspect
const stringify = require('./stringify.js')
const {assign, defineProperty} = Object
const {iterator, toStringTag} = Symbol

class SearchTree extends Map {
  constructor (elements = []) {
    super()
    elements.forEach(x => this.set(...x))
  }

  has ([first, ...rest]) {
    const spval = super.get(first)

    return Boolean(spval && (
      rest.length
        ? spval.subtree.has(rest)
        : spval.exists
    ))
  }

  get ([first, ...rest]) {
    const spval = super.get(first)

    return spval
      ? (rest.length
        ? spval.subtree.get(rest)
        : spval.value
      )
      : undefined
  }

  set ([first, ...rest], value) {
    const spval = super.get(first)

    if (spval) {
      if (rest.length) {
        spval.subtree.set(rest, value)
      } else {
        const {subtree = new SearchTree()} = spval
        assign(spval, {subtree, exists: true, value})
      }
    } else {
      const {length} = rest
      const subtree = new SearchTree(length ? [[rest, value]] : [])
      super.set(first, {subtree, exists: !length, value, __proto__: null})
    }

    return this
  }

  delete ([first, ...rest]) {
    const spval = super.get(first)

    if (!spval || !spval.exists) return false

    const {subtree} = spval

    if (rest.length) {
      if (subtree) {
        subtree.delete(rest)
      } else {
        super.delete(first)
      }
    } else {
      if (subtree) {
        spval.exists = false
      } else {
        super.delete(first)
      }
    }

    return true
  }

  clear () {
    super.clear()
    return this
  }

  get size () {
    let sz = 0

    for (const {1: spval} of super.entries()) {
      if (!spval) continue

      const {subtree, exists} = spval
      if (!subtree) continue

      sz += subtree.size + (exists ? 1 : 0)
    }

    return sz
  }

  * entries () {
    for (const [keyel, spval] of super.entries()) {
      if (!spval) continue

      const {subtree, exists, value} = spval

      if (exists) yield [keyel, value]

      if (subtree) {
        for (const [rest, value] of subtree) {
          yield [[keyel, ...rest], value]
        }
      }
    }
  }

  [iterator] () {
    return this.entries()
  }

  toString ({
    prefix = `${this[toStringTag]}\n`,

    suffix = '',

    arrow = ' => ',

    delimiter = ',\n  ',

    brackets: [
      openBracket = '{ ',
      closeBracket = ' }'
    ] = []
  } = {}) {
    const middle = Array.from(this)
      .map(x => x.map(stringify).join(arrow))
      .join(delimiter)

    return prefix + openBracket + middle + closeBracket + suffix
  }

  get [custom] () {
    return this.toString()
  }

  _showInternalStructure () {
    return new Map(Array.from(super.entries())
      .map(([keyel, spval]) => {
        if (!spval) return [keyel, spval]

        const {subtree, exists, value} = spval

        return [
          keyel,
          subtree
            ? {
              subtree: subtree._showInternalStructure(),
              exists,
              value
            }
            : spval
        ]
      })
    )
  }

  get _interalStructure () {
    return this._showInternalStructure()
  }

  remove (key) {
    this.remove(key)
    return this
  }

  get length () {
    return this.size
  }

  get count () {
    return this.size
  }

  static get name () {
    return 'SearchTree'
  }

  static toString () {
    return this[toStringTag]
  }

  static create (...args) {
    return new this(...args)
  }

  static get new () {
    return this.create()
  }
}

const defconst = (object, key, value, enumerable = false) =>
  defineProperty(object, key, {value, enumerable, writable: false, configurable: false})

const {prototype} = SearchTree
defconst(prototype, toStringTag, 'SearchTree')
defconst(SearchTree, toStringTag, 'class SearchTree extends Map')

module.exports = SearchTree
<commit_msg>Set default value to custom<commit_after>'use strict'
const {custom = Symbol('unavailable: custom')} = require('util').inspect
const stringify = require('./stringify.js')
const {assign, defineProperty} = Object
const {iterator, toStringTag} = Symbol

class SearchTree extends Map {
  constructor (elements = []) {
    super()
    elements.forEach(x => this.set(...x))
  }

  has ([first, ...rest]) {
    const spval = super.get(first)

    return Boolean(spval && (
      rest.length
        ? spval.subtree.has(rest)
        : spval.exists
    ))
  }

  get ([first, ...rest]) {
    const spval = super.get(first)

    return spval
      ? (rest.length
        ? spval.subtree.get(rest)
        : spval.value
      )
      : undefined
  }

  set ([first, ...rest], value) {
    const spval = super.get(first)

    if (spval) {
      if (rest.length) {
        spval.subtree.set(rest, value)
      } else {
        const {subtree = new SearchTree()} = spval
        assign(spval, {subtree, exists: true, value})
      }
    } else {
      const {length} = rest
      const subtree = new SearchTree(length ? [[rest, value]] : [])
      super.set(first, {subtree, exists: !length, value, __proto__: null})
    }

    return this
  }

  delete ([first, ...rest]) {
    const spval = super.get(first)

    if (!spval || !spval.exists) return false

    const {subtree} = spval

    if (rest.length) {
      if (subtree) {
        subtree.delete(rest)
      } else {
        super.delete(first)
      }
    } else {
      if (subtree) {
        spval.exists = false
      } else {
        super.delete(first)
      }
    }

    return true
  }

  clear () {
    super.clear()
    return this
  }

  get size () {
    let sz = 0

    for (const {1: spval} of super.entries()) {
      if (!spval) continue

      const {subtree, exists} = spval
      if (!subtree) continue

      sz += subtree.size + (exists ? 1 : 0)
    }

    return sz
  }

  * entries () {
    for (const [keyel, spval] of super.entries()) {
      if (!spval) continue

      const {subtree, exists, value} = spval

      if (exists) yield [keyel, value]

      if (subtree) {
        for (const [rest, value] of subtree) {
          yield [[keyel, ...rest], value]
        }
      }
    }
  }

  [iterator] () {
    return this.entries()
  }

  toString ({
    prefix = `${this[toStringTag]}\n`,

    suffix = '',

    arrow = ' => ',

    delimiter = ',\n  ',

    brackets: [
      openBracket = '{ ',
      closeBracket = ' }'
    ] = []
  } = {}) {
    const middle = Array.from(this)
      .map(x => x.map(stringify).join(arrow))
      .join(delimiter)

    return prefix + openBracket + middle + closeBracket + suffix
  }

  get [custom] () {
    return this.toString()
  }

  _showInternalStructure () {
    return new Map(Array.from(super.entries())
      .map(([keyel, spval]) => {
        if (!spval) return [keyel, spval]

        const {subtree, exists, value} = spval

        return [
          keyel,
          subtree
            ? {
              subtree: subtree._showInternalStructure(),
              exists,
              value
            }
            : spval
        ]
      })
    )
  }

  get _interalStructure () {
    return this._showInternalStructure()
  }

  remove (key) {
    this.remove(key)
    return this
  }

  get length () {
    return this.size
  }

  get count () {
    return this.size
  }

  static get name () {
    return 'SearchTree'
  }

  static toString () {
    return this[toStringTag]
  }

  static create (...args) {
    return new this(...args)
  }

  static get new () {
    return this.create()
  }
}

const defconst = (object, key, value, enumerable = false) =>
  defineProperty(object, key, {value, enumerable, writable: false, configurable: false})

const {prototype} = SearchTree
defconst(prototype, toStringTag, 'SearchTree')
defconst(SearchTree, toStringTag, 'class SearchTree extends Map')

module.exports = SearchTree
<|endoftext|>


<commit_before>/* LIB */

var authorize = require('./authorize');

/* MODULES */

var request = require('request');
var queryString = require('query-string');

/* CONSTRUCTOR */

(function() {

  var SendRequest = {};

  /* PRIVATE VARIABLES */

  var params;
  var baseUri = 'https://rest.telesign.com';

  /* PUBLIC FUNCTIONS */

  SendRequest.setup = function(setupParams) {
    params = setupParams;
    request = request.defaults({
      baseUrl: 'https://rest.telesign.com/v' + setupParams.version
    });
    authorize.setup(setupParams);
  };

  SendRequest.request = function(options, fn) {
    var headers = authorize.getHeaders(options.method, options.resource, options.fields);

    var requestOptions = {
      uri: options.resource,
      method: options.method,
      headers: headers,
      qs: options.qs,
      timeout: params.timeout,
      json: true
    };

    if (options.fields) {
      options.fields = queryString.stringify(options.fields);
      if (options.method === 'POST' || options.method === 'PUT') {
        requestOptions.body = options.fields;
      }
    }

    request(requestOptions, function(err, response, body) {
      if (err) {
        return fn('Error on request: ' + err);
      } else if (!response || !body) {
        return fn('Error - no response on request');
      } else if (response.status !== 200) {
        return fn(body);
      } else if (response.errors && response.errors.length > 0) {
        return fn(body);
      }
      return fn(null, body);
    });
  };

  /* NPM EXPORT */

  if (typeof module === 'object' && module.exports) {
    module.exports = SendRequest;
  } else {
    throw new Error('This module only works with NPM in NodeJS/IO.JS environments.');
  }

}());
<commit_msg>Fix statusCode check on request completion.<commit_after>/* LIB */

var authorize = require('./authorize');

/* MODULES */

var request = require('request');
var queryString = require('query-string');

/* CONSTRUCTOR */

(function() {

  var SendRequest = {};

  /* PRIVATE VARIABLES */

  var params;
  var baseUri = 'https://rest.telesign.com';

  /* PUBLIC FUNCTIONS */

  SendRequest.setup = function(setupParams) {
    params = setupParams;
    request = request.defaults({
      baseUrl: 'https://rest.telesign.com/v' + setupParams.version
    });
    authorize.setup(setupParams);
  };

  SendRequest.request = function(options, fn) {
    var headers = authorize.getHeaders(options.method, options.resource, options.fields);

    var requestOptions = {
      uri: options.resource,
      method: options.method,
      headers: headers,
      qs: options.qs,
      timeout: params.timeout,
      json: true
    };

    if (options.fields) {
      options.fields = queryString.stringify(options.fields);
      if (options.method === 'POST' || options.method === 'PUT') {
        requestOptions.body = options.fields;
      }
    }

    request(requestOptions, function(err, response, body) {
      if (err) {
        return fn('Error on request: ' + err);
      } else if (!response || !body) {
        return fn('Error - no response on request');
      } else if (response.statusCode !== 200) {
        return fn(body);
      } else if (response.errors && response.errors.length > 0) {
        return fn(body);
      }
      return fn(null, body);
    });
  };

  /* NPM EXPORT */

  if (typeof module === 'object' && module.exports) {
    module.exports = SendRequest;
  } else {
    throw new Error('This module only works with NPM in NodeJS/IO.JS environments.');
  }

}());
<|endoftext|>


<commit_before>(function() {
    'use strict';

    /* Global var accessible from any loaded module */
    global.cloudcmd     = {};

    var DIR, LIBDIR, SRVDIR, JSONDIR, HTMLDIR,
        Util,
        UTIL = 'util',

        SLASH,
        ISWIN32,
        ext, dir,
        path, fs, zlib, url, pipe, CloudFunc, diffPatch, querystring,

        OK, RANGE, FILE_NOT_FOUND, MOVED_PERMANENTLY,
        REQUEST, RESPONSE,

        Config = {
            server  : true,
            socket  : true,
            port    : 80
        };

    /* Consts */

    exports.OK                  = OK                = 200;
                                  RANGE             = 206;
                                  MOVED_PERMANENTLY = 301;
    exports.FILE_NOT_FOUND      = FILE_NOT_FOUND    = 404;

    exports.REQUEST     = REQUEST           = 'request';
    exports.RESPONSE    = RESPONSE          = 'response';

    /* Native Modules*/
    exports.crypto                          = require('crypto'),
    exports.child_process                   = require('child_process'),
    exports.fs          = fs                = require('fs'),
    exports.http                            = require('http'),
    exports.https                           = require('https'),
    exports.path        = path              = require('path'),
    exports.url         = url               = require('url'),
    exports.querystring = querystring       = require('querystring'),

    /* Constants */
    /* current dir + 2 levels up */
    exports.WIN32       = ISWIN32           = isWin32();
    exports.SLASH       = SLASH             = '/',

    exports.SRVDIR      = SRVDIR            = __dirname + SLASH,
    exports.LIBDIR      = LIBDIR            = path.normalize(SRVDIR + '../'),
    exports.DIR         = DIR               = path.normalize(LIBDIR + '../'),
    exports.HTMLDIR     = HTMLDIR           = DIR + 'html' + SLASH,
    exports.JSONDIR     = JSONDIR           = DIR + 'json' + SLASH,

    /* Functions */
    exports.require                         = mrequire,
    exports.librequire                      = librequire,
    exports.srvrequire                      = srvrequire,
    exports.rootrequire                     = rootrequire,
    exports.quietrequire                    = quietrequire,

    exports.generateHeaders                 = generateHeaders,
    exports.getQuery                        = getQuery,
    exports.getPathName                     = getPathName,
    exports.isGZIP                          = isGZIP,
    exports.mainSetHeader                   = mainSetHeader,

    exports.sendFile                        = sendFile,
    exports.sendResponse                    = sendResponse,
    exports.sendError                       = sendError,
    exports.redirect                        = redirect,

    exports.checkParams                     = checkParams,
    exports.checkCallBackParams             = checkCallBackParams,

    /* compitability with old versions of node */
    exports.fs.exists                       = exports.fs.exists || exports.path.exists,

    /* Needed Modules */

    /* we can not use librequare here */
    exports.util        = Util              = require(LIBDIR + UTIL),

    exports.zlib        = zlib              = mrequire('zlib'),

    /* Main Information */
    exports.modules                         = jsonrequire('modules');
    exports.ext         = ext               = jsonrequire('ext');
    exports.mainpackage                     = rootrequire('package');
    /* base configuration */
    exports.config                          = Config,

    /*
     * Any of loaded below modules could work with global var so
     * it should be initialized first. Becouse of almost any of
     * moudles do not depends on each other all needed information
     * for all modules is initialized hear.
     */
    global.cloudcmd.main                    = exports;

    exports.VOLUMES                         = getVolumes(),

    /* Additional Modules */
    exports.cloudfunc   = CloudFunc         = librequire('cloudfunc'),
    exports.pipe        = pipe              = srvrequire('pipe'),
    exports.socket                          = srvrequire('socket'),
    exports.console                         = srvrequire('console'),
    exports.terminal                        = !ISWIN32 ? srvrequire('terminal') : {
        init: function() {}
    },
    exports.express                         = srvrequire('express'),
    exports.auth                            = srvrequire('auth').auth,
    exports.appcache                        = srvrequire('appcache'),
    exports.dir         = dir               = srvrequire('dir'),
    exports.hash                            = srvrequire('hash'),
    diffPatch                               = librequire('diff/diff-match-patch').diff_match_patch,
    exports.diff                            = new (librequire('diff').DiffProto)(diffPatch),
    exports.users                           = srvrequire('users');
    exports.rest                            = srvrequire('rest').api,
    exports.update                          = srvrequire('update'),
    exports.ischanged                       = srvrequire('ischanged');
    exports.commander                       = srvrequire('commander');
    exports.files                           = srvrequire('files');

    exports.minify                          = srvrequire('minify').Minify;

    /* second initializing after all modules load, so global var is   *
     * totally filled of all information that should know all modules */
    global.cloudcmd.main            = exports;

    /**
     * function do safe require of needed module
     * @param {Strin} src
     */
    function mrequire(src) {
        var module, msg,
            error = Util.exec.try(function() {
                module = require(src);
            });

        if (error)
            if (error.code === 'MODULE_NOT_FOUND')
                msg = CloudFunc.formatMsg('require', src, 'no');
            else
                Util.log(error);

        Util.log(msg);

        return module;
    }

    function quietrequire(src) {
        var module;

        Util.exec.try(function() {
            module = require(src);
        });

        return module;
    }

    function rootrequire(src) { return mrequire(DIR + src); }

    function librequire(src) { return mrequire(LIBDIR + src); }

    function srvrequire(src) { return mrequire(SRVDIR + src); }

    function jsonrequire(src) { return mrequire(JSONDIR + src);}

    /**
     * function check is current platform is win32
     */
    function isWin32() { return process.platform === 'win32'; }

    /**
     * get volumes if win32 or get nothing if nix
     */
    function getVolumes() {
        var lRet = ISWIN32 ? [] : '/';

        if (ISWIN32)
            srvrequire('win').getVolumes(function(pVolumes) {
                Util.log(pVolumes);
                exports.VOLUMES = pVolumes;
            });

        return lRet;
    }

    /**
     * Функция создаёт заголовки файлов
     * в зависимости от расширения файла
     * перед отправкой их клиенту
     * @param pParams
     *  name - имя файла
     * gzip - данные сжаты gzip'ом
     * query
     * https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
     */
    function generateHeaders(params) {
        var header, p, extension, type, encoding, isContain, cmp;

        if (params.name) {
            p               = params,
            extension       = Util.getExt(p.name),
            type            = ext[extension] || 'text/plain',
            encoding        = '';

            /* if type of file any, but img - then we shoud specify charset */
            isContain       = Util.isContainStr(type, ['img', 'image', 'audio']);
            if (!isContain)
                encoding    = '; charset=UTF-8';

            isContain        = Util.isContainStr(p.query, 'download');
            if (isContain)
                type        = 'application/octet-stream';

            header          = {
                'Access-Control-Allow-Origin'   : '*',
                'Content-Type'                  : type  + encoding,
                'Vary'                          : 'Accept-Encoding',
                'Accept-Ranges'                 : 'bytes'
            };

            if (p.time)
                Util.copyObj(header, {
                    'Last-Modified' : p.time
                });

            if (p.range)
                Util.copyObj(header, {
                    'Content-Range' :   'bytes '    + p.range.start +
                                        '-'         + p.range.end   +
                                        '/'         + p.range.sizeTotal,

                    'Content-Length':   p.range.size
                });

            cmp             = Util.strCmp(ext, '.appcache');
            if (!cmp && p.cache)
                header['Cache-Control']     = 'max-age=' + 31337 * 21;

            if (p.gzip)
                header['Content-Encoding']  = 'gzip';
        }

        return header;
    }

    function mainSetHeader(pParams) {
        var p, header, lGzip,
            lRet = checkParams(pParams);

        if (lRet) {
            p       = pParams;
            lGzip   = p.isGzip || isGZIP(p.request) && p.gzip;

            header  = generateHeaders({
                name    : p.name,
                time    : p.time,
                range   : p.range,
                length  : p.length,
                cache   : p.cache,
                gzip    : lGzip,
                query   : getQuery(p.request)
            });

            setHeader(header, p.response);
            p.response.statusCode = p.status || OK;
        }
    }

    /**
     * send file to client thru pipe
     * and gzip it if client support
     *
     * @param pName - имя файла
     * @param pGzip - данные сжаты gzip'ом
     */
    function sendFile(params) {
        var isGzip,
            p       = params,
            ret     = checkParams(params);

        if (ret) {
            isGzip  = isGZIP(p.request) && p.gzip;

            fs.lstat(p.name, function(error, stat) {
                var time, length, range,
                    options = {};

                if (error) {
                    sendError(params, error);
                } else {
                    time    = stat.mtime,
                    length  = stat.size,
                    range   = getRange(p.request, length);

                    if (range)
                        Util.copyObj(p, {
                            range       : range,
                            status      : RANGE
                        });

                    Util.copyObj(p, {
                        isGzip      : isGzip && !range,
                        time        : time
                    });

                    mainSetHeader(params);

                    options = {
                        gzip    : isGzip && !range,
                        range   : range
                    };

                    pipe.create(p.name, p.response, options, function(error) {
                        if (error)
                            sendError(params, error);
                    });
                }
            });
        }

        return ret;
    }

    /**
     * Функция высылает ответ серверу
     * @param pHead     - заголовок
     * @param Data      - данные
     * @param pName     - имя отсылаемого файла
     */
    function sendResponse(params, data, notLog) {
        var p, isGzip, head,
            ret = checkParams(params);

        if (ret) {
            p           = params;
            data        = p.data || data;
            isGzip      = isGZIP(p.request);

            head        = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : isGzip,
                query   : p.query
            });

            setHeader(head, p.response);

            if (!notLog)
                Util.log(data);

            /* если браузер поддерживает gzip-сжатие - сжимаем данные*/
            Util.exec.if(!isGzip,
                function() {
                    p.status    = params.status || p.status;

                    if (!p.data)
                        p.data      = data;

                    p.response.statusCode = p.status || OK;
                    p.response.end(p.data);
                },

                function(callback) {
                    zlib.gzip (data, function(error, data) {
                        if (!error)
                            p.data = data;
                        else {
                            p.status    = FILE_NOT_FOUND;
                            p.data      = error.toString();
                        }

                        Util.exec(callback, p);
                    });
                });
        }
    }

    /**
     * redirect to another URL
     */
    function redirect(pParams) {
        var p, header,
            lRet    = Util.checkObjTrue(pParams, [RESPONSE]);

        if (lRet) {
            p       = pParams;

            header  = {
                'Location': p.url
            };

            setHeader(header, p.response);
            p.response.statusCode = MOVED_PERMANENTLY;
            p.response.end();
        }
    }

    /**
     * send error response
     */
    function sendError(params, error) {
        var p, ret     = checkParams(params);

        if (ret) {
            p           = params;
            p.status    = FILE_NOT_FOUND;

            if (!p.data && error)
              p.data    = error.toString();

            sendResponse(p);
        }
    }

    function checkCallBackParams(pParams) {
        return Util.checkObj(pParams, ['error', 'data', 'params']);
    }

    function checkParams(params, additional) {
        var ret = Util.checkObjTrue(params, ['name', REQUEST, RESPONSE]);

        if (ret && additional)
            ret = Util.checkObjTrue(params, additional);

        return ret;
    }

    function getQuery(req) {
        var query, parsed;

        if (req) {
            parsed  = url.parse(req.url);
            query   = parsed.query;
        }

        return query;
    }

    function getPathName(req) {
        var pathname, parsed;

        if (req) {
            parsed      = url.parse(req.url);
            pathname    = parsed.pathname;
            /* supporting of Russian language in directory names */
            pathname    = querystring.unescape(pathname);
        }

        return pathname;
    }

    function isGZIP(pReq) {
        var lEnc, lGZIP;
        if (pReq) {
            lEnc        = pReq.headers['accept-encoding'] || '';
            lGZIP       = lEnc.match(/\bgzip\b/);
        }

        return lGZIP;
    }

    function setHeader(header, response) {
        var name;

        if (!response.headersSent && Util.isObject(header))
            for (name in header)
                response.setHeader(name, header[name]);
    }

    function getRange(req, sizeTotal) {
        var range, start, end, size, parts,
            rangeStr = req.headers.range;

        if (rangeStr) {
            parts   = rangeStr.replace(/bytes=/, '').split('-');
            start   = parts[0];
            end     = parts[1] || sizeTotal - 1;
            size    = (end - start) + 1;

            range   = {
                start       : start - 0,
                end         : end - 0,
                size        : size,
                sizeTotal   : sizeTotal
            };
        }

        return range;
    }
})();
<commit_msg>fix(main) generateHeaders: if no cache: max-age - 0<commit_after>(function() {
    'use strict';

    /* Global var accessible from any loaded module */
    global.cloudcmd     = {};

    var DIR, LIBDIR, SRVDIR, JSONDIR, HTMLDIR,
        Util,
        UTIL = 'util',

        SLASH,
        ISWIN32,
        ext, dir,
        path, fs, zlib, url, pipe, CloudFunc, diffPatch, querystring,

        OK, RANGE, FILE_NOT_FOUND, MOVED_PERMANENTLY,
        REQUEST, RESPONSE,

        Config = {
            server  : true,
            socket  : true,
            port    : 80
        };

    /* Consts */

    exports.OK                  = OK                = 200;
                                  RANGE             = 206;
                                  MOVED_PERMANENTLY = 301;
    exports.FILE_NOT_FOUND      = FILE_NOT_FOUND    = 404;

    exports.REQUEST     = REQUEST           = 'request';
    exports.RESPONSE    = RESPONSE          = 'response';

    /* Native Modules*/
    exports.crypto                          = require('crypto'),
    exports.child_process                   = require('child_process'),
    exports.fs          = fs                = require('fs'),
    exports.http                            = require('http'),
    exports.https                           = require('https'),
    exports.path        = path              = require('path'),
    exports.url         = url               = require('url'),
    exports.querystring = querystring       = require('querystring'),

    /* Constants */
    /* current dir + 2 levels up */
    exports.WIN32       = ISWIN32           = isWin32();
    exports.SLASH       = SLASH             = '/',

    exports.SRVDIR      = SRVDIR            = __dirname + SLASH,
    exports.LIBDIR      = LIBDIR            = path.normalize(SRVDIR + '../'),
    exports.DIR         = DIR               = path.normalize(LIBDIR + '../'),
    exports.HTMLDIR     = HTMLDIR           = DIR + 'html' + SLASH,
    exports.JSONDIR     = JSONDIR           = DIR + 'json' + SLASH,

    /* Functions */
    exports.require                         = mrequire,
    exports.librequire                      = librequire,
    exports.srvrequire                      = srvrequire,
    exports.rootrequire                     = rootrequire,
    exports.quietrequire                    = quietrequire,

    exports.generateHeaders                 = generateHeaders,
    exports.getQuery                        = getQuery,
    exports.getPathName                     = getPathName,
    exports.isGZIP                          = isGZIP,
    exports.mainSetHeader                   = mainSetHeader,

    exports.sendFile                        = sendFile,
    exports.sendResponse                    = sendResponse,
    exports.sendError                       = sendError,
    exports.redirect                        = redirect,

    exports.checkParams                     = checkParams,
    exports.checkCallBackParams             = checkCallBackParams,

    /* compitability with old versions of node */
    exports.fs.exists                       = exports.fs.exists || exports.path.exists,

    /* Needed Modules */

    /* we can not use librequare here */
    exports.util        = Util              = require(LIBDIR + UTIL),

    exports.zlib        = zlib              = mrequire('zlib'),

    /* Main Information */
    exports.modules                         = jsonrequire('modules');
    exports.ext         = ext               = jsonrequire('ext');
    exports.mainpackage                     = rootrequire('package');
    /* base configuration */
    exports.config                          = Config,

    /*
     * Any of loaded below modules could work with global var so
     * it should be initialized first. Becouse of almost any of
     * moudles do not depends on each other all needed information
     * for all modules is initialized hear.
     */
    global.cloudcmd.main                    = exports;

    exports.VOLUMES                         = getVolumes(),

    /* Additional Modules */
    exports.cloudfunc   = CloudFunc         = librequire('cloudfunc'),
    exports.pipe        = pipe              = srvrequire('pipe'),
    exports.socket                          = srvrequire('socket'),
    exports.console                         = srvrequire('console'),
    exports.terminal                        = !ISWIN32 ? srvrequire('terminal') : {
        init: function() {}
    },
    exports.express                         = srvrequire('express'),
    exports.auth                            = srvrequire('auth').auth,
    exports.appcache                        = srvrequire('appcache'),
    exports.dir         = dir               = srvrequire('dir'),
    exports.hash                            = srvrequire('hash'),
    diffPatch                               = librequire('diff/diff-match-patch').diff_match_patch,
    exports.diff                            = new (librequire('diff').DiffProto)(diffPatch),
    exports.users                           = srvrequire('users');
    exports.rest                            = srvrequire('rest').api,
    exports.update                          = srvrequire('update'),
    exports.ischanged                       = srvrequire('ischanged');
    exports.commander                       = srvrequire('commander');
    exports.files                           = srvrequire('files');

    exports.minify                          = srvrequire('minify').Minify;

    /* second initializing after all modules load, so global var is   *
     * totally filled of all information that should know all modules */
    global.cloudcmd.main            = exports;

    /**
     * function do safe require of needed module
     * @param {Strin} src
     */
    function mrequire(src) {
        var module, msg,
            error = Util.exec.try(function() {
                module = require(src);
            });

        if (error)
            if (error.code === 'MODULE_NOT_FOUND')
                msg = CloudFunc.formatMsg('require', src, 'no');
            else
                Util.log(error);

        Util.log(msg);

        return module;
    }

    function quietrequire(src) {
        var module;

        Util.exec.try(function() {
            module = require(src);
        });

        return module;
    }

    function rootrequire(src) { return mrequire(DIR + src); }

    function librequire(src) { return mrequire(LIBDIR + src); }

    function srvrequire(src) { return mrequire(SRVDIR + src); }

    function jsonrequire(src) { return mrequire(JSONDIR + src);}

    /**
     * function check is current platform is win32
     */
    function isWin32() { return process.platform === 'win32'; }

    /**
     * get volumes if win32 or get nothing if nix
     */
    function getVolumes() {
        var lRet = ISWIN32 ? [] : '/';

        if (ISWIN32)
            srvrequire('win').getVolumes(function(pVolumes) {
                Util.log(pVolumes);
                exports.VOLUMES = pVolumes;
            });

        return lRet;
    }

    /**
     * Функция создаёт заголовки файлов
     * в зависимости от расширения файла
     * перед отправкой их клиенту
     * @param pParams
     *  name - имя файла
     * gzip - данные сжаты gzip'ом
     * query
     * https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
     */
    function generateHeaders(params) {
        var header, p, extension, type, encoding, isContain, cmp,
            maxAge          = 31337 * 21;

        if (params.name) {
            p               = params,
            extension       = Util.getExt(p.name),
            type            = ext[extension] || 'text/plain',
            encoding        = '';

            /* if type of file any, but img - then we shoud specify charset */
            isContain       = Util.isContainStr(type, ['img', 'image', 'audio']);
            if (!isContain)
                encoding    = '; charset=UTF-8';

            isContain        = Util.isContainStr(p.query, 'download');
            if (isContain)
                type        = 'application/octet-stream';

            header          = {
                'Access-Control-Allow-Origin'   : '*',
                'Content-Type'                  : type  + encoding,
                'Vary'                          : 'Accept-Encoding',
                'Accept-Ranges'                 : 'bytes'
            };

            if (p.time)
                Util.copyObj(header, {
                    'Last-Modified' : p.time
                });

            if (p.range)
                Util.copyObj(header, {
                    'Content-Range' :   'bytes '    + p.range.start +
                                        '-'         + p.range.end   +
                                        '/'         + p.range.sizeTotal,

                    'Content-Length':   p.range.size
                });

            cmp             = Util.strCmp(ext, '.appcache');
            if (!p.cache || cmp)
                maxAge  = 0;

            header['Cache-Control']     = 'max-age=' + maxAge;

            if (p.gzip)
                header['Content-Encoding']  = 'gzip';
        }

        return header;
    }

    function mainSetHeader(pParams) {
        var p, header, lGzip,
            lRet = checkParams(pParams);

        if (lRet) {
            p       = pParams;
            lGzip   = p.isGzip || isGZIP(p.request) && p.gzip;

            header  = generateHeaders({
                name    : p.name,
                time    : p.time,
                range   : p.range,
                length  : p.length,
                cache   : p.cache,
                gzip    : lGzip,
                query   : getQuery(p.request)
            });

            setHeader(header, p.response);
            p.response.statusCode = p.status || OK;
        }
    }

    /**
     * send file to client thru pipe
     * and gzip it if client support
     *
     * @param pName - имя файла
     * @param pGzip - данные сжаты gzip'ом
     */
    function sendFile(params) {
        var isGzip,
            p       = params,
            ret     = checkParams(params);

        if (ret) {
            isGzip  = isGZIP(p.request) && p.gzip;

            fs.lstat(p.name, function(error, stat) {
                var time, length, range,
                    options = {};

                if (error) {
                    sendError(params, error);
                } else {
                    time    = stat.mtime,
                    length  = stat.size,
                    range   = getRange(p.request, length);

                    if (range)
                        Util.copyObj(p, {
                            range       : range,
                            status      : RANGE
                        });

                    Util.copyObj(p, {
                        isGzip      : isGzip && !range,
                        time        : time
                    });

                    mainSetHeader(params);

                    options = {
                        gzip    : isGzip && !range,
                        range   : range
                    };

                    pipe.create(p.name, p.response, options, function(error) {
                        if (error)
                            sendError(params, error);
                    });
                }
            });
        }

        return ret;
    }

    /**
     * Функция высылает ответ серверу
     * @param pHead     - заголовок
     * @param Data      - данные
     * @param pName     - имя отсылаемого файла
     */
    function sendResponse(params, data, notLog) {
        var p, isGzip, head,
            ret = checkParams(params);

        if (ret) {
            p           = params;
            data        = p.data || data;
            isGzip      = isGZIP(p.request);

            head        = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : isGzip,
                query   : p.query
            });

            setHeader(head, p.response);

            if (!notLog)
                Util.log(data);

            /* если браузер поддерживает gzip-сжатие - сжимаем данные*/
            Util.exec.if(!isGzip,
                function() {
                    p.status    = params.status || p.status;

                    if (!p.data)
                        p.data      = data;

                    p.response.statusCode = p.status || OK;
                    p.response.end(p.data);
                },

                function(callback) {
                    zlib.gzip (data, function(error, data) {
                        if (!error)
                            p.data = data;
                        else {
                            p.status    = FILE_NOT_FOUND;
                            p.data      = error.toString();
                        }

                        Util.exec(callback, p);
                    });
                });
        }
    }

    /**
     * redirect to another URL
     */
    function redirect(pParams) {
        var p, header,
            lRet    = Util.checkObjTrue(pParams, [RESPONSE]);

        if (lRet) {
            p       = pParams;

            header  = {
                'Location': p.url
            };

            setHeader(header, p.response);
            p.response.statusCode = MOVED_PERMANENTLY;
            p.response.end();
        }
    }

    /**
     * send error response
     */
    function sendError(params, error) {
        var p, ret     = checkParams(params);

        if (ret) {
            p           = params;
            p.status    = FILE_NOT_FOUND;

            if (!p.data && error)
              p.data    = error.toString();

            sendResponse(p);
        }
    }

    function checkCallBackParams(pParams) {
        return Util.checkObj(pParams, ['error', 'data', 'params']);
    }

    function checkParams(params, additional) {
        var ret = Util.checkObjTrue(params, ['name', REQUEST, RESPONSE]);

        if (ret && additional)
            ret = Util.checkObjTrue(params, additional);

        return ret;
    }

    function getQuery(req) {
        var query, parsed;

        if (req) {
            parsed  = url.parse(req.url);
            query   = parsed.query;
        }

        return query;
    }

    function getPathName(req) {
        var pathname, parsed;

        if (req) {
            parsed      = url.parse(req.url);
            pathname    = parsed.pathname;
            /* supporting of Russian language in directory names */
            pathname    = querystring.unescape(pathname);
        }

        return pathname;
    }

    function isGZIP(pReq) {
        var lEnc, lGZIP;
        if (pReq) {
            lEnc        = pReq.headers['accept-encoding'] || '';
            lGZIP       = lEnc.match(/\bgzip\b/);
        }

        return lGZIP;
    }

    function setHeader(header, response) {
        var name;

        if (!response.headersSent && Util.isObject(header))
            for (name in header)
                response.setHeader(name, header[name]);
    }

    function getRange(req, sizeTotal) {
        var range, start, end, size, parts,
            rangeStr = req.headers.range;

        if (rangeStr) {
            parts   = rangeStr.replace(/bytes=/, '').split('-');
            start   = parts[0];
            end     = parts[1] || sizeTotal - 1;
            size    = (end - start) + 1;

            range   = {
                start       : start - 0,
                end         : end - 0,
                size        : size,
                sizeTotal   : sizeTotal
            };
        }

        return range;
    }
})();
<|endoftext|>