<commit_before>/**
 * Reordering utilities for the items drag and drop ordering page -AZ
 * Does not put stuff into the global namespace and uses only methods that are compatible with most browsers
 *
 * Update: Functions have been exposed to enable startSort() to be accessible by custom plugins - lovemore.nalube@uct.ac.za
 **/
var sortableIds = new Array();

$(document).ready(
        function () {
            startSort();
            $(document).trigger('activateControls.templateItems');
            buildSortableIds();
        }
    );

function $it(id) {
    return document.getElementById(id);
}

function enableOrderButtons() {
    try {
        $("#revertOrderButton")
                .attr('disabled', false)
                // put original order into the revertOrder trigger
                .bind('click', function() {
                    disableOrderButtons();
                    for (var i = sortableIds.length - 1; i > 0; --i) {
                        var thisitem = $it(sortableIds[i]);
                        var previtem = $it(sortableIds[i - 1]);
                        previtem.parentNode.removeChild(previtem);
                        thisitem.parentNode.insertBefore(previtem, thisitem);
                        setIndex(thisitem.id, i);
                    }
                    setIndex(sortableIds[0], 0);
                });
        $("#saveReorderButton").attr('disabled', false);
        $("#orderInputs").attr("class","itemOperationsEnabled");
    }catch(e){}
}

function disableOrderButtons() {
    try {
        $("#revertOrderButton").attr('disabled', true);
        $("#saveReorderButton").attr('disabled', true);
        $("#orderInputs").attr("class","itemOperations");
    }catch(e){}
}

function buildSortableIds() {
    $("#itemList > div.itemRow").each(function(){
       sortableIds.push($(this).attr('id'));
    });
}

function setIndex(itemId, newindex) {
    if (newindex != null || newindex != "") {
        var changed = sortableIds[newindex] != itemId;
        var itemSelect = document.getElementById(itemId + "item-select-selection");
        itemSelect.selectedIndex = newindex;
        // NOTE: might need to disable the pulldowns once the user drags
        $it(itemId + "hidden-item-num").value = newindex;
    }
}

function startSort() {
    var log = evalTemplateUtils.debug,
    numHasRun = 0;
    $("#itemList").sortable({
        axis:         'y',
        cancel:     ':input, button, a, select, div.itemLine3',
        connectWith: ['.itemTableBlock'],
        cursor:     'move',
        delay:         '1',
        opacity:     '0.9',
        scroll:     true,
        update: function(){
            evalTemplateSort.updateLabelling();
        }
    });
    $(".itemTableBlock").each(function() {
        $(this).sortable({
            axis: 'y',
            cancel: ':input, button, a, select',
            containment: 'parent',
            cursor: 'move',
            over: function(e, ui) {
                if ($('#closeItemOperationsEnabled').length > 0) {
                    $('#closeItemOperationsEnabled').parent().remove();
                }
            },
            deactivate: function(e, ui) {
                //Ensure this only runs once when object is dropped into the group by tracking {@link numHasRun}
                if (numHasRun === 0){
                    if ((ui.sender.attr('id') != "itemTableBlock") && (ui.item.parent().attr('id') != "itemList")) {
                        var that = ui.item.find('.itemCheckbox > input').eq(0).attr('id');
                        if (that === null || typeof that === "undefined") {
                            $(document).trigger('block.rejectItem', [ui , "plain"]);
                            log.warn("RejectItem: Item is not the same type as the grouped items");
                        }else{
                        var target = ui.item.parents('.itemRow').eq(0).find('.itemCheckbox > input').eq(0).attr('id');
                        if (target === null || typeof target === "undefined"){
                            $(document).trigger('block.rejectItem', [ui , "plain"]);
                            log.warn("RejectItem: Target is is not the same type as the selected Item");
                        }else{
                        var targetVal = target.substring(target.indexOf('-') + 1, target.lastIndexOf('-'));
                        var thatVal = that.substring(that.indexOf('-') + 1, that.lastIndexOf('-'));
                        if (targetVal !== thatVal) {
                            $(document).trigger('block.rejectItem', [ui, "plain"]);
                        } else {
                            var confirmMsg = 'Are you sure you want to add this item into this group?';//todo: i8n this
                                if (confirm(confirmMsg)) {
                                    var parentObj = ui.item.parents("div.itemRow"),
                                    blockId = parentObj.find("input[name=template-item-id]").val(),
                                    itemId =  ui.item.find('a[templateitemid]').attr('templateitemid');
                                    log.info("Added group %o", parentObj);
                                    ui.item.attr('style', 'display:none');
                                    var shadow = ui.item.parent().find('.itemRowBlock').eq(0).clone(true);
                                    ui.item.parent().find('div[id="' + shadow.attr('id') + '"]').not(':lt(2)').remove();
                                    shadow.find('span').eq(1).html(ui.item.find('.itemText > span').eq(0).html());
                                    shadow.find('input').eq(0).val(itemId);
                                    shadow.find('a[templateitemid]').attr('templateitemid', ui.item.find('a[templateitemid]').attr('templateitemid'));
                                    shadow.find('a[otp]').attr('otp', ui.item.find('a[otp]').attr('otp'));
                                    shadow.insertAfter(ui.item);
                                    log.info("Added %o to group %o", itemId, parentObj);
                                    //Save new item to the group using already set EB post method
                                    var params = {
                                        blockid : blockId,
                                        additems: itemId
                                    },
                                    fnAfter = function(){
                                        //remove item from list of items that can be grouped
                                        for (var i in evalTemplateUtils.vars.groupableItems){
                                            if(evalTemplateUtils.vars.groupableItems[i].itemId === itemId){
                                                evalTemplateUtils.vars.groupableItems.splice(i, 1);
                                            }
                                        }
                                        //Save new group order
                                        evalTemplateOrder.saveGroupLevelTemplateOrdering(ui.item);
                                        //Save overall template ordering so the template knows that we've removed a few items and grouped them.
                                        evalTemplateOrder.saveTopLevelTemplateOrdering();
                                        refreshSort();
                                        $(document).trigger('block.triggerChildrenSort', [parentObj]);
                                    };
                                    evalTemplateData.item.saveOrder(evalTemplateUtils.pages.eb_block_edit, params, null, fnAfter);
                                }
                                else{
                                    $(document).trigger('block.rejectItem', [ui, "noAlert"]);
                                }
                        }
                        triggerSort}
                    }
                    }
                }
                numHasRun ++;
            },
            delay: '1',
            items: 'div',
            opacity: '0.9',
            scroll: true,
            update: function(e, ui) {
                evalTemplateOrder.initSaveGroupOrderControls(ui.item);
            }
        });
    });
}
function refreshSort() {
    $("div.itemList").sortable('destroy');
    $("div.itemTableBlock").sortable('destroy');
    startSort();
}
$(document).bind('block.triggerChildrenSort', function(e, parentItem) {
    evalTemplateUtils.debug.info("block.triggerChildrenSort with patent item %o", parentItem);
    $.each(parentItem.find('div.itemRowBlock').not('.ui-sortable-helper'), function(i, _this){
        $(_this).find('span.itemLabel').text(i + 1);
    });
    refreshSort();
});
$(document).bind('block.rejectItem', function(e, ui, option) {
    $(document).trigger('list.warning', [ui, option, 'block', 'Sorry this item cannot be grouped here. It is not the same type as the grouped items.']);//todo: i8n this
    var shadow = ui.item.clone(true);
    var shadowPlace = $('.itemList > div.itemRow').eq(ui.item.find('input').eq(0).val()).attr('id');
    ui.item.remove();
    shadow.insertBefore($('[id="' + shadowPlace + '"]'));
    shadow.removeAttr('style').effect('highlight', 1000);
    $('.itemList div[id="' + shadow.attr('id') + '"]').not(':lt(1)').remove();
    refreshSort();
    evalTemplateSort.updateLabelling();
    //init dropdown controls
    evalTemplateOrder.initDropDowns();
});

$(document).bind('list.warning', function(e, ui, option, extra, err){
    var item = ui.item? ui.item : ui;
        if (option != "noAlert") {
        $('.itemOperationsEnabled').remove();
        var error = '
\
                        \
                        '+ err +' close
\
                        ';
        if(extra == 'block')
            item.parents('.itemLine3').prepend(error);
        $('#closeItemOperationsEnabled').click(function() {
            $(this).parent().slideUp('normal', function() {
                $(this).remove()
            });
            return false
        });
    }
});
<commit_msg>NOJIRA. removal of phantom triggerSort call.<commit_after>/**
 * Reordering utilities for the items drag and drop ordering page -AZ
 * Does not put stuff into the global namespace and uses only methods that are compatible with most browsers
 *
 * Update: Functions have been exposed to enable startSort() to be accessible by custom plugins - lovemore.nalube@uct.ac.za
 **/
var sortableIds = new Array();

$(document).ready(
        function () {
            startSort();
            $(document).trigger('activateControls.templateItems');
            buildSortableIds();
        }
    );

function $it(id) {
    return document.getElementById(id);
}

function enableOrderButtons() {
    try {
        $("#revertOrderButton")
                .attr('disabled', false)
                // put original order into the revertOrder trigger
                .bind('click', function() {
                    disableOrderButtons();
                    for (var i = sortableIds.length - 1; i > 0; --i) {
                        var thisitem = $it(sortableIds[i]);
                        var previtem = $it(sortableIds[i - 1]);
                        previtem.parentNode.removeChild(previtem);
                        thisitem.parentNode.insertBefore(previtem, thisitem);
                        setIndex(thisitem.id, i);
                    }
                    setIndex(sortableIds[0], 0);
                });
        $("#saveReorderButton").attr('disabled', false);
        $("#orderInputs").attr("class","itemOperationsEnabled");
    }catch(e){}
}

function disableOrderButtons() {
    try {
        $("#revertOrderButton").attr('disabled', true);
        $("#saveReorderButton").attr('disabled', true);
        $("#orderInputs").attr("class","itemOperations");
    }catch(e){}
}

function buildSortableIds() {
    $("#itemList > div.itemRow").each(function(){
       sortableIds.push($(this).attr('id'));
    });
}

function setIndex(itemId, newindex) {
    if (newindex != null || newindex != "") {
        var changed = sortableIds[newindex] != itemId;
        var itemSelect = document.getElementById(itemId + "item-select-selection");
        itemSelect.selectedIndex = newindex;
        // NOTE: might need to disable the pulldowns once the user drags
        $it(itemId + "hidden-item-num").value = newindex;
    }
}

function startSort() {
    var log = evalTemplateUtils.debug,
    numHasRun = 0;
    $("#itemList").sortable({
        axis:         'y',
        cancel:     ':input, button, a, select, div.itemLine3',
        connectWith: ['.itemTableBlock'],
        cursor:     'move',
        delay:         '1',
        opacity:     '0.9',
        scroll:     true,
        update: function(){
            evalTemplateSort.updateLabelling();
        }
    });
    $(".itemTableBlock").each(function() {
        $(this).sortable({
            axis: 'y',
            cancel: ':input, button, a, select',
            containment: 'parent',
            cursor: 'move',
            over: function(e, ui) {
                if ($('#closeItemOperationsEnabled').length > 0) {
                    $('#closeItemOperationsEnabled').parent().remove();
                }
            },
            deactivate: function(e, ui) {
                //Ensure this only runs once when object is dropped into the group by tracking {@link numHasRun}
                if (numHasRun === 0){
                    if ((ui.sender.attr('id') != "itemTableBlock") && (ui.item.parent().attr('id') != "itemList")) {
                        var that = ui.item.find('.itemCheckbox > input').eq(0).attr('id');
                        if (that === null || typeof that === "undefined") {
                            $(document).trigger('block.rejectItem', [ui , "plain"]);
                            log.warn("RejectItem: Item is not the same type as the grouped items");
                        }else{
                        var target = ui.item.parents('.itemRow').eq(0).find('.itemCheckbox > input').eq(0).attr('id');
                        if (target === null || typeof target === "undefined"){
                            $(document).trigger('block.rejectItem', [ui , "plain"]);
                            log.warn("RejectItem: Target is is not the same type as the selected Item");
                        }else{
                        var targetVal = target.substring(target.indexOf('-') + 1, target.lastIndexOf('-'));
                        var thatVal = that.substring(that.indexOf('-') + 1, that.lastIndexOf('-'));
                        if (targetVal !== thatVal) {
                            $(document).trigger('block.rejectItem', [ui, "plain"]);
                        } else {
                            var confirmMsg = 'Are you sure you want to add this item into this group?';//todo: i8n this
                                if (confirm(confirmMsg)) {
                                    var parentObj = ui.item.parents("div.itemRow"),
                                    blockId = parentObj.find("input[name=template-item-id]").val(),
                                    itemId =  ui.item.find('a[templateitemid]').attr('templateitemid');
                                    log.info("Added group %o", parentObj);
                                    ui.item.attr('style', 'display:none');
                                    var shadow = ui.item.parent().find('.itemRowBlock').eq(0).clone(true);
                                    ui.item.parent().find('div[id="' + shadow.attr('id') + '"]').not(':lt(2)').remove();
                                    shadow.find('span').eq(1).html(ui.item.find('.itemText > span').eq(0).html());
                                    shadow.find('input').eq(0).val(itemId);
                                    shadow.find('a[templateitemid]').attr('templateitemid', ui.item.find('a[templateitemid]').attr('templateitemid'));
                                    shadow.find('a[otp]').attr('otp', ui.item.find('a[otp]').attr('otp'));
                                    shadow.insertAfter(ui.item);
                                    log.info("Added %o to group %o", itemId, parentObj);
                                    //Save new item to the group using already set EB post method
                                    var params = {
                                        blockid : blockId,
                                        additems: itemId
                                    },
                                    fnAfter = function(){
                                        //remove item from list of items that can be grouped
                                        for (var i in evalTemplateUtils.vars.groupableItems){
                                            if(evalTemplateUtils.vars.groupableItems[i].itemId === itemId){
                                                evalTemplateUtils.vars.groupableItems.splice(i, 1);
                                            }
                                        }
                                        //Save new group order
                                        evalTemplateOrder.saveGroupLevelTemplateOrdering(ui.item);
                                        //Save overall template ordering so the template knows that we've removed a few items and grouped them.
                                        evalTemplateOrder.saveTopLevelTemplateOrdering();
                                        refreshSort();
                                        $(document).trigger('block.triggerChildrenSort', [parentObj]);
                                    };
                                    evalTemplateData.item.saveOrder(evalTemplateUtils.pages.eb_block_edit, params, null, fnAfter);
                                }
                                else{
                                    $(document).trigger('block.rejectItem', [ui, "noAlert"]);
                                }
                        }
                      }
                    }
                    }
                }
                numHasRun ++;
            },
            delay: '1',
            items: 'div',
            opacity: '0.9',
            scroll: true,
            update: function(e, ui) {
                evalTemplateOrder.initSaveGroupOrderControls(ui.item);
            }
        });
    });
}
function refreshSort() {
    $("div.itemList").sortable('destroy');
    $("div.itemTableBlock").sortable('destroy');
    startSort();
}
$(document).bind('block.triggerChildrenSort', function(e, parentItem) {
    evalTemplateUtils.debug.info("block.triggerChildrenSort with patent item %o", parentItem);
    $.each(parentItem.find('div.itemRowBlock').not('.ui-sortable-helper'), function(i, _this){
        $(_this).find('span.itemLabel').text(i + 1);
    });
    refreshSort();
});
$(document).bind('block.rejectItem', function(e, ui, option) {
    $(document).trigger('list.warning', [ui, option, 'block', 'Sorry this item cannot be grouped here. It is not the same type as the grouped items.']);//todo: i8n this
    var shadow = ui.item.clone(true);
    var shadowPlace = $('.itemList > div.itemRow').eq(ui.item.find('input').eq(0).val()).attr('id');
    ui.item.remove();
    shadow.insertBefore($('[id="' + shadowPlace + '"]'));
    shadow.removeAttr('style').effect('highlight', 1000);
    $('.itemList div[id="' + shadow.attr('id') + '"]').not(':lt(1)').remove();
    refreshSort();
    evalTemplateSort.updateLabelling();
    //init dropdown controls
    evalTemplateOrder.initDropDowns();
});

$(document).bind('list.warning', function(e, ui, option, extra, err){
    var item = ui.item? ui.item : ui;
        if (option != "noAlert") {
        $('.itemOperationsEnabled').remove();
        var error = '
\
                        \
                        '+ err +' close
\
                        ';
        if(extra == 'block')
            item.parents('.itemLine3').prepend(error);
        $('#closeItemOperationsEnabled').click(function() {
            $(this).parent().slideUp('normal', function() {
                $(this).remove()
            });
            return false
        });
    }
});
<|endoftext|>


<commit_before>'use strict';

/**
 * serverless-mocha-plugin
 * - a plugin for TDD with serverless
 */

const path  = require('path'),
  fs        = require('fs'),
  lambdaWrapper = require('lambda-wrapper'),
  Mocha = require('mocha'),
  chai = require('chai'),
  BbPromise = require('bluebird'); // Serverless uses Bluebird Promises and we recommend you do to because they provide more than your average Promise :)

const testFolder = 'test'; // Folder used my mocha for tests

module.exports = function(S) { // Always pass in the ServerlessPlugin Class

  /**
   * Adding/Manipulating Serverless classes
   * - You can add or manipulate Serverless classes like this
   */

  S.classes.Project.newStaticMethod     = function() { console.log("A new method!"); };
  S.classes.Project.prototype.newMethod = function() { S.classes.Project.newStaticMethod(); };

  /**
   * Extending the Plugin Class
   * - Here is how you can add custom Actions and Hooks to Serverless.
   * - This class is only required if you want to add Actions and Hooks.
   */

  class PluginBoilerplate extends S.classes.Plugin {

    /**
     * Constructor
     * - Keep this and don't touch it unless you know what you're doing.
     */

    constructor() {
      super();
      this.name = 'myPlugin'; // Define your plugin's name
    }

    /**
     * Register Actions
     * - function mocha-create
     */

    registerActions() {

      S.addAction(this._createAction.bind(this), {
        handler:       'customAction',
        description:   'Create mocha test for function',
        context:       'function',
        contextAction: 'mocha-create',
        options:       [{ // These must be specified in the CLI like this "-option true" or "-o true"
        }],
        parameters: [ // Use paths when you multiple values need to be input (like an array).  Input looks like this: "serverless custom run module1/function1 module1/function2 module1/function3.  Serverless will automatically turn this into an array and attach it to evt.options within your plugin
          {
            parameter: 'paths',
            description: 'Path to function to test. If not defined, test all functions.',
            position: '0->' // Can be: 0, 0-2, 0->  This tells Serverless which params are which.  3-> Means that number and infinite values after it.
          }
        ]
      });

      S.addAction(this._runAction.bind(this), {
        handler:       'customAction',
        description:   'Create mocha test for function',
        context:       'function',
        contextAction: 'mocha-run',
        options:       [{ // These must be specified in the CLI like this "-option true" or "-o true"
        }],
        parameters: [ // Use paths when you multiple values need to be input (like an array).  Input looks like this: "serverless custom run module1/function1 module1/function2 module1/function3.  Serverless will automatically turn this into an array and attach it to evt.options within your plugin
          {
            parameter: 'paths',
            description: 'Path to function to test. If not defined, test all functions.',
            position: '0->' // Can be: 0, 0-2, 0->  This tells Serverless which params are which.  3-> Means that number and infinite values after it.
          }
        ]
      });

      return BbPromise.resolve();
    }

    /**
     * Register Hooks
     * -  function create (post) creates mocha test file
     */

    registerHooks() {
      S.addHook(this._hookPostFuncCreate.bind(this), {
        action: 'functionCreate',
        event:  'post'
      });

      return BbPromise.resolve();
    }

    /**
     * Custom action serverless function mocha-create functioName
     */

    _createAction(evt) {
      return createTest(evt.options.paths[0]);
    }

    /**
     * Custom action serverless function mocha-create functioName
     */

    _runAction(evt) {
      return new BbPromise(function(resolve, reject) {
          let funcName = evt.options.paths;
          let mocha = new Mocha();
          getFilePaths(evt.options.paths)
          .then(function(paths) {
              paths.forEach(function(path,idx) {
                  mocha.addFile(path);
              })
              SetEnvVars();
              mocha.run();
              UnsetEnvVars();
          }, function(error) {
              return reject(error);
          });
      });
    }
    /**
     * Hook for creating the mocha test placeholder after function creation
     */

    _hookPostFuncCreate(evt) {
      // TODO: only run with runtime node4.3
      if (evt.options.runtime != 'nodejs4.3') {
        console.log(evt.options.runtime);
        return;
      }
      return createTest(evt.options.path);
    }
  }

  //Set environment variables
  function SetEnvVars() {
    var envVars = S.classes.Function.environment
    for (var key in Object.keys(envVars)) {
      process.env[key] = envVars[key];
    }
  }

  //Unset environment variables
  function UnsetEnvVars() {
    var envVars = S.classes.Function.environment
    for (var key in Object.keys(envVars)) {
      delete process.env[key];
    }
  }

  // Create the test folder
  function createTestFolder() {
      return new BbPromise(function(resolve, reject) {

        fs.exists(testFolder, function(exists) {
            if (exists) {
                return resolve(testFolder);
            }
            fs.mkdir(testFolder, function(err) {
                if (err) {
                    return reject(err);
                }
                return resolve(testFolder);
            })
        })
      });
  }

  // Create the test file (and test folder)

  function createTest(funcName) {
    return createTestFolder().then(function(testFolder) {
      return new BbPromise(function(resolve, reject) {
        let funcFilePath = testFilePath(funcName);

        fs.exists(funcFilePath, function (exists) {
           if (exists) {
               return reject(new Error(`File ${funcFilePath} already exists`));
           }
           fs.writeFile(funcFilePath, newTestFile(funcName), function(err) {
               if (err) {
                   return reject(new Error(`Creating file ${funcFilePath} failed: ${err}`));
               }
               console.log(`serverless-mocha-plugin: created ${funcFilePath}`);
               return resolve(funcFilePath);
           })
        });
      });
    });
  }

  // getTestFiles. If no functions provided, returns all files
  function getFilePaths(funcs) {
    return new BbPromise(function(resolve, reject) {
        var paths = [];

        if (funcs && (funcs.length > 0)) {
            funcs.forEach(function(val, idx) {
                paths.push(testFilePath(val));
            });
            return resolve(paths);
        }
        // No funcs provided, list all test files
        fs.readdirSync(testFolder).filter(function(file){
          // Only keep the .js files
          return file.substr(-3) === '.js';
        }).forEach(function(file) {
            paths.push(path.join(testFolder, file));
        });
        return resolve(paths);
    });
  };

  // Returns the path to a function's test file
  function testFilePath(funcName) {
      return path.join(testFolder, `${funcName.replace('/', '_')}.js`);
  }

  function newTestFile(funcName) {
      return `// tests for ${funcName}
// Generated by serverless-mocha-plugin

var mod = require('../${funcName}/handler.js');
var mochaPlugin = require('serverless-mocha-plugin');
var wrapper = mochaPlugin.lambdaWrapper;
var expect = mochaPlugin.chai.expect;

wrapper.init(mod);

describe('${funcName}', function() {
  it('implement tests here', function(done) {
    wrapper.run({}, function(err, response) {
      done('no tests implemented');
    });
  });
});
`;

  }
  // Export Plugin Class
  return PluginBoilerplate;
};

module.exports.lambdaWrapper = lambdaWrapper;
module.exports.chai = chai
<commit_msg>Added environment variables being set and unset before and after each mocha test<commit_after>'use strict';

/**
 * serverless-mocha-plugin
 * - a plugin for TDD with serverless
 */

const path  = require('path'),
  fs        = require('fs'),
  lambdaWrapper = require('lambda-wrapper'),
  Mocha = require('mocha'),
  chai = require('chai'),
  BbPromise = require('bluebird'); // Serverless uses Bluebird Promises and we recommend you do to because they provide more than your average Promise :)

const testFolder = 'test'; // Folder used my mocha for tests

module.exports = function(S) { // Always pass in the ServerlessPlugin Class

  /**
   * Adding/Manipulating Serverless classes
   * - You can add or manipulate Serverless classes like this
   */

  S.classes.Project.newStaticMethod     = function() { console.log("A new method!"); };
  S.classes.Project.prototype.newMethod = function() { S.classes.Project.newStaticMethod(); };

  /**
   * Extending the Plugin Class
   * - Here is how you can add custom Actions and Hooks to Serverless.
   * - This class is only required if you want to add Actions and Hooks.
   */

  class PluginBoilerplate extends S.classes.Plugin {

    /**
     * Constructor
     * - Keep this and don't touch it unless you know what you're doing.
     */

    constructor() {
      super();
      this.name = 'myPlugin'; // Define your plugin's name
    }

    /**
     * Register Actions
     * - function mocha-create
     */

    registerActions() {

      S.addAction(this._createAction.bind(this), {
        handler:       'customAction',
        description:   'Create mocha test for function',
        context:       'function',
        contextAction: 'mocha-create',
        options:       [{ // These must be specified in the CLI like this "-option true" or "-o true"
        }],
        parameters: [ // Use paths when you multiple values need to be input (like an array).  Input looks like this: "serverless custom run module1/function1 module1/function2 module1/function3.  Serverless will automatically turn this into an array and attach it to evt.options within your plugin
          {
            parameter: 'paths',
            description: 'Path to function to test. If not defined, test all functions.',
            position: '0->' // Can be: 0, 0-2, 0->  This tells Serverless which params are which.  3-> Means that number and infinite values after it.
          }
        ]
      });

      S.addAction(this._runAction.bind(this), {
        handler:       'customAction',
        description:   'Create mocha test for function',
        context:       'function',
        contextAction: 'mocha-run',
        options:       [{ // These must be specified in the CLI like this "-option true" or "-o true"
        }],
        parameters: [ // Use paths when you multiple values need to be input (like an array).  Input looks like this: "serverless custom run module1/function1 module1/function2 module1/function3.  Serverless will automatically turn this into an array and attach it to evt.options within your plugin
          {
            parameter: 'paths',
            description: 'Path to function to test. If not defined, test all functions.',
            position: '0->' // Can be: 0, 0-2, 0->  This tells Serverless which params are which.  3-> Means that number and infinite values after it.
          }
        ]
      });

      return BbPromise.resolve();
    }

    /**
     * Register Hooks
     * -  function create (post) creates mocha test file
     */

    registerHooks() {
      S.addHook(this._hookPostFuncCreate.bind(this), {
        action: 'functionCreate',
        event:  'post'
      });

      return BbPromise.resolve();
    }

    /**
     * Custom action serverless function mocha-create functioName
     */

    _createAction(evt) {
      return createTest(evt.options.paths[0]);
    }

    /**
     * Custom action serverless function mocha-create functioName
     */

    _runAction(evt) {
      return new BbPromise(function(resolve, reject) {
          let funcName = evt.options.paths;
          let mocha = new Mocha();
          getFilePaths(evt.options.paths)
          .then(function(paths) {
              paths.forEach(function(path,idx) {
                SetEnvVars(path);
                mocha.addFile(path);
              })
              mocha.run();
              paths.forEach(function(path,idx) {
                UnsetEnvVars(path);
              });
          }, function(error) {
            getFilePaths(evt.options.paths)
            .then(function(paths) {
              paths.forEach(function(path,idx) {
                UnsetEnvVars(path);
              });
            });

            return reject(error);
          });
      });
    }
    /**
     * Hook for creating the mocha test placeholder after function creation
     */

    _hookPostFuncCreate(evt) {
      // TODO: only run with runtime node4.3
      if (evt.options.runtime != 'nodejs4.3') {
        console.log(evt.options.runtime);
        return;
      }
      return createTest(evt.options.path);
    }
  }

  //Set environment variables
  function SetEnvVars(path) {
    var func = new S.classes.Function(null, path);
    var envVars = func.environment
    for (var key in Object.keys(envVars)) {
      process.env[key] = envVars[key];
    }
  }

  //Unset environment variables
  function UnsetEnvVars(path) {
      var func = new S.classes.Function(null, path);
      var envVars = func.environment
      for (var key in Object.keys(envVars)) {
        delete process.env[key];
      }
  }

  // Create the test folder
  function createTestFolder() {
      return new BbPromise(function(resolve, reject) {

        fs.exists(testFolder, function(exists) {
            if (exists) {
                return resolve(testFolder);
            }
            fs.mkdir(testFolder, function(err) {
                if (err) {
                    return reject(err);
                }
                return resolve(testFolder);
            })
        })
      });
  }

  // Create the test file (and test folder)

  function createTest(funcName) {
    return createTestFolder().then(function(testFolder) {
      return new BbPromise(function(resolve, reject) {
        let funcFilePath = testFilePath(funcName);

        fs.exists(funcFilePath, function (exists) {
           if (exists) {
               return reject(new Error(`File ${funcFilePath} already exists`));
           }
           fs.writeFile(funcFilePath, newTestFile(funcName), function(err) {
               if (err) {
                   return reject(new Error(`Creating file ${funcFilePath} failed: ${err}`));
               }
               console.log(`serverless-mocha-plugin: created ${funcFilePath}`);
               return resolve(funcFilePath);
           })
        });
      });
    });
  }

  // getTestFiles. If no functions provided, returns all files
  function getFilePaths(funcs) {
    return new BbPromise(function(resolve, reject) {
        var paths = [];

        if (funcs && (funcs.length > 0)) {
            funcs.forEach(function(val, idx) {
                paths.push(testFilePath(val));
            });
            return resolve(paths);
        }
        // No funcs provided, list all test files
        fs.readdirSync(testFolder).filter(function(file){
          // Only keep the .js files
          return file.substr(-3) === '.js';
        }).forEach(function(file) {
            paths.push(path.join(testFolder, file));
        });
        return resolve(paths);
    });
  };

  // Returns the path to a function's test file
  function testFilePath(funcName) {
      return path.join(testFolder, `${funcName.replace('/', '_')}.js`);
  }

  function newTestFile(funcName) {
      return `// tests for ${funcName}
// Generated by serverless-mocha-plugin

var mod = require('../${funcName}/handler.js');
var mochaPlugin = require('serverless-mocha-plugin');
var wrapper = mochaPlugin.lambdaWrapper;
var expect = mochaPlugin.chai.expect;

wrapper.init(mod);

describe('${funcName}', function() {
  it('implement tests here', function(done) {
    wrapper.run({}, function(err, response) {
      done('no tests implemented');
    });
  });
});
`;

  }
  // Export Plugin Class
  return PluginBoilerplate;
};

module.exports.lambdaWrapper = lambdaWrapper;
module.exports.chai = chai
<|endoftext|>


<commit_before>'use strict';
var spawn = require('child_process').spawn;
var path = require('path');
var format = require('util').format;
var Configstore = require('configstore');
var chalk = require('chalk');
var semverDiff = require('semver-diff');
var latestVersion = require('latest-version');
var isNpm = require('is-npm');
var boxen = require('boxen');
var xdgBasedir = require('xdg-basedir');
var ansiAlign = require('ansi-align');
var ONE_DAY = 1000 * 60 * 60 * 24;

function UpdateNotifier(options) {
	this.options = options = options || {};
	options.pkg = options.pkg || {};

	// reduce pkg to the essential keys. with fallback to deprecated options
	// TODO: remove deprecated options at some point far into the future
	options.pkg = {
		name: options.pkg.name || options.packageName,
		version: options.pkg.version || options.packageVersion
	};

	if (!options.pkg.name || !options.pkg.version) {
		throw new Error('pkg.name and pkg.version required');
	}

	this.packageName = options.pkg.name;
	this.packageVersion = options.pkg.version;
	this.updateCheckInterval = typeof options.updateCheckInterval === 'number' ? options.updateCheckInterval : ONE_DAY;
	this.hasCallback = typeof options.callback === 'function';
	this.callback = options.callback || function () {};

	if (!this.hasCallback) {
		try {
			this.config = new Configstore('update-notifier-' + this.packageName, {
				optOut: false,
				// init with the current time so the first check is only
				// after the set interval, so not to bother users right away
				lastUpdateCheck: Date.now()
			});
		} catch (_) {
			// expecting error code EACCES or EPERM
			process.on('exit', function () {
				var msg = [chalk.yellow(format(' %s update check failed ', options.pkg.name))];
				msg.push(format(' Try running with %s or get access ', chalk.cyan('sudo')));
				msg.push(' to the local update config store via ');
				msg.push(chalk.cyan(format(' sudo chown -R $USER:$(id -gn $USER) %s ', xdgBasedir.config)));
				console.error('\n' + boxen(ansiAlign.center(msg).join('\n')));
			});
		}
	}
}

UpdateNotifier.prototype.check = function () {
	if (this.hasCallback) {
		this.checkNpm().then(this.callback.bind(this, null)).catch(this.callback);
		return;
	}

	if (
		!this.config ||
		this.config.get('optOut') ||
		'NO_UPDATE_NOTIFIER' in process.env ||
		process.argv.indexOf('--no-update-notifier') !== -1
	) {
		return;
	}

	this.update = this.config.get('update');

	if (this.update) {
		this.config.del('update');
	}

	// Only check for updates on a set interval
	if (Date.now() - this.config.get('lastUpdateCheck') < this.updateCheckInterval) {
		return;
	}

	// Spawn a detached process, passing the options as an environment property
	spawn(process.execPath, [path.join(__dirname, 'check.js'), JSON.stringify(this.options)], {
		detached: true,
		stdio: 'ignore'
	}).unref();
};

UpdateNotifier.prototype.checkNpm = function () {
	return latestVersion(this.packageName).then(function (latestVersion) {
		return {
			latest: latestVersion,
			current: this.packageVersion,
			type: semverDiff(this.packageVersion, latestVersion) || 'latest',
			name: this.packageName
		};
	}.bind(this));
};

UpdateNotifier.prototype.notify = function (opts) {
	if (!process.stdout.isTTY || isNpm || !this.update) {
		return this;
	}

	opts = opts || {};

	var message = '\n' + boxen('Update available ' + chalk.dim(this.update.current) + chalk.reset(' → ') + chalk.green(this.update.latest) + ' \nRun ' + chalk.cyan('npm i -g ' + this.packageName) + ' to update', {
		padding: 1,
		margin: 1,
		borderColor: 'yellow',
		borderStyle: 'round'
	});

	if (opts.defer === undefined) {
		process.on('exit', function () {
			console.error(message);
		});
	} else {
		console.error(message);
	}

	return this;
};

module.exports = function (options) {
	var updateNotifier = new UpdateNotifier(options);
	updateNotifier.check();
	return updateNotifier;
};

module.exports.UpdateNotifier = UpdateNotifier;
<commit_msg>show message on sigint as well as exit (#75)<commit_after>'use strict';
var spawn = require('child_process').spawn;
var path = require('path');
var format = require('util').format;
var Configstore = require('configstore');
var chalk = require('chalk');
var semverDiff = require('semver-diff');
var latestVersion = require('latest-version');
var isNpm = require('is-npm');
var boxen = require('boxen');
var xdgBasedir = require('xdg-basedir');
var ansiAlign = require('ansi-align');
var ONE_DAY = 1000 * 60 * 60 * 24;

function UpdateNotifier(options) {
	this.options = options = options || {};
	options.pkg = options.pkg || {};

	// reduce pkg to the essential keys. with fallback to deprecated options
	// TODO: remove deprecated options at some point far into the future
	options.pkg = {
		name: options.pkg.name || options.packageName,
		version: options.pkg.version || options.packageVersion
	};

	if (!options.pkg.name || !options.pkg.version) {
		throw new Error('pkg.name and pkg.version required');
	}

	this.packageName = options.pkg.name;
	this.packageVersion = options.pkg.version;
	this.updateCheckInterval = typeof options.updateCheckInterval === 'number' ? options.updateCheckInterval : ONE_DAY;
	this.hasCallback = typeof options.callback === 'function';
	this.callback = options.callback || function () {};

	if (!this.hasCallback) {
		try {
			this.config = new Configstore('update-notifier-' + this.packageName, {
				optOut: false,
				// init with the current time so the first check is only
				// after the set interval, so not to bother users right away
				lastUpdateCheck: Date.now()
			});
		} catch (_) {
			// expecting error code EACCES or EPERM
			process.on('exit', function () {
				var msg = [chalk.yellow(format(' %s update check failed ', options.pkg.name))];
				msg.push(format(' Try running with %s or get access ', chalk.cyan('sudo')));
				msg.push(' to the local update config store via ');
				msg.push(chalk.cyan(format(' sudo chown -R $USER:$(id -gn $USER) %s ', xdgBasedir.config)));
				console.error('\n' + boxen(ansiAlign.center(msg).join('\n')));
			});
		}
	}
}

UpdateNotifier.prototype.check = function () {
	if (this.hasCallback) {
		this.checkNpm().then(this.callback.bind(this, null)).catch(this.callback);
		return;
	}

	if (
		!this.config ||
		this.config.get('optOut') ||
		'NO_UPDATE_NOTIFIER' in process.env ||
		process.argv.indexOf('--no-update-notifier') !== -1
	) {
		return;
	}

	this.update = this.config.get('update');

	if (this.update) {
		this.config.del('update');
	}

	// Only check for updates on a set interval
	if (Date.now() - this.config.get('lastUpdateCheck') < this.updateCheckInterval) {
		return;
	}

	// Spawn a detached process, passing the options as an environment property
	spawn(process.execPath, [path.join(__dirname, 'check.js'), JSON.stringify(this.options)], {
		detached: true,
		stdio: 'ignore'
	}).unref();
};

UpdateNotifier.prototype.checkNpm = function () {
	return latestVersion(this.packageName).then(function (latestVersion) {
		return {
			latest: latestVersion,
			current: this.packageVersion,
			type: semverDiff(this.packageVersion, latestVersion) || 'latest',
			name: this.packageName
		};
	}.bind(this));
};

UpdateNotifier.prototype.notify = function (opts) {
	if (!process.stdout.isTTY || isNpm || !this.update) {
		return this;
	}

	opts = opts || {};

	var message = '\n' + boxen('Update available ' + chalk.dim(this.update.current) + chalk.reset(' → ') + chalk.green(this.update.latest) + ' \nRun ' + chalk.cyan('npm i -g ' + this.packageName) + ' to update', {
		padding: 1,
		margin: 1,
		borderColor: 'yellow',
		borderStyle: 'round'
	});

	if (opts.defer === undefined) {
		process.on('exit', function () {
			console.error(message);
		});

		process.on('SIGINT', function () {
			console.error('\n' + message);
		});
	} else {
		console.error(message);
	}

	return this;
};

module.exports = function (options) {
	var updateNotifier = new UpdateNotifier(options);
	updateNotifier.check();
	return updateNotifier;
};

module.exports.UpdateNotifier = UpdateNotifier;
<|endoftext|>


<commit_before>/**
 * @file gulpfile.js
 *
 * Defines tasks that can be run on gulp.
 *
 * Summary:

 *
 `test` - runs all the tests on node and the browser (mocha and karma)
 *

 *
 `test:node`
 *
 `test:node:nofail` - internally used for watching (due to bug on gulp-mocha)
 *
 `test:browser`
 *
`
 *
 `watch:test` - watch for file changes and run tests
 *

 *
 `watch:test:node`
 *
 `watch:test:browser`
 *
`
 *
 `browser` - generate files needed for browser (browserify)
 *

 *
 `browser:uncompressed` - build uncomprssed browser bundle (`bitcore-*.js`)
 *
 `browser:compressed` - build compressed browser bundle (`bitcore-*.min.js`)
 *
 `browser:maketests` - build `tests.js`, needed for testing without karma
 *
`
 *
 `lint` - run `jshint`
 *
 `coverage` - run `istanbul` with mocha to generate a report of test coverage
 *
 `coveralls` - updates coveralls info
 *
 `release` - automates release process (only for maintainers)
 *

 */
'use strict';

var gulp = require('gulp');

var coveralls = require('gulp-coveralls');
var gutil = require('gulp-util');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var runsequence = require('run-sequence');
runsequence.use(gulp);
var shell = require('gulp-shell');
var uglify = require('gulp-uglify');
var bump = require('gulp-bump');
var git = require('gulp-git');

function ignoreerror() {
  /* jshint ignore:start */ // using `this` in this context is weird
  this.emit('end');
  /* jshint ignore:end */
}

function startGulp(name, opts) {

  opts = opts || {};
  var browser = !opts.skipBrowser;
  var isSubmodule = name ? true : false;
  var fullname = name ? 'bitcore-' + name : 'bitcore';
  var files = ['lib/**/*.js'];
  var tests = ['test/**/*.js'];
  var alljs = files.concat(tests);

  var buildPath = './node_modules/bitcore-build/';
  var buildModulesPath = buildPath + 'node_modules/';
  var buildBinPath = buildPath + 'node_modules/.bin/';

  /**
   * testing
   */
  var testmocha = function() {
    return gulp.src(tests).pipe(new mocha({
      reporter: 'spec'
    }));
  };

  var testkarma = shell.task([
    buildModulesPath + 'karma/bin/karma start ' + buildPath + 'karma.conf.js'
  ]);

  gulp.task('test:node', testmocha);

  gulp.task('test:node:nofail', function() {
    return testmocha().on('error', ignoreerror);
  });

  gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testkarma);

  if (browser) {
    gulp.task('test', function(callback) {
      runsequence(['test:node'], ['test:browser'], callback);
    });
  } else {
    gulp.task('test', ['test:node']);
  }

  gulp.task('noop', function() {
  });

  /**
   * file generation
   */
  if (browser) {

    var browserifyCommand;

    if (isSubmodule) {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:' + fullname + ' --external bitcore -o ' + fullname + '.js';
    } else {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:bitcore -o bitcore.js';
    }

    gulp.task('browser:uncompressed', shell.task([
      browserifyCommand
    ]));

    gulp.task('browser:compressed', ['browser:uncompressed'], function() {
      return gulp.src(fullname + '.js')
        .pipe(uglify({
          mangle: true,
          compress: true
        }))
        .pipe(rename(fullname + '.min.js'))
        .pipe(gulp.dest('.'))
        .on('error', gutil.log);
    });

    gulp.task('browser:maketests', shell.task([
      'find test/ -type f -name "*.js" | xargs ' + buildBinPath + 'browserify -t brfs -o tests.js'
    ]));

    gulp.task('browser', function(callback) {
      runsequence(['browser:compressed'], callback);
    });
  }

  /**
   * code quality and documentation
   */

  gulp.task('lint', function() {
    return gulp.src(alljs)
      .pipe(jshint())
      .pipe(jshint.reporter('default'));
  });

  gulp.task('plato', shell.task([buildBinPath + 'plato -d report -r -l .jshintrc -t ' + fullname + ' lib']));

  gulp.task('coverage', shell.task([buildBinPath + './istanbul cover ' + buildBinPath + '_mocha -- --recursive']));

  gulp.task('coveralls', ['coverage'], function() {
    gulp.src('coverage/lcov.info').pipe(coveralls());
  });

  /**
   * watch tasks
   */

  gulp.task('watch:test', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test']);
  });

  gulp.task('watch:test:node', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test:node']);
  });

  if (browser) {
    gulp.task('watch:test:browser', function() {
      // todo: only run tests that are linked to file changes by doing
      // something smart like reading through the require statements
      return gulp.watch(alljs, ['test:browser']);
    });
  }

  gulp.task('watch:coverage', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['coverage']);
  });

  gulp.task('watch:lint', function() {
    // todo: only lint files that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['lint']);
  });

  if (browser) {
    gulp.task('watch:browser', function() {
      return gulp.watch(alljs, ['browser']);
    });
  }

  /**
   * Release automation
   */

  gulp.task('release:install', function() {
    return shell.task([
      'npm install',
    ]);
  });

  var releaseFiles = ['./package.json'];
  if (browser) {
    releaseFiles.push('./bower.json');
  }

  var bump_version = function(importance) {
    return gulp.src(releaseFiles)
      .pipe(bump({
        type: importance
      }))
      .pipe(gulp.dest('./'));
  };

  gulp.task('release:checkout-releases', function(cb) {
    var tempBranch = 'releases/' + new Date().getTime() + '-build';
    git.branch(tempBranch, {
      args: ''
    }, function() {
      git.checkout(tempBranch, {
        args: ''
      }, cb);
    });
  });

  gulp.task('release:checkout-master', function(cb) {
    git.checkout('master', {
      args: ''
    }, cb);
  });

  gulp.task('release:sign-built-files', shell.task([
    'gpg --yes --out ' + fullname + '.js.sig --detach-sig ' + fullname + '.js',
    'gpg --yes --out ' + fullname + '.min.js.sig --detach-sig ' + fullname + '.min.js'
  ]));

  var buildFiles = ['./package.json'];
  var signatureFiles = [];
  if (browser) {
    buildFiles.push(fullname + '.js');
    buildFiles.push(fullname + '.js.sig');
    buildFiles.push(fullname + '.min.js');
    buildFiles.push(fullname + '.min.js.sig');

    buildFiles.push('./bower.json');

    signatureFiles.push(fullname + '.js.sig');
    signatureFiles.push(fullname + '.min.js.sig');
  }
  var addFiles = function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.add({
        args: '-f'
      }));
  };

  var buildCommit = function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.commit('Build: ' + pjson.version, {
        args: ''
      }));
  };

  gulp.task('release:add-signed-files', ['release:sign-built-files'], addFiles);
  gulp.task('release:add-built-files', addFiles);

  if (browser) {
    gulp.task('release:build-commit', [
      'release:add-signed-files'
    ], buildCommit);
  } else {
    gulp.task('release:build-commit', [
      'release:add-built-files'
    ], buildCommit);
  }

  gulp.task('release:version-commit', function() {
    var pjson = require('../../package.json');
    return gulp.src(releaseFiles)
      .pipe(git.commit('Bump package version to ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:push', function(cb) {
    git.push('bitpay', 'master', {
      args: ''
    }, cb);
  });

  gulp.task('release:push-tag', function(cb) {
    var pjson = require('../../package.json');
    var name = 'v' + pjson.version;
    git.tag(name, 'Release ' + name, function() {
      git.push('bitpay', name, cb);
    });
  });

  gulp.task('release:publish', shell.task([
    'npm publish'
  ]));

  // requires https://hub.github.com/
  var release = function(importance, cb) {
    var bumper = 'release:bump:' + importance;
    return runsequence(
      // Checkout the release temporal branch
      'release:checkout-releases',
      // Run npm install
      'release:install',
      // Run tests with gulp test
      'test',
      // Update package.json and bower.json
      bumper,
      // build browser files
      browser ? 'browser' : 'noop',
      // Commit
      'release:build-commit',
      // Run git push bitpay $VERSION
      'release:push-tag',
      // Run npm publish
      'release:publish',
      // Checkout the `master` branch
      'release:checkout-master',
      // Bump package.json and bower.json, again
      bumper,
      // Version commit with no binary files to master
      'release:version-commit',
      // Push to master
      'release:push',
      cb);
  };

  ['patch', 'minor', 'major'].forEach(function(importance) {
    gulp.task('release:' + importance, function(cb) {
      release(importance, cb);
    });
    gulp.task('release:bump:' + importance, function() {
      bump_version(importance);
    });
  });
  gulp.task('release', ['release:patch']);

}

module.exports = startGulp;
<commit_msg>remove release branch after release<commit_after>/**
 * @file gulpfile.js
 *
 * Defines tasks that can be run on gulp.
 *
 * Summary:

 *
 `test` - runs all the tests on node and the browser (mocha and karma)
 *

 *
 `test:node`
 *
 `test:node:nofail` - internally used for watching (due to bug on gulp-mocha)
 *
 `test:browser`
 *
`
 *
 `watch:test` - watch for file changes and run tests
 *

 *
 `watch:test:node`
 *
 `watch:test:browser`
 *
`
 *
 `browser` - generate files needed for browser (browserify)
 *

 *
 `browser:uncompressed` - build uncomprssed browser bundle (`bitcore-*.js`)
 *
 `browser:compressed` - build compressed browser bundle (`bitcore-*.min.js`)
 *
 `browser:maketests` - build `tests.js`, needed for testing without karma
 *
`
 *
 `lint` - run `jshint`
 *
 `coverage` - run `istanbul` with mocha to generate a report of test coverage
 *
 `coveralls` - updates coveralls info
 *
 `release` - automates release process (only for maintainers)
 *

 */
'use strict';

var gulp = require('gulp');

var coveralls = require('gulp-coveralls');
var gutil = require('gulp-util');
var jshint = require('gulp-jshint');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var runsequence = require('run-sequence');
runsequence.use(gulp);
var shell = require('gulp-shell');
var uglify = require('gulp-uglify');
var bump = require('gulp-bump');
var git = require('gulp-git');

function ignoreerror() {
  /* jshint ignore:start */ // using `this` in this context is weird
  this.emit('end');
  /* jshint ignore:end */
}

function startGulp(name, opts) {

  opts = opts || {};
  var browser = !opts.skipBrowser;
  var isSubmodule = name ? true : false;
  var fullname = name ? 'bitcore-' + name : 'bitcore';
  var files = ['lib/**/*.js'];
  var tests = ['test/**/*.js'];
  var alljs = files.concat(tests);

  var buildPath = './node_modules/bitcore-build/';
  var buildModulesPath = buildPath + 'node_modules/';
  var buildBinPath = buildPath + 'node_modules/.bin/';

  /**
   * testing
   */
  var testmocha = function() {
    return gulp.src(tests).pipe(new mocha({
      reporter: 'spec'
    }));
  };

  var testkarma = shell.task([
    buildModulesPath + 'karma/bin/karma start ' + buildPath + 'karma.conf.js'
  ]);

  gulp.task('test:node', testmocha);

  gulp.task('test:node:nofail', function() {
    return testmocha().on('error', ignoreerror);
  });

  gulp.task('test:browser', ['browser:uncompressed', 'browser:maketests'], testkarma);

  if (browser) {
    gulp.task('test', function(callback) {
      runsequence(['test:node'], ['test:browser'], callback);
    });
  } else {
    gulp.task('test', ['test:node']);
  }

  gulp.task('noop', function() {
  });

  /**
   * file generation
   */
  if (browser) {

    var browserifyCommand;

    if (isSubmodule) {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:' + fullname + ' --external bitcore -o ' + fullname + '.js';
    } else {
      browserifyCommand = buildBinPath + 'browserify --require ./index.js:bitcore -o bitcore.js';
    }

    gulp.task('browser:uncompressed', shell.task([
      browserifyCommand
    ]));

    gulp.task('browser:compressed', ['browser:uncompressed'], function() {
      return gulp.src(fullname + '.js')
        .pipe(uglify({
          mangle: true,
          compress: true
        }))
        .pipe(rename(fullname + '.min.js'))
        .pipe(gulp.dest('.'))
        .on('error', gutil.log);
    });

    gulp.task('browser:maketests', shell.task([
      'find test/ -type f -name "*.js" | xargs ' + buildBinPath + 'browserify -t brfs -o tests.js'
    ]));

    gulp.task('browser', function(callback) {
      runsequence(['browser:compressed'], callback);
    });
  }

  /**
   * code quality and documentation
   */

  gulp.task('lint', function() {
    return gulp.src(alljs)
      .pipe(jshint())
      .pipe(jshint.reporter('default'));
  });

  gulp.task('plato', shell.task([buildBinPath + 'plato -d report -r -l .jshintrc -t ' + fullname + ' lib']));

  gulp.task('coverage', shell.task([buildBinPath + './istanbul cover ' + buildBinPath + '_mocha -- --recursive']));

  gulp.task('coveralls', ['coverage'], function() {
    gulp.src('coverage/lcov.info').pipe(coveralls());
  });

  /**
   * watch tasks
   */

  gulp.task('watch:test', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test']);
  });

  gulp.task('watch:test:node', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['test:node']);
  });

  if (browser) {
    gulp.task('watch:test:browser', function() {
      // todo: only run tests that are linked to file changes by doing
      // something smart like reading through the require statements
      return gulp.watch(alljs, ['test:browser']);
    });
  }

  gulp.task('watch:coverage', function() {
    // todo: only run tests that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['coverage']);
  });

  gulp.task('watch:lint', function() {
    // todo: only lint files that are linked to file changes by doing
    // something smart like reading through the require statements
    return gulp.watch(alljs, ['lint']);
  });

  if (browser) {
    gulp.task('watch:browser', function() {
      return gulp.watch(alljs, ['browser']);
    });
  }

  /**
   * Release automation
   */

  gulp.task('release:install', function() {
    return shell.task([
      'npm install',
    ]);
  });

  var releaseFiles = ['./package.json'];
  if (browser) {
    releaseFiles.push('./bower.json');
  }

  var bump_version = function(importance) {
    return gulp.src(releaseFiles)
      .pipe(bump({
        type: importance
      }))
      .pipe(gulp.dest('./'));
  };

  var tempBranch = 'releases/' + new Date().getTime() + '-build';
  gulp.task('release:checkout-releases', function(cb) {
    git.branch(tempBranch, {
      args: ''
    }, function() {
      git.checkout(tempBranch, {
        args: ''
      }, cb);
    });
  });

  gulp.task('release:cleanup', function(cb) {
    git.branch(tempBranch, {
      args: '-D'
    }, cb);
  });

  gulp.task('release:checkout-master', function(cb) {
    git.checkout('master', {
      args: ''
    }, cb);
  });

  gulp.task('release:sign-built-files', shell.task([
    'gpg --yes --out ' + fullname + '.js.sig --detach-sig ' + fullname + '.js',
    'gpg --yes --out ' + fullname + '.min.js.sig --detach-sig ' + fullname + '.min.js'
  ]));

  var buildFiles = ['./package.json'];
  var signatureFiles = [];
  if (browser) {
    buildFiles.push(fullname + '.js');
    buildFiles.push(fullname + '.js.sig');
    buildFiles.push(fullname + '.min.js');
    buildFiles.push(fullname + '.min.js.sig');

    buildFiles.push('./bower.json');

    signatureFiles.push(fullname + '.js.sig');
    signatureFiles.push(fullname + '.min.js.sig');
  }
  var addFiles = function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.add({
        args: '-f'
      }));
  };

  var buildCommit = function() {
    var pjson = require('../../package.json');
    return gulp.src(buildFiles)
      .pipe(git.commit('Build: ' + pjson.version, {
        args: ''
      }));
  };

  gulp.task('release:add-signed-files', ['release:sign-built-files'], addFiles);
  gulp.task('release:add-built-files', addFiles);

  if (browser) {
    gulp.task('release:build-commit', [
      'release:add-signed-files'
    ], buildCommit);
  } else {
    gulp.task('release:build-commit', [
      'release:add-built-files'
    ], buildCommit);
  }

  gulp.task('release:version-commit', function() {
    var pjson = require('../../package.json');
    return gulp.src(releaseFiles)
      .pipe(git.commit('Bump package version to ' + pjson.version, {
        args: ''
      }));
  });

  gulp.task('release:push', function(cb) {
    git.push('bitpay', 'master', {
      args: ''
    }, cb);
  });

  gulp.task('release:push-tag', function(cb) {
    var pjson = require('../../package.json');
    var name = 'v' + pjson.version;
    git.tag(name, 'Release ' + name, function() {
      git.push('bitpay', name, cb);
    });
  });

  gulp.task('release:publish', shell.task([
    'npm publish'
  ]));

  // requires https://hub.github.com/
  var release = function(importance, cb) {
    var bumper = 'release:bump:' + importance;
    return runsequence(
      // Checkout the release temporal branch
      'release:checkout-releases',
      // Run npm install
      'release:install',
      // Run tests with gulp test
      'test',
      // Update package.json and bower.json
      bumper,
      // build browser files
      browser ? 'browser' : 'noop',
      // Commit
      'release:build-commit',
      // Run git push bitpay $VERSION
      'release:push-tag',
      // Run npm publish
      'release:publish',
      // Checkout the `master` branch
      'release:checkout-master',
      // Bump package.json and bower.json, again
      bumper,
      // Version commit with no binary files to master
      'release:version-commit',
      // Push to master
      'release:push',
      // remove release branch
      'release:cleanup',
      cb);
  };

  ['patch', 'minor', 'major'].forEach(function(importance) {
    gulp.task('release:' + importance, function(cb) {
      release(importance, cb);
    });
    gulp.task('release:bump:' + importance, function() {
      bump_version(importance);
    });
  });
  gulp.task('release', ['release:patch']);

}

module.exports = startGulp;
<|endoftext|>


<commit_before>// Setting up required files the bot will need
//	* Some are required only for specific commands
try {
	var AuthDetails = require('./auth.json');
} catch (e){
	console.log("Please create an auth.json file with account email and password"+e.stack);
	process.exit();
}

try {
	var Discord = require('discord.io');
} catch (e){
	console.log("Please run npm install discord.io"+e.stack);
	process.exit();
}

try {
	var d20 = require('d20');
} catch (e){
	console.log("Please run npm install d20"+e.stack);
}

try {
	var Stats = require("./user_stats.json");
} catch (e){
	console.log("Unable to provide stats: Missing file");
}

// Setting up Roles object for future reference
var roles = {};
roles.admin_id = 0;
roles.mod_id = 0;

// Setting up Games object for future reference
var games = {};
games.rolloff = false;

// Start client
var bot = new Discord.Client({
	token: AuthDetails.token,
	autorun: true
});

// Create commands
//	* usage - To be used by !help
//	* description - To be used by !help
//	* process - what gets run when command is called
var commands = {
	"dam": {
		usage: "",
		description: "returns image/gif",
		process: function(channel) {
			var rand = Math.floor(Math.random() * 2) + 1;
			var result;
			if (rand == 1)
				result = 'https://i.imgur.com/7lZwLKc.jpg';
			else
				result = 'https://i.imgur.com/VQLGJOL.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"happy": {
		usage: "",
		description: "returns image/gif",
		process: function(channel) {
			var rand = Math.floor(Math.random() * 2) + 1;
			var result;
			if (rand == 1)
			  result = 'https://i.imgur.com/gbXzYXp.gif';
			else
			  result = 'https://i.imgur.com/OxwIC0O.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"horse": {
		usage: "",
		description: "returns horse gif",
		process: function(channel) {
			var result = 'https://i.giphy.com/S4mOmgmpBQAXm.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	//NEEDS UPDATE
	"zzzimg": {
		usage: "<search term>",
		description: "searches imgur based on keyword",
		process: function(channel, suffix) {
			var key = AuthDetails;
			var Imgur = require('imgur-search');

			var term = suffix;
			if(!term) {
				bot.sendMessage({to: channel, message:"No Search Term"});
				return;
			}
			new Imgur(key.imgur_key).search(term).then(function(result) {
				if (result.length == 0 || result == undefined) {
					bot.sendMessage({to: channel, message:"You suck at searching"});
				} else {
					var img = result[Math.floor(Math.random() * result.length)];
					bot.sendMessage({to: channel, message: img.link});
				}
			});
		}
	},
	"why": {
		usage: "",
		description: "returns gif",
		process: function(channel) {
			var result = 'https://media.giphy.com/media/1M9fmo1WAFVK0/giphy.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"roll": {
		usage: "[#d#]",
		description: "dice roller, with single command giving a d20, otherwise rolling specified combo",
		process: function(channel, suffix) {
			if (games.rolloff){
				var roll_bot;
				var roll_usr;

				roll_bot = d20.roll(20);
				roll_usr = d20.roll(20);
				bot.sendMessage({to: channel, message:"rolled: " + roll_usr});
				setTimeout(function(){
					if (roll_bot > roll_usr)
						bot.sendMessage({to: channel, message:"MUAHAHAHA. My " + roll_bot + " p4wned your " + roll_usr + ". Get rekt."});
					else if (roll_usr > roll_bot)
						bot.sendMessage({to: channel, message:"Lucky roll... My " + roll_bot + " can't beat your " + roll_usr + "."});
					else
						bot.sendMessage({to: channel, message:"Tie? TIE!? Let's call that a win for me..."})
				;},500);

				games.rolloff = false;
			} else {
				if(!suffix) {
					bot.sendMessage({to: channel, message:"rolled: " + d20.roll(20)});
				} else {
					var result;
					try {
						result = d20.roll(suffix);
					} catch (e){
						bot.sendMessage({to: channel, message:"Could not roll " + suffix});
						return;
					}
					if (!isNaN(result) && result != 'NaN')
						bot.sendMessage({to: channel, message:"Rolled: " + d20.verboseRoll(suffix)});
					else
						bot.sendMessage({to: channel, message:"Not a valid number"});
				}
			}
		}
	},
	"rolloff": {
		usage: "",
		description: "Roll off against the bot (D20)",
		process: function(channel) {
			bot.sendMessage({to: channel, message:"A Challenger APPROACHES! Use !roll to compete against me!"});
			games.rolloff = true;
		}
	},
	"blown": {
		usage: "",
		description: "returns gif",
		process: function(channel) {
			var result;
			var rand = Math.floor(Math.random() * 6);
			var gifs = [	'https://i.imgur.com/YGsTG5o.gif',
					'https://i.imgur.com/pBTk7MC.gif',
					'https://i.imgur.com/rfFWukr.gif',
					'https://media.giphy.com/media/OK27wINdQS5YQ/giphy.gif',
					'https://i.imgur.com/l4bJmRE.gif',
					'https://i.imgur.com/3WB3L.gif',
					'https://giphy.com/gifs/cheezburger-robots-screaming-NfEQd1ge1kP04']

			bot.sendMessage({to: channel, message:gifs[rand]});
		}
	},
	"weekend": {
		usage: "",
		description: "returns days until weekend",
		process: function(channel) {
			var date = new Date();
			var day = date.getDay();
			var result = [  "Last day, Enjoy it!",
					"4 Days Left. Got a case of the Mondays?",
					"3 Days Left",
					"2 Days Left.  Hump Day!",
					"1 Day Left",
					"FRIDAY!",
					"Less than 48 hours left..."];

			bot.sendMessage({to: channel, message:result[day]});
		}
	},
	"stats": {
		// members in JSON file need to be lowercase
		usage: "<user>",
		description: "Score for users in chat games",
		process: function(channel, suffix, userID) {
			if (isAdmin(userID)){
				if (suffix){
					var usr = suffix.toLowerCase();
					var score = Stats.members[usr];
					if (score != null)
						bot.sendMessage({to: channel, message: "Score: " + score});
					else
						bot.sendMessage({to: channel, message: "nothing!"});
				} else {
					bot.sendMessage({to: channel, message:"Pong"});
				}
			} else {
				bot.sendMessage({to: channel, message:"For admins only, I'm afraid"});
			}
		}
	}
};

// Load Roles object with needed roles
//	* the propVal checks may need to be updated on role name changes
function loadRoles(){
	for (var r in bot.servers[AuthDetails.server_id].roles){
		var role = bot.servers[AuthDetails.server_id].roles[r];
		var propVal;
		for (var prop in role){
			propVal = role[prop];
			if (prop == 'name' && propVal == 'Admin'){
				roles.admin_id = role['id'];
			}
			if (prop == 'name' && propVal == 'Moderator'){
				roles.mod_id = role['id'];
			}
		}
	}
}

// Compares user's roles and admin_id
function isAdmin(userID){
	var usrRoles = bot.servers[AuthDetails.server_id].members[userID].roles;
	for (var i = 0; i < usrRoles.length; i++){
		if (usrRoles[i] == roles.admin_id)
			return true;
	}
	return false;
}

// Ready trigger
bot.on('ready', function () {
	console.log("Ready to start.");
	try {
		loadRoles();
	} catch (e){
		console.log('Unable to load role IDs'+e.stack);
	}
});

// Disconnect trigger
bot.on('disconnected', function() {
	console.log('Disconnected.');
	process.exit(1);
});

// Message trigger
bot.on('message', function (user, userID, channelID, message, evt) {
	// if message starts with '!', a command has been entered
	if (message.substring(0,1) == '!'){
		var args = message.substring(1).split(' ');
		var cmd = args[0];
		var suffix = args[1];
		var result = commands[cmd];

		if (cmd == 'help'){
			var info = "Available Commands: ";
			for (var cmd in commands){
				info += "!" + cmd;
				var usage = commands[cmd].usage;
				if (usage){
					info += " " + usage + "; ";
				} else {
					info += "; ";
				}
			}
			bot.sendMessage({to: userID, message: info});
		} else if (result){
			try {
				result.process(channelID,suffix,userID);
			} catch (e){
				console.log("Command failed: " + cmd + ". " + e.stack);
			}
		} else {
			bot.sendMessage({to: channelID, message: "Not a command, use !help"});
		}
	}
});<commit_msg>updated help on specific commands, stopped messages from triggering if submitted by bot<commit_after>// Setting up required files the bot will need
//	* Some are required only for specific commands
try {
	var AuthDetails = require('./auth.json');
} catch (e){
	console.log("Please create an auth.json file with account email and password"+e.stack);
	process.exit();
}

try {
	var Discord = require('discord.io');
} catch (e){
	console.log("Please run npm install discord.io"+e.stack);
	process.exit();
}

try {
	var d20 = require('d20');
} catch (e){
	console.log("Please run npm install d20"+e.stack);
}

try {
	var Stats = require("./user_stats.json");
} catch (e){
	console.log("Unable to provide stats: Missing file");
}

// Setting up Roles object for future reference
var roles = {};
roles.admin_id = 0;
roles.mod_id = 0;

// Setting up Games object for future reference
var games = {};
games.rolloff = false;

// Start client
var bot = new Discord.Client({
	token: AuthDetails.token,
	autorun: true
});

// Create commands
//	* usage - To be used by !help
//	* description - To be used by !help
//	* process - what gets run when command is called
var commands = {
	"dam": {
		usage: "",
		description: "returns image/gif",
		process: function(channel) {
			var rand = Math.floor(Math.random() * 2) + 1;
			var result;
			if (rand == 1)
				result = 'https://i.imgur.com/7lZwLKc.jpg';
			else
				result = 'https://i.imgur.com/VQLGJOL.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"happy": {
		usage: "",
		description: "returns image/gif",
		process: function(channel) {
			var rand = Math.floor(Math.random() * 2) + 1;
			var result;
			if (rand == 1)
			  result = 'https://i.imgur.com/gbXzYXp.gif';
			else
			  result = 'https://i.imgur.com/OxwIC0O.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"horse": {
		usage: "",
		description: "returns horse gif",
		process: function(channel) {
			var result = 'https://i.giphy.com/S4mOmgmpBQAXm.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	//NEEDS UPDATE
	"zzzimg": {
		usage: "<search term>",
		description: "searches imgur based on keyword",
		process: function(channel, suffix) {
			var key = AuthDetails;
			var Imgur = require('imgur-search');

			var term = suffix;
			if(!term) {
				bot.sendMessage({to: channel, message:"No Search Term"});
				return;
			}
			new Imgur(key.imgur_key).search(term).then(function(result) {
				if (result.length == 0 || result == undefined) {
					bot.sendMessage({to: channel, message:"You suck at searching"});
				} else {
					var img = result[Math.floor(Math.random() * result.length)];
					bot.sendMessage({to: channel, message: img.link});
				}
			});
		}
	},
	"why": {
		usage: "",
		description: "returns gif",
		process: function(channel) {
			var result = 'https://media.giphy.com/media/1M9fmo1WAFVK0/giphy.gif';
			bot.sendMessage({to: channel, message: result});
		}
	},
	"roll": {
		usage: "[#d#]",
		description: "dice roller, with single command giving a d20, otherwise rolling specified combo",
		process: function(channel, suffix) {
			if (games.rolloff){
				var roll_bot;
				var roll_usr;

				roll_bot = d20.roll(20);
				roll_usr = d20.roll(20);
				bot.sendMessage({to: channel, message:"rolled: " + roll_usr});
				setTimeout(function(){
					if (roll_bot > roll_usr)
						bot.sendMessage({to: channel, message:"MUAHAHAHA. My " + roll_bot + " p4wned your " + roll_usr + ". Get rekt."});
					else if (roll_usr > roll_bot)
						bot.sendMessage({to: channel, message:"Lucky roll... My " + roll_bot + " can't beat your " + roll_usr + "."});
					else
						bot.sendMessage({to: channel, message:"Tie? TIE!? Let's call that a win for me..."})
				;},500);

				games.rolloff = false;
			} else {
				if(!suffix) {
					bot.sendMessage({to: channel, message:"rolled: " + d20.roll(20)});
				} else {
					var result;
					try {
						result = d20.roll(suffix);
					} catch (e){
						bot.sendMessage({to: channel, message:"Could not roll " + suffix});
						return;
					}
					if (!isNaN(result) && result != 'NaN')
						bot.sendMessage({to: channel, message:"Rolled: " + d20.verboseRoll(suffix)});
					else
						bot.sendMessage({to: channel, message:"Not a valid number"});
				}
			}
		}
	},
	"rolloff": {
		usage: "",
		description: "roll off against the bot (D20)",
		process: function(channel) {
			bot.sendMessage({to: channel, message:"A Challenger APPROACHES! Use !roll to compete against me!"});
			games.rolloff = true;
		}
	},
	"blown": {
		usage: "",
		description: "returns gif",
		process: function(channel) {
			var result;
			var rand = Math.floor(Math.random() * 6);
			var gifs = [	'https://i.imgur.com/YGsTG5o.gif',
					'https://i.imgur.com/pBTk7MC.gif',
					'https://i.imgur.com/rfFWukr.gif',
					'https://media.giphy.com/media/OK27wINdQS5YQ/giphy.gif',
					'https://i.imgur.com/l4bJmRE.gif',
					'https://i.imgur.com/3WB3L.gif',
					'https://giphy.com/gifs/cheezburger-robots-screaming-NfEQd1ge1kP04']

			bot.sendMessage({to: channel, message:gifs[rand]});
		}
	},
	"weekend": {
		usage: "",
		description: "returns days until weekend",
		process: function(channel) {
			var date = new Date();
			var day = date.getDay();
			var result = [  "Last day, Enjoy it!",
					"4 Days Left. Got a case of the Mondays?",
					"3 Days Left",
					"2 Days Left.  Hump Day!",
					"1 Day Left",
					"FRIDAY!",
					"Less than 48 hours left..."];

			bot.sendMessage({to: channel, message:result[day]});
		}
	},
	"stats": {
		// members in JSON file need to be lowercase
		usage: "<user>",
		description: "score for users in chat games",
		process: function(channel, suffix, userID) {
			if (isAdmin(userID)){
				if (suffix){
					var usr = suffix.toLowerCase();
					var score = Stats.members[usr];
					if (score != null)
						bot.sendMessage({to: channel, message: "Score: " + score});
					else
						bot.sendMessage({to: channel, message: "nothing!"});
				} else {
					bot.sendMessage({to: channel, message:"Pong"});
				}
			} else {
				bot.sendMessage({to: channel, message:"For admins only, I'm afraid"});
			}
		}
	}
};

// Load Roles object with needed roles
//	* the propVal checks may need to be updated on role name changes
function loadRoles(){
	for (var r in bot.servers[AuthDetails.server_id].roles){
		var role = bot.servers[AuthDetails.server_id].roles[r];
		var propVal;
		for (var prop in role){
			propVal = role[prop];
			if (prop == 'name' && propVal == 'Admin'){
				roles.admin_id = role['id'];
			}
			if (prop == 'name' && propVal == 'Moderator'){
				roles.mod_id = role['id'];
			}
		}
	}
}

// Compares user's roles and admin_id
function isAdmin(userID){
	var usrRoles = bot.servers[AuthDetails.server_id].members[userID].roles;
	for (var i = 0; i < usrRoles.length; i++){
		if (usrRoles[i] == roles.admin_id)
			return true;
	}
	return false;
}

// Ready trigger
bot.on('ready', function () {
	console.log("Ready to start.");
	try {
		loadRoles();
	} catch (e){
		console.log('Unable to load role IDs'+e.stack);
	}
});

// Disconnect trigger
bot.on('disconnected', function() {
	console.log('Disconnected.');
	process.exit(1);
});

// Message trigger
bot.on('message', function (user, userID, channelID, message, evt) {
	// if message starts with '!', a command has been entered
	if (message.substring(0,1) == '!' && userID != bot.id){
		var args = message.substring(1).split(' ');
		var cmd = args[0];
		var suffix = args[1];
		var result = commands[cmd];

		if (cmd == 'help'){
			if (suffix){
				var com = commands[suffix];
				if (com){
					bot.sendMessage({to: userID, message: "!" + suffix + " " + com.usage + " -> " + com.description});
				} else {
					bot.sendMessage({to: userID, message: "No record for " + suffix});
				}
			} else {
				var info = "Available Commands: ";
				for (var cmd in commands){
					info += "!" + cmd;
					var usage = commands[cmd].usage;
					if (usage){
						info += " " + usage + "; ";
					} else {
						info += "; ";
					}
				}
				bot.sendMessage({to: userID, message: info});
			}
		} else if (result){
			try {
				result.process(channelID,suffix,userID);
			} catch (e){
				console.log("Command failed: " + cmd + ". " + e.stack);
			}
		} else {
			bot.sendMessage({to: channelID, message: "Not a command, use !help"});
		}
	}
});<|endoftext|>


<commit_before>const mkdirp = require('mkdirp');
const path = require('path');

function makeConsoleLog(mPath) {
	const path = mPath | process.cwd();
    console.log("Hey!!!")
    console.log("Du befindest dich gerade hier: " + path)
}

function buildWebApp(mPath) {
	const folder = mPath | path.resolve(process.cwd(), './public');
    mkdirp(folder, function (err) {
        if (err) console.error(err)
        else console.log('Created Folder: ' + folder)
    });
}

module.exports = {
    makeConsoleLog: makeConsoleLog,
    buildWebApp: buildWebApp
};<commit_msg>quickfix<commit_after>const mkdirp = require('mkdirp');
const path = require('path');

function makeConsoleLog(mPath) {
	console.log("P: " + mPath);
	const path = mPath | process.cwd();
    console.log("Hey!!!")
    console.log("Du befindest dich gerade hier: " + path)
}

function buildWebApp(mPath) {
	const folder = mPath | path.resolve(process.cwd(), './public');
    mkdirp(folder, function (err) {
        if (err) console.error(err)
        else console.log('Created Folder: ' + folder)
    });
}

module.exports = {
    makeConsoleLog: makeConsoleLog,
    buildWebApp: buildWebApp
};<|endoftext|>


<commit_before>var postcss = require('postcss');

module.exports = postcss.plugin('postcss-remove-nodes', function (opts) {
    opts = opts || {};

    return function (css, result) {
        css.walkAtRules('remove', function (atrule) {
          	var params = atrule.params;
          	var selector = atrule.parent.selector;

          	if (atrule.parent.type == "root") {
              param = "all";
              selector = atrule.params;
            }

        	removeRules[selector] = {params: params, line: atrule.source.start.line};
          	atrule.remove();
        });

        css.walkRules(function (rule) {
          	var sel = removeRules[rule.selector];

          	if (sel === undefined) return;

          	if (sel.params === "all") {
              rule.remove();
              return;
            }

	        rule.walkDecls(sel.params, function (decl) {
              	if (sel.line >= decl.source.start.line) decl.remove();
            });
        });

    };
});
<commit_msg>syntax fixx<commit_after>var postcss = require('postcss');

module.exports = postcss.plugin('postcss-remove-nodes', function (opts) {
    opts = opts || {};
    var removeRules = {};

    return function (css, result) {
        css.walkAtRules('remove', function (atrule) {
          	var params = atrule.params;
          	var selector = atrule.parent.selector;

          	if (atrule.parent.type == "root") {
              param = "all";
              selector = atrule.params;
            }

        	removeRules[selector] = {params: params, line: atrule.source.start.line};
          	atrule.remove();
        });

        css.walkRules(function (rule) {
          	var sel = removeRules[rule.selector];

          	if (sel === undefined) return;

          	if (sel.params === "all") {
              rule.remove();
              return;
            }

	        rule.walkDecls(sel.params, function (decl) {
              	if (sel.line >= decl.source.start.line) decl.remove();
            });
        });

    };
});
<|endoftext|>


<commit_before>module.exports = function(name, ocss) {
  validate(arguments);

  function validate(args) {
    var name = args[0];
    var ocss = args[1];

    if ( ! name) throw new Error('missing object name param');
    if (/-/.test(name)) throw new Error('dashes are not allowed in object names');

    if (typeof ocss !== 'string') throw new Error('missing ocss param');
  }

  function removeComments(line) {
    return line.replace(/#.*$/, '');
  }

  function toObjects(line, linenum) {
    return {
      raw: line,
      linenum: linenum+1
    };
  }

  function isNotEmpty(line) {
    return ! /^\s*$/.test(line.raw);
  }

  function addIndentation(line) {
    line.indentation = line.raw.match(/^\s*/)[0].length;
    line.raw = line.raw.replace(/^\s+/, '');
    return line;
  }

  function addType(line) {
    line.type = type(line.raw, line.linenum);
    return line;
  }

  function type(string, linenum) {
    if (isElement(string)) return 'element';
    if (isDeclaration(string)) return 'declaration';

    throw new Error('Syntax error on line '+linenum+': '+string);
  }

  function isElement(string) {
    return /^[A-z]+$/.test(string);
  }

  function isDeclaration(string) {
    return /^\s*([A-z-]+):\s*([A-z\-]+)\s*$/.test(string);
  }

  var parse = {};

  parse.element = function(line) {
    line.name = line.raw.trim();
    return line;
  };

  parse.declaration = function(line) {
    var values = line.raw.match(/^(.+):\s*(.+)$/);

    line.property = values[1];
    line.value = values[2];

    return line;
  };

  function toAST(previous, current, index, lines) {

    if (index === lines.length-1) {
      return current;
    }
    if (current.indentation > previous.indentation+1) {
      throw new Error('wrong indentation at line '+current.linenum);
    }

    var nesting = (previous.indentation-current.indentation)+1;
    var parent = addParent(current, getNestedParent(nesting, previous));

    if (!parent[current.type+'s']) {
      parent[current.type+'s'] = [];
    }
    parent[current.type+'s'].push(current);

    return current;
  }

  function parseType(line) {
    if (parse[line.type]) {
      var parsedLine = parse[line.type](line);
    }
    return parsedLine;
  }

  function addParent(node, value) {
    Object.defineProperty(node, 'parent', {
      configurable: true,
      writable: true,
      enumerable: false,
      value: value || null
    });
    return node.parent;
  }

  function getNestedParent(nesting, node) {
    while(nesting--) {
      node = node.parent;
    }
    return node;
  }

  var object = {type: 'object', indentation: -1, name: name};

  return ocss
    .split('\n')
    .map(removeComments)
    .map(toObjects)
    .filter(isNotEmpty)
    .map(addIndentation)
    .map(addType)
    .map(parseType)
    .concat(object)
    .reduce(toAST, object);
};
<commit_msg>refactor toAST function<commit_after>module.exports = function(name, ocss) {
  validate(arguments);

  function validate(args) {
    var name = args[0];
    var ocss = args[1];

    if ( ! name) throw new Error('missing object name param');
    if (/-/.test(name)) throw new Error('dashes are not allowed in object names');

    if (typeof ocss !== 'string') throw new Error('missing ocss param');
  }

  function removeComments(line) {
    return line.replace(/#.*$/, '');
  }

  function toObjects(line, linenum) {
    return {
      raw: line,
      linenum: linenum+1
    };
  }

  function isNotEmpty(line) {
    return ! /^\s*$/.test(line.raw);
  }

  function addIndentation(line) {
    line.indentation = line.raw.match(/^\s*/)[0].length;
    line.raw = line.raw.replace(/^\s+/, '');
    return line;
  }

  function addType(line) {
    line.type = type(line.raw, line.linenum);
    return line;
  }

  function type(string, linenum) {
    if (isElement(string)) return 'element';
    if (isDeclaration(string)) return 'declaration';

    throw new Error('Syntax error on line '+linenum+': '+string);
  }

  function isElement(string) {
    return /^[A-z]+$/.test(string);
  }

  function isDeclaration(string) {
    return /^\s*([A-z-]+):\s*([A-z\-]+)\s*$/.test(string);
  }

  var parse = {};

  parse.object = function(name) {
    return {
      type: 'object',
      name: name,
      indentation: -1
    };
  };

  parse.declaration = function(line) {
    var values = line.raw.match(/^(.+):\s*(.+)$/);

    line.property = values[1];
    line.value = values[2];

    return line;
  };

  parse.element = function(line) {
    line.name = line.raw.trim();
    return line;
  };

  function toAST(previousLine, currentLine, index, lines) {
    if (currentLine.indentation > previousLine.indentation+1) {
      throw new Error('wrong indentation at line '+currentLine.linenum);
    }

    var nesting = (previousLine.indentation-currentLine.indentation)+1;
    var parent = addParent(currentLine, getNestedParent(nesting, previousLine));

    if (!parent[currentLine.type+'s']) {
      parent[currentLine.type+'s'] = [];
    }
    parent[currentLine.type+'s'].push(currentLine);

    if (index === lines.length-1) {
      return lines[0].parent;
    }
    return currentLine;
  }

  function parseType(line) {
    if (parse[line.type]) {
      var parsedLine = parse[line.type](line);
    }
    return parsedLine;
  }

  function addParent(node, value) {
    Object.defineProperty(node, 'parent', {
      configurable: true,
      writable: true,
      enumerable: false,
      value: value || null
    });
    return node.parent;
  }

  function getNestedParent(nesting, node) {
    while(nesting--) {
      node = node.parent;
    }
    return node;
  }

  return ocss
    .split('\n')
    .map(removeComments)
    .map(toObjects)
    .filter(isNotEmpty)
    .map(addIndentation)
    .map(addType)
    .map(parseType)
    .reduce(toAST, parse.object(name));
};
<|endoftext|>


<commit_before>/* eslint-env node */
module.exports = {
  'extends': 'eslint:recommended',
  'rules': {
    'array-bracket-spacing': [2, 'never'],
    'block-scoped-var': 2,
    'brace-style': [2, 'stroustrup', {'allowSingleLine': false}],
    'camelcase': 2,
    'callback-return': [2, ["callback", "_callback", "_cb", "cb", "next", "_next"]],
    'comma-style': 2,
    'curly': [2, 'multi-line'],
    'eol-last': 2,
    'eqeqeq': [2, 'smart'],
    'import/prefer-default-export': 0,
    'max-depth': [1, 3],
    'max-statements': [1, 30],
    'max-len': [1, 120, 4, {"ignoreComments": true, "ignoreUrls": true}],
    'new-cap': [
      2,
      {
        newIsCap: true,
        capIsNew: true,
        newIsCapExceptions: [],
        capIsNewExceptions: ['Router', 'Resource', 'Schema', 'ObjectId', 'Q', 'Chance']
      }
    ],
    'no-cond-assign': 2,
    'no-extend-native': 2,
    'no-extra-semi': 2,
    'no-mixed-spaces-and-tabs': 2,
    'no-multiple-empty-lines': [2, {max: 1}],
    'no-spaced-func': 2,
    'no-trailing-spaces': 2,
    'no-underscore-dangle': 0,
    'no-use-before-define': [2, 'nofunc'],
    'no-unexpected-multiline': 2,
    'no-unused-vars': 1,
    'object-curly-spacing': [2, 'never'],
    'padded-blocks': [2, 'never'],
    'react/forbid-prop-types': 0,
    'react/jsx-filename-extension': 0,
    'react/prefer-stateless-function': 0,
    'quotes': [2, 'single', 'avoid-escape'],
    'semi': [2, 'always'],
    'keyword-spacing': [2, {"after": true}],
    'space-before-blocks': 2,
    'space-before-function-paren': [2, 'never'],
    'space-unary-ops': 2,
  }
};
<commit_msg>Add no noninteractive element interactions.<commit_after>/* eslint-env node */
module.exports = {
  'extends': 'eslint:recommended',
  'rules': {
    'array-bracket-spacing': [2, 'never'],
    'block-scoped-var': 2,
    'brace-style': [2, 'stroustrup', {'allowSingleLine': false}],
    'camelcase': 2,
    'callback-return': [2, ["callback", "_callback", "_cb", "cb", "next", "_next"]],
    'comma-style': 2,
    'curly': [2, 'multi-line'],
    'eol-last': 2,
    'eqeqeq': [2, 'smart'],
    'import/prefer-default-export': 0,
    'jsx-a11y/no-noninteractive-element-interactions': 0,
    'max-depth': [1, 3],
    'max-statements': [1, 30],
    'max-len': [1, 120, 4, {"ignoreComments": true, "ignoreUrls": true}],
    'new-cap': [
      2,
      {
        newIsCap: true,
        capIsNew: true,
        newIsCapExceptions: [],
        capIsNewExceptions: ['Router', 'Resource', 'Schema', 'ObjectId', 'Q', 'Chance']
      }
    ],
    'no-cond-assign': 2,
    'no-extend-native': 2,
    'no-extra-semi': 2,
    'no-mixed-spaces-and-tabs': 2,
    'no-multiple-empty-lines': [2, {max: 1}],
    'no-spaced-func': 2,
    'no-trailing-spaces': 2,
    'no-underscore-dangle': 0,
    'no-use-before-define': [2, 'nofunc'],
    'no-unexpected-multiline': 2,
    'no-unused-vars': 1,
    'object-curly-spacing': [2, 'never'],
    'padded-blocks': [2, 'never'],
    'react/forbid-prop-types': 0,
    'react/jsx-filename-extension': 0,
    'react/prefer-stateless-function': 0,
    'quotes': [2, 'single', 'avoid-escape'],
    'semi': [2, 'always'],
    'keyword-spacing': [2, {"after": true}],
    'space-before-blocks': 2,
    'space-before-function-paren': [2, 'never'],
    'space-unary-ops': 2,
  }
};
<|endoftext|>


<commit_before>/*
Daefen
------

A library for encoding and decoding large numbers into a pronounceable, high density, string, that uses 3456 syllables as it's base.

*/

// Creates the syllable array
var syllables = [];
var consonants = 'bcdfghjklmnprstvwz'; // consonants except hard to speak ones
var vowels = 'aeiouy'; // vowels

// Vowel + Consonant
for (a = 0; a < vowels.length; a++) {
  for (b = 0; b < consonants.length; b++) {
    syllables.push(vowels[a] + consonants[b] );
  }
}

// Consonant + Vowel
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    syllables.push(consonants[b] + vowels[a]);
  }
}

// Consonant + Vowel + Vowel
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    for (e = 0; e < vowels.length; e++) {
      syllables.push(consonants[b] + vowels[a] + vowels[e]);
    }
  }
}

// Consonant + Vowel + Consonant
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    for (c = 0; c < consonants.length; c++) {
      syllables.push(consonants[b] + vowels[a] + consonants[c]);
    }
  }
}

// Vowel + Consonant + Vowel
for (a = 0; a < vowels.length; a++) {
  for (b = 0; b < consonants.length; b++) {
    for (e = 0; e < vowels.length; e++) {
      syllables.push(vowels[a] + consonants[b] + vowels[e]);
    }
  }
}

// Quick function that converst a big Number object into an array of numbers in any base
function fromBase10(bigNum, base) {
  var result = [];
  if (bigNum == 0) return [0];
  for (var i=bigNum; i > 0; i = i.dividedBy(base).floor()){
   result.unshift(i.modulo(base).toFixed());
  };
  return result;
}

// Important to check some spacing issues
function isConsonant(letter) {
  return consonants.indexOf(letter) >= 0;
}

// Converts an integer (passed as a string to avoid scientific notation issues)
function toWords(numberAsString) {
  let bn = new BigNumber(numberAsString.toString());
  let numberArray = fromBase10(bn, syllables.length);
  let result = '';
  let lastWord = '';
  let n = 0;
  for (i = 0; i < numberArray.length; i++) {
    n = numberArray[i] || 0;

    lastWord = result.split(" ").slice(-1)[0];

    if (result == ''  || lastWord.length == syllables[n].length
      || (lastWord.length < 5 && isConsonant(lastWord.slice(-1)) && isConsonant(syllables[n].slice(0,1))) ) {
      result += syllables[n];
    } else {
      result += " " + syllables[n];
    }
  }
  return result.replace(/\b[a-z]/g,function(f){return f.toUpperCase();});
}

// Converts a valid phrase back into a string
function fromWords(words) {
  let wordArray = words.toLowerCase()
    .replace(/[bcdfghjklmnprstvwz][bcdfghjklmnprstvwz]/gi,function(r){ let n = Math.floor(r.length/2); return r.substr(0,n) + ' ' + r.substr(n,n)})
    .replace(/[a-z]{6}|[a-z]{4}/gi,function(r){ let n = Math.floor(r.length/2); return r.substr(0,n) + ' ' + r.substr(n,n)})
    .split(" ");
  let result = new BigNumber(0);

  for (i = 0; i < wordArray.length; i++) {
    if (syllables.indexOf(wordArray[i]) < 0) return;
    result = result.plus(new BigNumber(syllables.indexOf(wordArray[i])).times(new BigNumber(syllables.length).toPower(wordArray.length - i - 1)))
  }

  return result.toString(10);
}

var random = Math.floor(Math.random()*Math.pow(3456,5)).toString()
toWords(random)

<commit_msg>Minor changes to the comments<commit_after>/*
Daefen
------

A library for encoding/decoding large numbers into/from a pronounceable high-density string constructed from a base of 3456 syllables.

*/

// Creates the syllable array
var syllables = [];
var consonants = 'bcdfghjklmnprstvwz'; // consonants that are unambiguous easy to pronounce
var vowels = 'aeiouy'; // vowels

// Vowel + Consonant
for (a = 0; a < vowels.length; a++) {
  for (b = 0; b < consonants.length; b++) {
    syllables.push(vowels[a] + consonants[b] );
  }
}

// Consonant + Vowel
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    syllables.push(consonants[b] + vowels[a]);
  }
}

// Consonant + Vowel + Vowel
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    for (e = 0; e < vowels.length; e++) {
      syllables.push(consonants[b] + vowels[a] + vowels[e]);
    }
  }
}

// Consonant + Vowel + Consonant
for (b = 0; b < consonants.length; b++) {
  for (a = 0; a < vowels.length; a++) {
    for (c = 0; c < consonants.length; c++) {
      syllables.push(consonants[b] + vowels[a] + consonants[c]);
    }
  }
}

// Vowel + Consonant + Vowel
for (a = 0; a < vowels.length; a++) {
  for (b = 0; b < consonants.length; b++) {
    for (e = 0; e < vowels.length; e++) {
      syllables.push(vowels[a] + consonants[b] + vowels[e]);
    }
  }
}

// Quick function that converts a big Number object into an array of numbers for any chosen base
function fromBase10(bigNum, base) {
  var result = [];
  if (bigNum == 0) return [0];
  for (var i=bigNum; i > 0; i = i.dividedBy(base).floor()){
   result.unshift(i.modulo(base).toFixed());
  };
  return result;
}

// Important to check some spacing issues
function isConsonant(letter) {
  return consonants.indexOf(letter) >= 0;
}

// Converts an integer (passed as a string to avoid scientific notation issues)
function toWords(numberAsString) {
  let bn = new BigNumber(numberAsString.toString());
  let numberArray = fromBase10(bn, syllables.length);
  let result = '';
  let lastWord = '';
  let n = 0;
  for (i = 0; i < numberArray.length; i++) {
    n = numberArray[i] || 0;

    lastWord = result.split(" ").slice(-1)[0];

    if (result == ''  || lastWord.length == syllables[n].length
      || (lastWord.length < 5 && isConsonant(lastWord.slice(-1)) && isConsonant(syllables[n].slice(0,1))) ) {
      result += syllables[n];
    } else {
      result += " " + syllables[n];
    }
  }
  return result.replace(/\b[a-z]/g,function(f){return f.toUpperCase();});
}

// Converts a valid phrase back into a string
function fromWords(words) {
  let wordArray = words.toLowerCase()
    .replace(/[bcdfghjklmnprstvwz][bcdfghjklmnprstvwz]/gi,function(r){ let n = Math.floor(r.length/2); return r.substr(0,n) + ' ' + r.substr(n,n)})
    .replace(/[a-z]{6}|[a-z]{4}/gi,function(r){ let n = Math.floor(r.length/2); return r.substr(0,n) + ' ' + r.substr(n,n)})
    .split(" ");
  let result = new BigNumber(0);

  for (i = 0; i < wordArray.length; i++) {
    if (syllables.indexOf(wordArray[i]) < 0) return;
    result = result.plus(new BigNumber(syllables.indexOf(wordArray[i])).times(new BigNumber(syllables.length).toPower(wordArray.length - i - 1)))
  }

  return result.toString(10);
}

var random = Math.floor(Math.random()*Math.pow(3456,5)).toString()
toWords(random)

<|endoftext|>