<commit_before>'use strict';

/**
 * A CatApiEndpoint wraps several helper functions to easily execute backend calls for the base CRUD operations.
 * It also adds support for 'children' which can only be used by resolving them for a parent id.
 * @param {string} url the base url which is added before the configured urls
 * @param {object} endpointConfig the configuration of this endpoint - holds properties like name, url, the model and children
 * @param {object} $http the angular $http service which handles the actual xhr requests
 * @param {object} catConversionService the catConversionService used to convert from and to server side data
 * @constructor
 */
function CatApiEndpoint(url, endpointConfig, $http, catConversionService) {
    var that = this;

    var _endpointName = endpointConfig.name;
    var config = endpointConfig.config;
    var _endpointUrl = url + (config.url || endpointConfig.name);
    var _childEndpointSettings = endpointConfig.children;

    /**
     * This helper function initializes all configured child endpoints by creating the appropriate url by appending
     * the given id before initializing them.
     * @return {object} a object holding all resolved child endpoints for the given id
     * @private
     */
    var _res = _.memoize(function (id) {
        var url = _endpointUrl + '/' + id + '/';
        var ret = {};
        _.forEach(_.keys(_childEndpointSettings), function (path) {
            ret[path] = new CatApiEndpoint(url, _childEndpointSettings[path], $http);
            ret[path].parentEndpoint = that;
            ret[path].parentId = id;
            ret[path].parentInfo = function () {
                return that.info(id);
            };
        });
        return ret;
    });

    var _addChildEndpoints = function (data) {
        _.merge(data, _res(data.id));
    };

    /**
     * This helper method initializes a new instance of the configured model with the given data and adds all child
     * endpoints to it.
     * @param data the data received from the backend which is used to initialize the model
     * @return {Object} an instance of the configured model initialized with the given data and the resolved child
     * endpoints
     * @private
     */
    var _mapResponse = function (data) {
        var object = catConversionService.toClient(data, config);

        if (!_.isUndefined(object.id)) {
            _addChildEndpoints(object);
        }

        if (_.isArray(object)) {
            _.forEach(object, _addChildEndpoints);
        }

        if (_.isArray(object.elements)) {
            _.forEach(object.elements, _addChildEndpoints);
        }

        return object;
    };

    /**
     * This helper methods deletes all child endpoints from the given object.
     * @param {object} object the object to remove the child endpoints from
     * @return {object} the passed in object without the child endpoints
     * @private
     */
    var _removeEndpoints = function (object) {
        var endpoints = _res(object.id);
        _.forEach(_.keys(endpoints), function (key) {
            delete object[key];
        });
        return object;
    };

    /**
     * This helper method turns a cat.SearchRequest in to en url encoded search query
     * @param {window.cat.SearchRequest} [searchRequest] the search request which should be url encoded
     * @return {string} either the url encoded search query or an empty string if no search request is given or it is not a instance of cat.SearchRequest
     * @private
     */
    var _getSearchQuery = function (searchRequest) {
        return !!searchRequest && searchRequest instanceof window.cat.SearchRequest ? '?' + searchRequest.urlEncoded() : '';
    };

    /**
     * This method is used to instantiate actual child api endpoints which are dependent on a certain parent id
     * @param id the id for which to 'resolve' the child endpoints.
     * @return {object} a object which maps all child endpoint names to the actual endpoints where the url was resolved
     * with the provided id
     */
    this.res = function (id) {
        return _res(id);
    };

    /**
     * A small helper function to retrieve the actual url this endpoint resolved to.
     * @return {string} the resolved url of this endpoint
     */
    this.getEndpointUrl = function () {
        return _endpointUrl;
    };

    /**
     * A small helper to retrieve the name of the endpoint.
     * @return {string} the name of this endpoint
     */
    this.getEndpointName = function () {
        return _endpointName;
    };

    /**
     * This function calls the url available via #getEndpointUrl without further modification apart from adding search
     * parameters if the searchRequest parameter is provided. It can handle either an array response in which case all
     * elements will be mapped to the appropriate configured model or a 'paginated' result in which case an object
     * with totalCount, facests and elements will be returned.
     *
     * @param {SearchRequest} [searchRequest] if given searchRequest#urlEncoded() will be added to the request url
     * @return {[{object}]|{totalCount: {Number}, facets: [{Facet}], elements: []}} a promise wrapping either a list of
     * instances of the configured model or a wrapper object which holds not only the list but pagination information
     * as well
     */
    this.list = function (searchRequest) {
        return $http.get(_endpointUrl + _getSearchQuery(searchRequest)).then(function (response) {
            return _mapResponse(response.data);
        });
    };

    /**
     * A helper function which adds '/all' to the request url available via #getEndpointUrl and maps the response to
     * the configured model.
     * @return [{object}] a promise wrapping an array of new instances of the configured model initialized with the data retrieved from
     * the backend
     */
    this.all = function () {
        return $http.get(_endpointUrl + '/all').then(function (response) {
            return _.map(response.data, function (elem) {
                return _mapResponse(elem);
            });
        });
    };

    /**
     * This method makes a GET request to the url available via #getEndpointUrl with the addition of the provided id at the end.
     * @param id the id which will be appended as '/:id' to the url
     * @return {object} a promise wrapping a new instance of the configured model initialized with the data retrieved
     * from the backend
     */
    this.get = function (id) {
        return $http.get(_endpointUrl + '/' + id).then(function (response) {
            return _mapResponse(response.data);
        });
    };

    /**
     * This method makes a GET the url available via #getEndpointUrl with the addition of the provided id at the end + the
     * 'info' request parameter.
     * @param id the id which will be appended as '/:id' to the url
     * @return {*} a promise wrapping the data retrieved from the backend
     */
    this.info = function (id) {
        return $http.get(_endpointUrl + '/' + id + '?info').then(function (response) {
            return response.data;
        });
    };

    /**
     * This method is either makes a PUT or POST request to the backend depending on wheter or not the given object
     * has an 'id' attribute.
     * For PUT requests the url resolves to #getEndpointUrl + /:id, for POST requests it is just the #getEndpointUrl
     * @param {object} object the object which should be sent to the sever. it is stripped of all child endpoints before
     * it is sent.
     * @return {object} a promise wrapping a new instance of the configured model initialized with the data retrieved
     * from the backend
     */
    this.save = function (object) {
        if (!!object.id) {
            return $http.put(_endpointUrl + '/' + object.id, _removeEndpoints(object)).then(function (response) {
                return _mapResponse(response.data);
            });
        } else {
            return $http.post(_endpointUrl, _removeEndpoints(object)).then(function (response) {
                return _mapResponse(response.data);
            });
        }
    };

    /**
     * This method executes a DELETE request to the url available via #getEndpointUrl with the addition of the provided url at the end.
     * @param url the url to be appended to the endpoint url - usually only the id of the object to delete
     * @return {*} The promise returned by the $http 'DELETE' call
     */
    this.remove = function (url) {
        return $http({method: 'DELETE', url: _endpointUrl + '/' + url});
    };

    /**
     * Simple wrapper object which contains the custom get, put and post methods
     * @type {{}}
     */
    this.custom = {};

    /**
     * This method executes a GET request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param searchRequest an optional cat.SearchRequest to be applied to the request
     * @return {*} The promise returned by the $http.get call
     */
    this.custom.get = function (url, searchRequest) {
        return $http.get([_endpointUrl, url].join('/') + _getSearchQuery(searchRequest));
    };

    /**
     * This method executes a POST request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param object hte object to send as payload - not that it will be used as is for this request
     * @return {*} The promise returned by the $http.post call
     */
    this.custom.post = function (url, object) {
        return $http.post([_endpointUrl, url].join('/'), object);
    };

    /**
     * This method executes a PUT request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param object hte object to send as payload - not that it will be used as is for this request
     * @return {*} The promise returned by the $http.put call
     */
    this.custom.put = function (url, object) {
        return $http.put([_endpointUrl, url].join('/'), object);
    };
}

/**
 * @description
 * An 'EndpointConfig' basically is a wrapper around the configuration for an api endpoint during the configuration
 * phase which is later used to instantiate the actual CatApiEndpoints. It exposes its name, the configuration itself,
 * as well as a map of all its children and helper function to create or receive child endpoint configurations.
 *
 * @param {string} name the name of the endpoint
 * @param {object} config the api endpoint configuration which basically wraps an 'url' and a 'model' attribute.
 * If a 'children' attribute is present as well it will be used to create the appropriate child endpoints automatically,
 * without the need to call the #child method manually - this works to arbitrary deps.
 * @constructor
 */
function EndpointConfig(name, config) {
    var that = this;
    this.config = config || {};
    this.children = {};
    this.name = name;

    /**
     * This method method either returns or creates and returns a child api endpoint of the current one.
     *
     * @param {string} childName the name of the child endpoint
     * @param {object} [childConfig] if given a new EndpointConfig will be created as a child of the current one. The
     * parent property of the created config will point to the current config
     * @return {EndpointConfig} the child endpoint config with the given name
     */
    this.child = function (childName, childConfig) {
        if (!_.isUndefined(childConfig)) {
            this.children[childName] = new EndpointConfig(childName, childConfig);
            this.children[childName].parent = this;
        }

        return this.children[childName];
    };

    // this takes care of mapping the 'old' config style to the new builder style
    if (!_.isUndefined(this.config.children)) {
        var childrenConfig = this.config.children;
        delete this.config.children;
        _.forEach(_.keys(childrenConfig), function (childName) {
            that.child(childName, childrenConfig[childName]);
        });
    }
}

// this is saved outside so that both $api and catApiService use the same config - will be moved back inside
// CatApiServiceProvider in a future release
var _endpoints = {};

/**
 * @ngdoc service
 * @description
 *
 * The CatApiServiceProvider exposes a single configuration method 'endpoint' which can be used to create or retrieve
 * named endpoint configurations.
 *
 * @constructor
 */
function CatApiServiceProvider() {
    var _urlPrefix = '/api/';

    /**
     * This method is used to either create or retrieve named endpoint configurations.
     * @param {string} name the name of the api endpoint to create or retrieve the configuration for
     * @param {object} [settings] if given a new {EndpointConfig} will be created with the given settings
     * @return {EndpointConfig} the endpoint config for the given name
     */
    this.endpoint = function (name, settings) {
        if (!_.isUndefined(settings)) {
            _endpoints[name] = new EndpointConfig(name, settings);
        }
        return _endpoints[name];
    };

    this.$get = ['$http', 'catConversionService',
        /**
         * @return {object} returns a map from names to CatApiEndpoints
         */
            function $getCatApiService($http, catConversionService) {
            var catApiService = {};

            _.forEach(_.keys(_endpoints), function (path) {
                catApiService[path] = new CatApiEndpoint(_urlPrefix, _endpoints[path], $http, catConversionService);
            });

            return catApiService;
        }];
}
angular.module('cat.service.api').provider('catApiService', CatApiServiceProvider);
// $api is deprecated, will be removed in a future release
angular.module('cat.service.api').provider('$api', CatApiServiceProvider);
<commit_msg>[FIX] add catConversionService parameter to child endpoint creation<commit_after>'use strict';

/**
 * A CatApiEndpoint wraps several helper functions to easily execute backend calls for the base CRUD operations.
 * It also adds support for 'children' which can only be used by resolving them for a parent id.
 * @param {string} url the base url which is added before the configured urls
 * @param {object} endpointConfig the configuration of this endpoint - holds properties like name, url, the model and children
 * @param {object} $http the angular $http service which handles the actual xhr requests
 * @param {object} catConversionService the catConversionService used to convert from and to server side data
 * @constructor
 */
function CatApiEndpoint(url, endpointConfig, $http, catConversionService) {
    var that = this;

    var _endpointName = endpointConfig.name;
    var config = endpointConfig.config;
    var _endpointUrl = url + (config.url || endpointConfig.name);
    var _childEndpointSettings = endpointConfig.children;

    /**
     * This helper function initializes all configured child endpoints by creating the appropriate url by appending
     * the given id before initializing them.
     * @return {object} a object holding all resolved child endpoints for the given id
     * @private
     */
    var _res = _.memoize(function (id) {
        var url = _endpointUrl + '/' + id + '/';
        var ret = {};
        _.forEach(_.keys(_childEndpointSettings), function (path) {
            ret[path] = new CatApiEndpoint(url, _childEndpointSettings[path], $http, catConversionService);
            ret[path].parentEndpoint = that;
            ret[path].parentId = id;
            ret[path].parentInfo = function () {
                return that.info(id);
            };
        });
        return ret;
    });

    var _addChildEndpoints = function (data) {
        _.merge(data, _res(data.id));
    };

    /**
     * This helper method initializes a new instance of the configured model with the given data and adds all child
     * endpoints to it.
     * @param data the data received from the backend which is used to initialize the model
     * @return {Object} an instance of the configured model initialized with the given data and the resolved child
     * endpoints
     * @private
     */
    var _mapResponse = function (data) {
        var object = catConversionService.toClient(data, config);

        if (!_.isUndefined(object.id)) {
            _addChildEndpoints(object);
        }

        if (_.isArray(object)) {
            _.forEach(object, _addChildEndpoints);
        }

        if (_.isArray(object.elements)) {
            _.forEach(object.elements, _addChildEndpoints);
        }

        return object;
    };

    /**
     * This helper methods deletes all child endpoints from the given object.
     * @param {object} object the object to remove the child endpoints from
     * @return {object} the passed in object without the child endpoints
     * @private
     */
    var _removeEndpoints = function (object) {
        var endpoints = _res(object.id);
        _.forEach(_.keys(endpoints), function (key) {
            delete object[key];
        });
        return object;
    };

    /**
     * This helper method turns a cat.SearchRequest in to en url encoded search query
     * @param {window.cat.SearchRequest} [searchRequest] the search request which should be url encoded
     * @return {string} either the url encoded search query or an empty string if no search request is given or it is not a instance of cat.SearchRequest
     * @private
     */
    var _getSearchQuery = function (searchRequest) {
        return !!searchRequest && searchRequest instanceof window.cat.SearchRequest ? '?' + searchRequest.urlEncoded() : '';
    };

    /**
     * This method is used to instantiate actual child api endpoints which are dependent on a certain parent id
     * @param id the id for which to 'resolve' the child endpoints.
     * @return {object} a object which maps all child endpoint names to the actual endpoints where the url was resolved
     * with the provided id
     */
    this.res = function (id) {
        return _res(id);
    };

    /**
     * A small helper function to retrieve the actual url this endpoint resolved to.
     * @return {string} the resolved url of this endpoint
     */
    this.getEndpointUrl = function () {
        return _endpointUrl;
    };

    /**
     * A small helper to retrieve the name of the endpoint.
     * @return {string} the name of this endpoint
     */
    this.getEndpointName = function () {
        return _endpointName;
    };

    /**
     * This function calls the url available via #getEndpointUrl without further modification apart from adding search
     * parameters if the searchRequest parameter is provided. It can handle either an array response in which case all
     * elements will be mapped to the appropriate configured model or a 'paginated' result in which case an object
     * with totalCount, facests and elements will be returned.
     *
     * @param {SearchRequest} [searchRequest] if given searchRequest#urlEncoded() will be added to the request url
     * @return {[{object}]|{totalCount: {Number}, facets: [{Facet}], elements: []}} a promise wrapping either a list of
     * instances of the configured model or a wrapper object which holds not only the list but pagination information
     * as well
     */
    this.list = function (searchRequest) {
        return $http.get(_endpointUrl + _getSearchQuery(searchRequest)).then(function (response) {
            return _mapResponse(response.data);
        });
    };

    /**
     * A helper function which adds '/all' to the request url available via #getEndpointUrl and maps the response to
     * the configured model.
     * @return [{object}] a promise wrapping an array of new instances of the configured model initialized with the data retrieved from
     * the backend
     */
    this.all = function () {
        return $http.get(_endpointUrl + '/all').then(function (response) {
            return _.map(response.data, function (elem) {
                return _mapResponse(elem);
            });
        });
    };

    /**
     * This method makes a GET request to the url available via #getEndpointUrl with the addition of the provided id at the end.
     * @param id the id which will be appended as '/:id' to the url
     * @return {object} a promise wrapping a new instance of the configured model initialized with the data retrieved
     * from the backend
     */
    this.get = function (id) {
        return $http.get(_endpointUrl + '/' + id).then(function (response) {
            return _mapResponse(response.data);
        });
    };

    /**
     * This method makes a GET the url available via #getEndpointUrl with the addition of the provided id at the end + the
     * 'info' request parameter.
     * @param id the id which will be appended as '/:id' to the url
     * @return {*} a promise wrapping the data retrieved from the backend
     */
    this.info = function (id) {
        return $http.get(_endpointUrl + '/' + id + '?info').then(function (response) {
            return response.data;
        });
    };

    /**
     * This method is either makes a PUT or POST request to the backend depending on wheter or not the given object
     * has an 'id' attribute.
     * For PUT requests the url resolves to #getEndpointUrl + /:id, for POST requests it is just the #getEndpointUrl
     * @param {object} object the object which should be sent to the sever. it is stripped of all child endpoints before
     * it is sent.
     * @return {object} a promise wrapping a new instance of the configured model initialized with the data retrieved
     * from the backend
     */
    this.save = function (object) {
        if (!!object.id) {
            return $http.put(_endpointUrl + '/' + object.id, _removeEndpoints(object)).then(function (response) {
                return _mapResponse(response.data);
            });
        } else {
            return $http.post(_endpointUrl, _removeEndpoints(object)).then(function (response) {
                return _mapResponse(response.data);
            });
        }
    };

    /**
     * This method executes a DELETE request to the url available via #getEndpointUrl with the addition of the provided url at the end.
     * @param url the url to be appended to the endpoint url - usually only the id of the object to delete
     * @return {*} The promise returned by the $http 'DELETE' call
     */
    this.remove = function (url) {
        return $http({method: 'DELETE', url: _endpointUrl + '/' + url});
    };

    /**
     * Simple wrapper object which contains the custom get, put and post methods
     * @type {{}}
     */
    this.custom = {};

    /**
     * This method executes a GET request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param searchRequest an optional cat.SearchRequest to be applied to the request
     * @return {*} The promise returned by the $http.get call
     */
    this.custom.get = function (url, searchRequest) {
        return $http.get([_endpointUrl, url].join('/') + _getSearchQuery(searchRequest));
    };

    /**
     * This method executes a POST request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param object hte object to send as payload - not that it will be used as is for this request
     * @return {*} The promise returned by the $http.post call
     */
    this.custom.post = function (url, object) {
        return $http.post([_endpointUrl, url].join('/'), object);
    };

    /**
     * This method executes a PUT request to the url available via #getEndpointUrl joined with the provided one.
     * Be aware that the result of the promise will not be mapped to the configured model but instead will be passed on directly.
     * @param url the url to be appended to the endpoint url
     * @param object hte object to send as payload - not that it will be used as is for this request
     * @return {*} The promise returned by the $http.put call
     */
    this.custom.put = function (url, object) {
        return $http.put([_endpointUrl, url].join('/'), object);
    };
}

/**
 * @description
 * An 'EndpointConfig' basically is a wrapper around the configuration for an api endpoint during the configuration
 * phase which is later used to instantiate the actual CatApiEndpoints. It exposes its name, the configuration itself,
 * as well as a map of all its children and helper function to create or receive child endpoint configurations.
 *
 * @param {string} name the name of the endpoint
 * @param {object} config the api endpoint configuration which basically wraps an 'url' and a 'model' attribute.
 * If a 'children' attribute is present as well it will be used to create the appropriate child endpoints automatically,
 * without the need to call the #child method manually - this works to arbitrary deps.
 * @constructor
 */
function EndpointConfig(name, config) {
    var that = this;
    this.config = config || {};
    this.children = {};
    this.name = name;

    /**
     * This method method either returns or creates and returns a child api endpoint of the current one.
     *
     * @param {string} childName the name of the child endpoint
     * @param {object} [childConfig] if given a new EndpointConfig will be created as a child of the current one. The
     * parent property of the created config will point to the current config
     * @return {EndpointConfig} the child endpoint config with the given name
     */
    this.child = function (childName, childConfig) {
        if (!_.isUndefined(childConfig)) {
            this.children[childName] = new EndpointConfig(childName, childConfig);
            this.children[childName].parent = this;
        }

        return this.children[childName];
    };

    // this takes care of mapping the 'old' config style to the new builder style
    if (!_.isUndefined(this.config.children)) {
        var childrenConfig = this.config.children;
        delete this.config.children;
        _.forEach(_.keys(childrenConfig), function (childName) {
            that.child(childName, childrenConfig[childName]);
        });
    }
}

// this is saved outside so that both $api and catApiService use the same config - will be moved back inside
// CatApiServiceProvider in a future release
var _endpoints = {};

/**
 * @ngdoc service
 * @description
 *
 * The CatApiServiceProvider exposes a single configuration method 'endpoint' which can be used to create or retrieve
 * named endpoint configurations.
 *
 * @constructor
 */
function CatApiServiceProvider() {
    var _urlPrefix = '/api/';

    /**
     * This method is used to either create or retrieve named endpoint configurations.
     * @param {string} name the name of the api endpoint to create or retrieve the configuration for
     * @param {object} [settings] if given a new {EndpointConfig} will be created with the given settings
     * @return {EndpointConfig} the endpoint config for the given name
     */
    this.endpoint = function (name, settings) {
        if (!_.isUndefined(settings)) {
            _endpoints[name] = new EndpointConfig(name, settings);
        }
        return _endpoints[name];
    };

    this.$get = ['$http', 'catConversionService',
        /**
         * @return {object} returns a map from names to CatApiEndpoints
         */
            function $getCatApiService($http, catConversionService) {
            var catApiService = {};

            _.forEach(_.keys(_endpoints), function (path) {
                catApiService[path] = new CatApiEndpoint(_urlPrefix, _endpoints[path], $http, catConversionService);
            });

            return catApiService;
        }];
}
angular.module('cat.service.api').provider('catApiService', CatApiServiceProvider);
// $api is deprecated, will be removed in a future release
angular.module('cat.service.api').provider('$api', CatApiServiceProvider);
<|endoftext|>


<commit_before>'use strict';

const Rela = require('./lib'),
      info = require('./package.json');

/* index.js
 * Server initialization and package information.
 * * */

// Library initializer
module.exports = exports = function(){
  return new Rela();
};

// Raw server accessor.
exports.Rela = Rela;

// Meta
exports.name = info.name;
exports.version = info.version;
exports.author = info.author;
exports.license = info.license;
<commit_msg>Auto initialized into functional call to initialize.<commit_after>'use strict';

const Rela = require('./lib'),
      info = require('./package.json');

/* index.js
 * Server initialization and package information.
 * * */

// Library initializer
module.exports = exports = function(opts){
  return new Rela(opts);
};

// Raw server accessor.
exports.Rela = Rela;

// Meta
exports.name = info.name;
exports.version = info.version;
exports.author = info.author;
exports.license = info.license;
<|endoftext|>


<commit_before>import templateUrl from './process-snapshots-modal.html'

export const ProcessSnapshotsModalComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  bindings: {
    resolve: '<',
    modalInstance: '<',
    close: '&',
    dismiss: '&'
  },
  templateUrl
}

/** @ngInject */
function ComponentController ($controller, $state, EventNotifications, VmsService) {
  const vm = this

  vm.$onInit = function () {
    angular.extend(vm, $controller('BaseModalController', {
      $uibModalInstance: vm.modalInstance
    }))

    angular.extend(vm, {
      modalData: {},
      vm: vm.resolve.vm,
      modalType: vm.resolve.modalType,
      save: save
    })

    vm.nameLabel = __("Name")
    vm.descriptionLabel = __("Description")

    vm.nameLabelClass = 'col-sm-3'
    vm.descriptionLabelClass = 'col-sm-3'

    vm.nameShown = true
    vm.nameRequired = true

    vm.descriptionShown = true
    vm.descriptionRequired = false

    // FIXME: @record.snapshot_name_optional?
    if (['ovirt', 'redhat'].includes(vm.vm.vendor)) {
      vm.nameShown = false
      vm.descriptionRequired = true
    }
    if (vm.vm.vendor == 'openstack') {
      vm.nameShown = true
      vm.descriptionRequired = true
    }

    if (! vm.nameShown) {
      vm.nameRequired = false
    }
    if (! vm.descriptionShown) {
      vm.descriptionRequired = false
    }

    if (vm.nameRequired) {
      vm.nameLabel += ' *'
      vm.nameLabelClass += ' required'
    }
    if (vm.descriptionRequired) {
      vm.descriptionLabel += ' *'
      vm.descriptionLabelClass += ' required'
    }
  }

  function save () {
    VmsService.createSnapshots(vm.vm.id, vm.modalData).then(success, failure)
  }

  function success (response) {
    vm.close()
    $state.go($state.current, {}, {reload: true})
    EventNotifications.batch(response.results, __('Creating snapshot.'), __('Error creating snapshot.'))
  }

  function failure (response) {
    EventNotifications.error(__('There was an error creating the snapshot.') + response.message)
  }
}
<commit_msg>js style fixes<commit_after>import templateUrl from './process-snapshots-modal.html'

export const ProcessSnapshotsModalComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  bindings: {
    resolve: '<',
    modalInstance: '<',
    close: '&',
    dismiss: '&'
  },
  templateUrl
}

/** @ngInject */
function ComponentController ($controller, $state, EventNotifications, VmsService) {
  const vm = this

  vm.$onInit = function () {
    angular.extend(vm, $controller('BaseModalController', {
      $uibModalInstance: vm.modalInstance
    }))

    angular.extend(vm, {
      modalData: {},
      vm: vm.resolve.vm,
      modalType: vm.resolve.modalType,
      save: save
    })

    vm.nameLabel = __('Name')
    vm.descriptionLabel = __('Description')

    vm.nameLabelClass = 'col-sm-3'
    vm.descriptionLabelClass = 'col-sm-3'

    vm.nameShown = true
    vm.nameRequired = true

    vm.descriptionShown = true
    vm.descriptionRequired = false

    // FIXME: @record.snapshot_name_optional?
    if (['ovirt', 'redhat'].includes(vm.vm.vendor)) {
      vm.nameShown = false
      vm.descriptionRequired = true
    }
    if (vm.vm.vendor === 'openstack') {
      vm.nameShown = true
      vm.descriptionRequired = true
    }

    if (!vm.nameShown) {
      vm.nameRequired = false
    }
    if (!vm.descriptionShown) {
      vm.descriptionRequired = false
    }

    if (vm.nameRequired) {
      vm.nameLabel += ' *'
      vm.nameLabelClass += ' required'
    }
    if (vm.descriptionRequired) {
      vm.descriptionLabel += ' *'
      vm.descriptionLabelClass += ' required'
    }
  }

  function save () {
    VmsService.createSnapshots(vm.vm.id, vm.modalData).then(success, failure)
  }

  function success (response) {
    vm.close()
    $state.go($state.current, {}, {reload: true})
    EventNotifications.batch(response.results, __('Creating snapshot.'), __('Error creating snapshot.'))
  }

  function failure (response) {
    EventNotifications.error(__('There was an error creating the snapshot.') + response.message)
  }
}
<|endoftext|>


<commit_before>define(
  'ephox.jax.response.JsonResponse',

  [
    'ephox.katamari.api.Result',
    'ephox.sand.api.JSON'
  ],

  function (Result, JSON) {
    var parse = function (text) {
      try {
        var parsed = JSON.parse(text);
        return Result.value(parsed);
      } catch (err) {
        return Result.error('Response was not JSON');
      }
    };
    return {
      parse: parse
    };
  }
);
<commit_msg>whitespace<commit_after>define(
  'ephox.jax.response.JsonResponse',

  [
    'ephox.katamari.api.Result',
    'ephox.sand.api.JSON'
  ],

  function (Result, JSON) {
    var parse = function (text) {
      try {
        var parsed = JSON.parse(text);
        return Result.value(parsed);
      } catch (err) {
        return Result.error('Response was not JSON');
      }
    };

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


<commit_before>// http://stylelint.io/user-guide/rules/

'use strict';

module.exports = {
  rules: {
    'color-hex-case'  : 'lower',
    'color-hex-length': 'short',

    // 'color-named':

    'font-family-name-quotes': 'always-where-recommended',
    'font-weight-notation'   : 'named-where-possible',

    'function-calc-no-unspaced-operator'               : true,
    'function-comma-newline-after'                     : 'never-multi-line',
    'function-comma-newline-before'                    : 'never-multi-line',
    'function-comma-space-after'                       : 'always',
    'function-comma-space-before'                      : 'never',
    'function-linear-gradient-no-nonstandard-direction': true,
    'function-max-empty-lines'                         : 0,
    'function-name-case'                               : 'lower',
    'function-parentheses-newline-inside'              : 'always-multi-line',
    'function-parentheses-space-inside'                : 'never-single-line',
    'function-url-no-scheme-relative'                  : true,
    'function-url-quotes'                              : 'always',
    'function-url-scheme-whitelist'                    : ['http', 'https', 'data'],

    'number-leading-zero'     : 'never',
    'number-max-precision'    : 2,
    'number-no-trailing-zeros': true,

    'string-no-newline': true,
    'string-quotes'    : 'double',

    'length-zero-no-unit': true,

    'time-no-imperceptible': true,

    'unit-case'      : 'lower',
    'unit-no-unknown': true,

    'value-keyword-case'             : 'lower',
    'value-no-vendor-prefix'         : true, // please use autoprefixer
    'value-list-comma-newline-after' : 'always-multi-line',
    'value-list-comma-newline-before': 'never-multi-line',
    'value-list-comma-space-after'   : 'always',
    'value-list-comma-space-before'  : 'never',
    'value-list-max-empty-lines'     : 0,

    'custom-property-empty-line-before': 'never',
    'custom-property-no-outside-root'  : true,

    'shorthand-property-no-redundant-values': true,

    'property-case'            : 'lower',
    'property-no-unknown'      : true,
    'property-no-vendor-prefix': true,

    'keyframe-declaration-no-important': true,

    'declaration-bang-space-after'  : 'never',
    'declaration-bang-space-before' : 'always',
    'declaration-colon-space-after' : 'always',
    'declaration-colon-space-before': 'never',
    'declaration-no-important'      : true,

    'declaration-block-no-duplicate-properties'         : true,
    'declaration-block-no-redundant-longhand-properties': true,
    'declaration-block-no-shorthand-property-overrides' : true,
    'declaration-block-properties-order'                : 'alphabetical',
    'declaration-block-semicolon-newline-after'         : 'always',
    'declaration-block-semicolon-newline-before'        : 'never-multi-line',
    'declaration-block-semicolon-space-after'           : 'always-single-line',
    'declaration-block-semicolon-space-before'          : 'never',

    // 'declaration-block-single-line-max-declarations': 1,
    'declaration-block-trailing-semicolon': 'always',

    'block-closing-brace-empty-line-before': 'never',
    'block-closing-brace-newline-after'    : 'always',
    'block-closing-brace-newline-before'   : 'always',
    'block-closing-brace-space-after'      : 'never-single-line',
    'block-closing-brace-space-before'     : 'never-single-line',
    'block-no-empty'                       : true,
    'block-no-single-line'                 : true,
    'block-opening-brace-newline-after'    : 'always',
    'block-opening-brace-newline-before'   : 'never-single-line',
    'block-opening-brace-space-after'      : 'never-single-line',
    'block-opening-brace-space-before'     : 'always',

    'selector-attribute-brackets-space-inside'   : 'never',
    'selector-attribute-operator-space-after'    : 'never',
    'selector-attribute-operator-space-before'   : 'never',
    'selector-attribute-quotes'                  : 'always',
    'selector-combinator-space-after'            : 'always',
    'selector-combinator-space-before'           : 'always',
    'selector-descendant-combinator-no-non-space': true,
    'selector-max-compound-selectors'            : 3,
    'selector-no-empty'                          : true,
    'selector-no-id'                             : true,
    'selector-no-qualifying-type'                : true,

    // 'selector-no-type': true,
    'selector-no-universal'                         : true,
    'selector-no-vendor-prefix'                     : true,
    'selector-pseudo-class-case'                    : 'lower',
    'selector-pseudo-class-no-unknown'              : true,
    'selector-pseudo-class-parentheses-space-inside': 'never',
    'selector-pseudo-element-case'                  : 'lower',
    'selector-pseudo-element-colon-notation'        : 'single',
    'selector-pseudo-element-no-unknown'            : true,
    'selector-root-no-composition'                  : true,
    'selector-type-case'                            : 'lower',
    'selector-type-no-unknown'                      : true,
    'selector-max-empty-lines'                      : 0,

    'selector-list-comma-newline-after' : 'always',
    'selector-list-comma-newline-before': 'never-multi-line',
    'selector-list-comma-space-after'   : 'always-single-line',
    'selector-list-comma-space-before'  : 'never',

    'root-no-standard-properties': true,

    'rule-empty-line-before': ['always-multi-line', {
      except: [
        'after-single-line-comment',
        'first-nested'
      ]
    }],

    'media-feature-colon-space-after'          : 'always',
    'media-feature-colon-space-before'         : 'never',
    'media-feature-name-case'                  : 'lower',
    'media-feature-name-no-unknown'            : true,
    'media-feature-name-no-vendor-prefix'      : true,
    'media-feature-no-missing-punctuation'     : true,
    'media-feature-parentheses-space-inside'   : 'never',
    'media-feature-range-operator-space-after' : 'always',
    'media-feature-range-operator-space-before': 'always',

    // 'custom-media-pattern': []

    'media-query-list-comma-newline-after' : 'always-multi-line',
    'media-query-list-comma-newline-before': 'never-multi-line',
    'media-query-list-comma-space-after'   : 'always',
    'media-query-list-comma-space-before'  : 'never',

    'at-rule-name-case'              : 'lower',
    'at-rule-name-newline-after'     : 'always-multi-line',
    'at-rule-name-space-after'       : 'always',
    'at-rule-no-unknown'             : true,
    'at-rule-no-vendor-prefix'       : true,
    'at-rule-semicolon-newline-after': 'always',

    'stylelint-disable-reason': 'always-before',

    'comment-empty-line-before': ['always', {
      except: ['first-nested']
    }],
    'comment-no-empty': true,

    'indentation'                     : 2,
    'max-empty-lines'                 : 1,
    'max-line-length'                 : 80,
    'max-nesting-depth'               : 3,
    'no-browser-hacks'                : true,
    'no-descending-specificity'       : true,
    'no-duplicate-selectors'          : true,
    'no-empty-source'                 : true,
    'no-eol-whitespace'               : true,
    'no-extra-semicolons'             : true,
    'no-indistinguishable-colors'     : true,
    'no-invalid-double-slash-comments': true,
    'no-missing-end-of-source-newline': true,
    'no-unknown-animations'           : true
  }
};
<commit_msg>feat: delete depricated rules<commit_after>// http://stylelint.io/user-guide/rules/

'use strict';

module.exports = {
  rules: {
    'color-hex-case'  : 'lower',
    'color-hex-length': 'short',

    // 'color-named':

    'font-family-name-quotes': 'always-where-recommended',
    'font-weight-notation'   : 'named-where-possible',

    'function-calc-no-unspaced-operator'               : true,
    'function-comma-newline-after'                     : 'never-multi-line',
    'function-comma-newline-before'                    : 'never-multi-line',
    'function-comma-space-after'                       : 'always',
    'function-comma-space-before'                      : 'never',
    'function-linear-gradient-no-nonstandard-direction': true,
    'function-max-empty-lines'                         : 0,
    'function-name-case'                               : 'lower',
    'function-parentheses-newline-inside'              : 'always-multi-line',
    'function-parentheses-space-inside'                : 'never-single-line',
    'function-url-no-scheme-relative'                  : true,
    'function-url-quotes'                              : 'always',
    'function-url-scheme-whitelist'                    : ['http', 'https', 'data'],

    'number-leading-zero'     : 'never',
    'number-max-precision'    : 2,
    'number-no-trailing-zeros': true,

    'string-no-newline': true,
    'string-quotes'    : 'double',

    'length-zero-no-unit': true,

    'time-no-imperceptible': true,

    'unit-case'      : 'lower',
    'unit-no-unknown': true,

    'value-keyword-case'             : 'lower',
    'value-no-vendor-prefix'         : true, // please use autoprefixer
    'value-list-comma-newline-after' : 'always-multi-line',
    'value-list-comma-newline-before': 'never-multi-line',
    'value-list-comma-space-after'   : 'always',
    'value-list-comma-space-before'  : 'never',
    'value-list-max-empty-lines'     : 0,

    'custom-property-empty-line-before': 'never',
    'custom-property-no-outside-root'  : true,

    'shorthand-property-no-redundant-values': true,

    'property-case'            : 'lower',
    'property-no-unknown'      : true,
    'property-no-vendor-prefix': true,

    'keyframe-declaration-no-important': true,

    'declaration-bang-space-after'  : 'never',
    'declaration-bang-space-before' : 'always',
    'declaration-colon-space-after' : 'always',
    'declaration-colon-space-before': 'never',
    'declaration-no-important'      : true,

    'declaration-block-no-duplicate-properties'         : true,
    'declaration-block-no-redundant-longhand-properties': true,
    'declaration-block-no-shorthand-property-overrides' : true,
    'declaration-block-properties-order'                : 'alphabetical',
    'declaration-block-semicolon-newline-after'         : 'always',
    'declaration-block-semicolon-newline-before'        : 'never-multi-line',
    'declaration-block-semicolon-space-after'           : 'always-single-line',
    'declaration-block-semicolon-space-before'          : 'never',

    // 'declaration-block-single-line-max-declarations': 1,
    'declaration-block-trailing-semicolon': 'always',

    'block-closing-brace-empty-line-before': 'never',
    'block-closing-brace-newline-after'    : 'always',
    'block-closing-brace-newline-before'   : 'always',
    'block-closing-brace-space-after'      : 'never-single-line',
    'block-closing-brace-space-before'     : 'never-single-line',
    'block-no-empty'                       : true,
    'block-no-single-line'                 : true,
    'block-opening-brace-newline-after'    : 'always',
    'block-opening-brace-newline-before'   : 'never-single-line',
    'block-opening-brace-space-after'      : 'never-single-line',
    'block-opening-brace-space-before'     : 'always',

    'selector-attribute-brackets-space-inside'   : 'never',
    'selector-attribute-operator-space-after'    : 'never',
    'selector-attribute-operator-space-before'   : 'never',
    'selector-attribute-quotes'                  : 'always',
    'selector-combinator-space-after'            : 'always',
    'selector-combinator-space-before'           : 'always',
    'selector-descendant-combinator-no-non-space': true,
    'selector-max-compound-selectors'            : 3,
    'selector-no-empty'                          : true,
    'selector-no-id'                             : true,
    'selector-no-qualifying-type'                : true,

    // 'selector-no-type': true,
    'selector-no-universal'                         : true,
    'selector-no-vendor-prefix'                     : true,
    'selector-pseudo-class-case'                    : 'lower',
    'selector-pseudo-class-no-unknown'              : true,
    'selector-pseudo-class-parentheses-space-inside': 'never',
    'selector-pseudo-element-case'                  : 'lower',
    'selector-pseudo-element-colon-notation'        : 'single',
    'selector-pseudo-element-no-unknown'            : true,
    'selector-root-no-composition'                  : true,
    'selector-type-case'                            : 'lower',
    'selector-type-no-unknown'                      : true,
    'selector-max-empty-lines'                      : 0,

    'selector-list-comma-newline-after' : 'always',
    'selector-list-comma-newline-before': 'never-multi-line',
    'selector-list-comma-space-after'   : 'always-single-line',
    'selector-list-comma-space-before'  : 'never',

    'root-no-standard-properties': true,

    'rule-empty-line-before': ['always-multi-line', {
      except: [
        'after-single-line-comment',
        'first-nested'
      ]
    }],

    'media-feature-colon-space-after'          : 'always',
    'media-feature-colon-space-before'         : 'never',
    'media-feature-name-case'                  : 'lower',
    'media-feature-name-no-unknown'            : true,
    'media-feature-name-no-vendor-prefix'      : true,
    'media-feature-no-missing-punctuation'     : true,
    'media-feature-parentheses-space-inside'   : 'never',
    'media-feature-range-operator-space-after' : 'always',
    'media-feature-range-operator-space-before': 'always',

    // 'custom-media-pattern': []

    'media-query-list-comma-newline-after' : 'always-multi-line',
    'media-query-list-comma-newline-before': 'never-multi-line',
    'media-query-list-comma-space-after'   : 'always',
    'media-query-list-comma-space-before'  : 'never',

    'at-rule-name-case'              : 'lower',
    'at-rule-name-newline-after'     : 'always-multi-line',
    'at-rule-name-space-after'       : 'always',
    'at-rule-no-vendor-prefix'       : true,
    'at-rule-semicolon-newline-after': 'always',

    'comment-empty-line-before': ['always', {
      except: ['first-nested']
    }],
    'comment-no-empty': true,

    'indentation'                     : 2,
    'max-empty-lines'                 : 1,
    'max-line-length'                 : 80,
    'max-nesting-depth'               : 3,
    'no-browser-hacks'                : true,
    'no-descending-specificity'       : true,
    'no-duplicate-selectors'          : true,
    'no-empty-source'                 : true,
    'no-eol-whitespace'               : true,
    'no-extra-semicolons'             : true,
    'no-invalid-double-slash-comments': true,
    'no-missing-end-of-source-newline': true,
    'no-unknown-animations'           : true
  }
};
<|endoftext|>


<commit_before>var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');
var Q = require('q');

var latest = fs.readFileSync('tmp/latest').toString();
var config = require('./package.json');

var argv = process.argv.slice(2);

//todo: read config
//todo: debug in correct places
//todo: enable/disable growl
//todo: regard existing mp3

var getPage = function(url){
    var defer = Q.defer();

    request({
        url: url,
        headers:
        {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0',
            'Referer': 'http://cuenation.com'
        }
    }, function(error, response, body){
        if(response.statusCode==200){
            defer.resolve(body);
        }else{
            defer.reject(error);
        }
    });

    return defer.promise;
}

var getEpisodeMetadata = function(body, issue){

    var defer = Q.defer();

    var doc = cheerio(body);

    var list = cheerio('p.list a', doc);

    var re = /([0-9\.]+) \S([0-9]{4}\-[0-9]{2}\-[0-9]{2}).+\[Livesets\.us\]/;

    var found = false;

    list.each(function(i){

        if(i%2 == 0){
            return;
        }

        var elem = cheerio(list).eq(i);
        var title = elem.html();

        var results = re.exec(title);

        if(!results){
            return;
        }

        var episode = results[1];
        var date = results[2];

        if(!issue) {
            if(episode<=latest){
                return false;
            }
        }else{
            if(episode != issue){
                return;
            }
        }

        found = true;

        getPage('http://cuenation.com/'+elem.attr('href'))
            .then(function getComponents(body){

                var doc = cheerio(body);
                var links = cheerio('a.clear', doc);

                var cuelink = 'http://cuenation.com/'+links.eq(0).attr('href');

                var mp3Link = links.eq(1).attr('href');
                mp3Link = decodeURIComponent(mp3Link.substr(mp3Link.indexOf('=')+1));

                return [cuelink, getPage(mp3Link).then(function(body){
                    var doc = cheerio('#veri8 a', body);
                    return doc.eq(0).attr('href');
                })];

            }).spread(function(cuelink,mp3Link){
                defer.resolve({
                    episode: episode,
                    date: date,
                    cuesheet: cuelink,
                    mp3: mp3Link
                });
            });

        return false;

    });

    if(!found){
        defer.reject('episode not found');
    }

    return defer.promise;
}

var getCueSheet = function(url){
    var defer = Q.defer();

    getPage(url)
        .then(function(data){

            fs.writeFileSync('tmp/cue.cue', data);

            var parser = require('cue-parser');
            var result = parser.parse('tmp/cue.cue');

            defer.resolve(
                result
            );
        });

    return defer.promise;
}

var downloadMp3 = function(url){

    var defer = Q.defer();

    var request = require('request');
    var progress = require('request-progress');
    var ProgressBar = require('progress');

    var bar;
    var previous;

    var start = true;
    var max = 0;

    progress(request(url), {
        throttle: 2000,  // Throttle the progress event to 2000ms, defaults to 1000ms
        delay: 1000      // Only start to emit after 1000ms delay, defaults to 0ms
    })
        .on('progress', function (state) {

            if(start){
                bar = new ProgressBar('  downloading [:bar] :percent :etas', {
                    complete: '=',
                    incomplete: ' ',
                    width: 20,
                    total: state.total
                });
                start = false;
                max = state.total;
            }

            if(previous){
                bar.tick(state.received-previous);
            }

            previous = state.received;

        })
        .on('error', defer.reject)
        .pipe(fs.createWriteStream('tmp/mp3.mp3'))
        .on('close', function (err) {
            bar.tick(max-previous);

            defer.resolve('tmp/mp3.mp3');
        });

    return defer.promise;
}

var notify = function(issue, callback){
    var path = require('path');

    var Growl = require('node-notifier').Growl;

    var notifier = new Growl({
        name: 'A State of Trance' // Defaults as 'Node'
    });

    notifier.notify({
        title: 'New podcast!',
        message: 'The '+issue+' has arrived and is ready for playing!',
        icon: path.join(__dirname, 'icon.png'),
        wait: !!callback,
        sticky: true
    }, callback);

    return true;
}

var splitFiles = function(cue,mp3,data){

    var defer = Q.defer();

    var ffmpeg = require('fluent-ffmpeg');
    var slug = require('slug');

    var result = Q();

    var start = '0:0';

    var tracks = cue.files[0].tracks;
    var cwd = 'tmp/'+data.episode;
    require('fs').mkdir(cwd);

    tracks.forEach(function(i,v){

        var stamp = null;
        var duration = null;

        if(tracks[v+1]){
            var time = tracks[v+1].indexes[0].time;
            var currentTime = i.indexes[0].time

            stamp = (time.min%60)+':'+time.sec;

            if(time.min>59){
                stamp = Math.floor(time.min/60)+':'+stamp;
            }

            var nextLength = time.min*60+time.sec;
            var currentLength = currentTime.min*60+currentTime.sec;

            duration = nextLength-currentLength;
        }

        (function(start,duration,i){
            result = result.then(function(){
                var defer = Q.defer();

                console.log(i.performer, '-', i.title, start, duration);

                var o = ffmpeg(mp3)
                    .audioCodec('copy')
                    .seekInput(start);

                if(duration){
                    o.duration(duration);
                }

                var options = [
                    '-id3v2_version', '3', '-write_id3v1', '1',
                    '-metadata', 'artist='+i.performer+' ',
                    '-metadata', 'title='+i.title+' ',
                    '-metadata', 'album='+cue.title+' '
                ];
                var filename = (v<10 ? '0'+v : v)+'_'+slug(i.performer, '_')+'_-_'+slug(i.title);

                console.log(filename);

                o.outputOption(options);

                o.on('end', function(){
                    defer.resolve();
                })
                    .on('error', function(err){
                        console.log(err);
                        defer.reject()
                    })
                    .save(cwd+'/'+filename+'.mp3');

                return defer.promise;
            });
        })(start, duration, i);

        start = stamp;

    });

    result.then(function(){
        defer.resolve(data);
    });

    return defer.promise;
}

var markLatest = function(data){
    fs.writeFile('tmp/latest', data.episode);
}

var cleanup = function(){
    fs.unlink('tmp/cue.cue');
    fs.unlink('tmp/mp3.mp3');
};

var task = getPage('http://cuenation.com/?page=cues&folder=asot');

if(argv[0]){
    task = task.then(function(data){
        return getEpisodeMetadata(data, argv[0]);
    });
}else{
    task = task
        .then(getEpisodeMetadata);

}

task = task
    .then(function downloadAllFiles(data){
        return [
            getCueSheet(data.cuesheet),
            downloadMp3(data.mp3),
            data
        ];
    })
    .spread(splitFiles)
    .then(function makeDone(data){
        return [
            markLatest(data),
            cleanup(data),
            notify(data.episode)
        ];
    })
    .fail(function(err){
        console.error(err);
    });
<commit_msg>added support for cached/predownloaded cue/mp3<commit_after>var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');
var Q = require('q');

var latest = fs.readFileSync('tmp/latest').toString();
var config = require('./package.json');

var argv = process.argv.slice(2);

//todo: read config
//todo: debug in correct places
//todo: enable/disable growl

var getPage = function(url){
    var defer = Q.defer();

    request({
        url: url,
        headers:
        {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0',
            'Referer': 'http://cuenation.com'
        }
    }, function(error, response, body){
        if(response.statusCode==200){
            defer.resolve(body);
        }else{
            defer.reject(error);
        }
    });

    return defer.promise;
}

var getEpisodeMetadata = function(body, issue){

    var defer = Q.defer();

    var doc = cheerio(body);

    var list = cheerio('p.list a', doc);

    var re = /([0-9\.]+) \S([0-9]{4}\-[0-9]{2}\-[0-9]{2}).+\[Livesets\.us\]/;

    var found = false;

    list.each(function(i){

        if(i%2 == 0){
            return;
        }

        var elem = cheerio(list).eq(i);
        var title = elem.html();

        var results = re.exec(title);

        if(!results){
            return;
        }

        var episode = results[1];
        var date = results[2];

        if(!issue) {
            if(episode<=latest){
                return false;
            }
        }else{
            if(episode != issue){
                return;
            }
        }

        found = true;

        getPage('http://cuenation.com/'+elem.attr('href'))
            .then(function getComponents(body){

                var doc = cheerio(body);
                var links = cheerio('a.clear', doc);

                var cuelink = 'http://cuenation.com/'+links.eq(0).attr('href');

                var mp3Link = links.eq(1).attr('href');
                mp3Link = decodeURIComponent(mp3Link.substr(mp3Link.indexOf('=')+1));

                return [cuelink, getPage(mp3Link).then(function(body){
                    var doc = cheerio('#veri8 a', body);
                    return doc.eq(0).attr('href');
                })];

            }).spread(function(cuelink,mp3Link){
                defer.resolve({
                    episode: episode,
                    date: date,
                    cuesheet: cuelink,
                    mp3: mp3Link
                });
            });

        return false;

    });

    if(!found){
        defer.reject('episode not found');
    }

    return defer.promise;
}

var getCueSheet = function(data){

    var parser = require('cue-parser');

    if(fs.existsSync('tmp/'+data.episode+'.cue')){
        return parser.parse('tmp/'+data.episode+'.cue');
    }

    var defer = Q.defer();

    getPage(data.cuesheet)
        .then(function(body){

            fs.writeFileSync('tmp/'+data.episode+'.cue', body);

            var result = parser.parse('tmp/'+data.episode+'.cue');

            defer.resolve(
                result
            );
        });

    return defer.promise;
}

var downloadMp3 = function(data){

    if(fs.existsSync('tmp/'+data.episode+'.mp3')){
        return 'tmp/'+data.episode+'.mp3';
    }

    var defer = Q.defer();

    var request = require('request');
    var progress = require('request-progress');
    var ProgressBar = require('progress');

    var bar;
    var previous;

    var start = true;
    var max = 0;

    progress(request(data.mp3), {
        throttle: 2000,  // Throttle the progress event to 2000ms, defaults to 1000ms
        delay: 1000      // Only start to emit after 1000ms delay, defaults to 0ms
    })
        .on('progress', function (state) {

            if(start){
                bar = new ProgressBar('  downloading [:bar] :percent :etas', {
                    complete: '=',
                    incomplete: ' ',
                    width: 20,
                    total: state.total
                });
                start = false;
                max = state.total;
            }

            if(previous){
                bar.tick(state.received-previous);
            }

            previous = state.received;

        })
        .on('error', defer.reject)
        .pipe(fs.createWriteStream('tmp/'+data.episode+'.mp3'))
        .on('close', function (err) {
            bar.tick(max-previous);

            defer.resolve('tmp/'+data.episode+'.mp3');
        });

    return defer.promise;
}

var notify = function(data, callback){
    var path = require('path');

    var Growl = require('node-notifier').Growl;

    var notifier = new Growl({
        name: 'A State of Trance' // Defaults as 'Node'
    });

    notifier.notify({
        title: 'New podcast!',
        message: 'The '+data.episode+' has arrived and is ready for playing!',
        icon: path.join(__dirname, 'icon.png'),
        wait: !!callback,
        sticky: true
    }, callback);

    return true;
}

var splitFiles = function(cue,mp3,data){

    var defer = Q.defer();

    var ffmpeg = require('fluent-ffmpeg');
    var slug = require('slug');

    var result = Q();

    var start = '0:0';

    var tracks = cue.files[0].tracks;
    var cwd = 'tmp/'+data.episode;
    require('fs').mkdir(cwd);

    tracks.forEach(function(i,v){

        var stamp = null;
        var duration = null;

        if(tracks[v+1]){
            var time = tracks[v+1].indexes[0].time;
            var currentTime = i.indexes[0].time

            stamp = (time.min%60)+':'+time.sec;

            if(time.min>59){
                stamp = Math.floor(time.min/60)+':'+stamp;
            }

            var nextLength = time.min*60+time.sec;
            var currentLength = currentTime.min*60+currentTime.sec;

            duration = nextLength-currentLength;
        }

        (function(start,duration,i){
            result = result.then(function(){
                var defer = Q.defer();

                console.log(i.performer, '-', i.title, start, duration);

                var o = ffmpeg(mp3)
                    .audioCodec('copy')
                    .seekInput(start);

                if(duration){
                    o.duration(duration);
                }

                var options = [
                    '-id3v2_version', '3', '-write_id3v1', '1',
                    '-metadata', 'artist='+i.performer+' ',
                    '-metadata', 'title='+i.title+' ',
                    '-metadata', 'album='+cue.title+' '
                ];
                var filename = (v<10 ? '0'+v : v)+'_'+slug(i.performer, '_')+'_-_'+slug(i.title);

                console.log(filename);

                o.outputOption(options);

                o.on('end', function(){
                    defer.resolve();
                })
                    .on('error', function(err){
                        console.log(err);
                        defer.reject()
                    })
                    .save(cwd+'/'+filename+'.mp3');

                return defer.promise;
            });
        })(start, duration, i);

        start = stamp;

    });

    result.then(function(){
        defer.resolve(data);
    });

    return defer.promise;
}

var markLatest = function(data){
    fs.writeFile('tmp/latest', data.episode);
}

var cleanup = function(data){
    fs.unlink('tmp/'+data.episode+'.cue');
    fs.unlink('tmp/'+data.episode+'.mp3');
};

var task = getPage('http://cuenation.com/?page=cues&folder=asot');

if(argv[0]){
    task = task.then(function(data){
        return getEpisodeMetadata(data, argv[0]);
    });
}else{
    task = task
        .then(getEpisodeMetadata);

}

task = task
    .then(function downloadAllFiles(data){
        return [
            getCueSheet(data),
            downloadMp3(data),
            data
        ];
    })
    .spread(splitFiles)
    .then(function makeDone(data){
        return [
            markLatest(data),
            //cleanup(data),
            notify(data)
        ];
    })
    .fail(function(err){
        console.error(err);
    });
<|endoftext|>


<commit_before>module.exports = Automata;

function Automata () {
  var ctx = {}

  var neighbourhoods = ['000', '001', '010', '011', '100', '101', '110', '111']

  // need some automata accessible variables
  ctx.automata = []
  ctx.rule

  // create automata lattice based on size (number of cells) provided
  // run over a set number of a given life
  ctx.set = function (size, rule, life) {
    var lattice = []
    lattice = ctx.setState(lattice, size)
    lattice = ctx.setNeighbours(lattice)
    ctx.rule = ctx.getRulesBinary(rule)
    // automata stores each lattice procedurely
    ctx.automata.push(lattice)
    // TODO: consider calling this function outside of the library instead
    // that way user has control
    ctx.automata = ctx.runRules(ctx.automata, life)
    console.log(ctx.automata)

    return ctx.set
  }

  // get a random state and create all cells
  ctx.setState = function (lattice, size) {
    for (var num = 0; num < size; num++) {
      var cell = {}
      cell.state = getRandomState()
      lattice.push(cell)
    }
    return lattice
  }

  ctx.setNeighbours = function (lattice) {
    return lattice.map( function (cell, index, array) {
      var lastEl = lattice.length-1

      if (index === 0) {
        cell.left = lattice[lastEl].state
        cell.right = lattice[index+1].state
        return cell
      }

      if (index === lastEl) {
        cell.right = lattice[0].state
        cell.left = lattice[index-1].state
        return cell
      }

      cell.right = lattice[index-1].state
      cell.left = lattice[index+1].state

      return cell
    })
  }

  // get a neighbour binary from current neighbours \o/
  // thank you @aredridel for the pro-tip
  ctx.getNeighbours = function (cell, right, left) {
    var hood = (left ? 1 : 0) | (cell ? 2 : 0) | (right ? 4 : 0)
    return neighbourhoods[hood]
  }

  // determine rules for a given lattice
  ctx.getRulesBinary = function (num) {
    // let's convert a number to 8-bit binary
    // so pass '10' to parseInt for decimal
    // and '2' toString for binary
    // pass an empty 8 digit string to force into 8-bit
    return ("000000000" + parseInt(num, 10).toString(2)).substr(-8)
  }

  // let's see which rule we are currently looking at
  ctx.getRule = function (neighbourhood) {
    var currentRule
    var rule = [...ctx.rule]

    neighbourhoods.forEach( function (hood, index) {
      if (hood === neighbourhood) {
        currentRule = rule[index]
      }
    })

    return currentRule
  }

  ctx.nextLife = function (cell) {
    var hood = ctx.getNeighbours(cell.state, cell.right, cell.left)
    var rule = ctx.getRule(hood)
    return {
      state: rule
    }
  }

  ctx.runRules = function (automata, life, currentLife) {
    // can also pass an automata externally
    if (!currentLife) currentLife = 0
    var automaton = automata || ctx.automata
    // get the last array
    var lastLife = automaton.slice(-1)[0]

    var nextLife = lastLife.map(ctx.nextLife)
    nextLife = ctx.setNeighbours(nextLife)
    automaton.push(nextLife)

    if (currentLife < life) ctx.runRules(automaton, life, ++currentLife)

    return automaton
  }

  function getRandomState () {
    var min = 0
    var max = 1
    return Math.floor(Math.random() * (max - min + 1)) + min
  }

  return ctx
}

Automata().set(20, 110, 2)
<commit_msg>join them 'hoods to get the current state of thangs<commit_after>module.exports = Automata;

function Automata () {
  var ctx = {}

  var neighbourhoods = [ '111', '110', '101', '100', '011', '010', '001', '000' ]

  // need some automata accessible variables
  ctx.automata = []
  ctx.rule

  // create automata lattice based on size (number of cells) provided
  // run over a set number of a given life
  ctx.set = function (size, rule, life) {
    var lattice = []
    lattice = ctx.setState(lattice, size)
    lattice = ctx.setNeighbours(lattice)
    ctx.rule = ctx.getRulesBinary(rule)
    // automata stores each lattice procedurely
    ctx.automata.push(lattice)
    // TODO: consider calling this function outside of the library instead
    // that way user has control
    ctx.automata = ctx.runRules(ctx.automata, life)

    return ctx.set
  }

  // get a random state and create all cells
  ctx.setState = function (lattice, size) {
    for (var num = 0; num < size; num++) {
      var cell = {}
      cell.state = getRandomState()
      lattice.push(cell)
    }
    return lattice
  }

  ctx.setNeighbours = function (lattice) {
    return lattice.map( function (cell, index, array) {
      var lastEl = lattice.length-1

      if (index === 0) {
        cell.left = lattice[lastEl].state
        cell.right = lattice[index+1].state
        return cell
      }

      if (index === lastEl) {
        cell.right = lattice[0].state
        cell.left = lattice[index-1].state
        return cell
      }

      cell.right = lattice[index-1].state
      cell.left = lattice[index+1].state

      return cell
    })
  }

  ctx.runRules = function (automata, life, currentLife) {
    // want to take in automata externally
    var automaton = automata || ctx.automata
    var lastLife = automaton.slice(-1)[0]
    var nextLife = lastLife.map(ctx.nextLife)
    nextLife = ctx.setNeighbours(nextLife)
    automaton.push(nextLife)

    if (!currentLife) currentLife = 0
    if (currentLife < life) ctx.runRules(automaton, life, ++currentLife)

    return automaton
  }

  ctx.nextLife = function (cell, index) {
    var hood = ctx.getNeighbours(cell.state, cell.right, cell.left)
    var rule = ctx.getRule(hood)

    return {
      state: rule
    }
  }

  ctx.getNeighbours = function (cell, right, left) {
    var current = []
    current.push.apply(current, [right, cell, left])
    var currentHood = current.join('')

    return currentHood
  }

  // let's see which rule we are currently looking at
  ctx.getRule = function (neighbourhood) {
    var currentState = null
    var rule = [...ctx.rule]
    neighbourhoods.forEach( function (hood, index) {
      if (hood === neighbourhood) {
        currentState = rule[index]
      }
    })

    return currentState
  }

  // determine rules for a given lattice
  ctx.getRulesBinary = function (num) {
    // let's convert a number to an 8-bit bae
    var rule = ('000000000' + parseInt(num, 10).toString(2)).substr(-8)
    // let's reverse it, b/c our neighbourhoods are reversed too
    return rule
  }

  function getRandomState () {
    var min = 0
    var max = 1
    return Math.floor(Math.random() * (max - min + 1)) + min
  }

  return ctx
}
<|endoftext|>


<commit_before>var nbind = require('nbind');
var binding = nbind.init(__dirname);
var Ui = binding.lib.Ui;

var loopRunning = false;

module.exports = binding.lib;

function stopLoop() {
	if (!loopRunning) {
		return;
	}
	clearInterval(frequencyCheck);
	boost();
	Ui.quit();
	console.log('quit done')
}

var boosted = false;
function boost() {
	boosted = true;
	console.log('boost')
}

var frequencyCheck = null;

function startLoop(cb) {
	var counter = 0;

	function step() {
		counter++;
		if (Ui.mainStep(false)) {
			if (boosted) {
				setImmediate(step);
				boosted = false;
			} else {
				setTimeout(step);
			}
		} else if (cb) {
			console.log('exit')
			cb();
		}
	}

	if (loopRunning) {
		return;
	}

	frequencyCheck = setInterval(function () {
		console.log(counter + "Hz");
		counter = 0;
	}, 1000);

	loopRunning = true;
	Ui.mainSteps();
	step();
}

function Color(r, g, b, a) {
	this.r = r;
	this.g = g;
	this.b = b;
	this.a = a;
}

Color.prototype.fromJS = function fromJS(output) {
	output(this.r, this.g, this.b, this.a);
};

binding.bind('Color', Color);

function Point(x, y) {
	this.x = x;
	this.y = y;
}

Point.prototype.fromJS = function fromJS(output) {
	output(this.x, this.y);
};

binding.bind('Point', Point);

function PointDouble(x, y) {
	this.x = x;
	this.y = y;
}

PointDouble.prototype.fromJS = function fromJS(output) {
	output(this.x, this.y);
};

binding.bind('PointDouble', PointDouble);

function Size(w, h) {
	this.w = w;
	this.h = h;
}

Size.prototype.fromJS = function fromJS(output) {
	output(this.w, this.h);
};

binding.bind('Size', Size);

function SizeDouble(w, h) {
	this.w = w;
	this.h = h;
}

SizeDouble.prototype.fromJS = function fromJS(output) {
	output(this.w, this.h);
};

binding.bind('SizeDouble', SizeDouble);

var textWeight = {
	thin: 0,
	ultraLight: 1,
	light: 2,
	book: 3,
	normal: 4,
	medium: 5,
	semiBold: 6,
	bold: 7,
	utraBold: 8,
	heavy: 9,
	ultraHeavy: 10
};

var textItalic = {
	normal: 0,
	oblique: 1,
	italic: 2
};

var textStretch = {
	ultraCondensed: 0,
	extraCondensed: 1,
	condensed: 2,
	semiCondensed: 3,
	normal: 4,
	semiExpanded: 5,
	expanded: 6,
	extraExpanded: 7,
	ultraExpanded: 8
};

module.exports.boost = boost;
module.exports.textStretch = textStretch;
module.exports.textItalic = textItalic;
module.exports.textWeight = textWeight;
module.exports.Size = Size;
module.exports.Point = Point;
module.exports.Color = Color;
module.exports.startLoop = startLoop;
module.exports.stopLoop = stopLoop;
<commit_msg>tweak<commit_after>var nbind = require('nbind');
var binding = nbind.init(__dirname);
var Ui = binding.lib.Ui;

var loopRunning = false;
var frequencyCheck = null;

module.exports = binding.lib;

function stopLoop() {
	if (!loopRunning) {
		return;
	}
	clearInterval(frequencyCheck);
	boost();
	Ui.quit();
	console.log('quit done')
}

var boosted = false;
function boost() {
	boosted = true;
	console.log('boost')
}

function startLoop(cb) {
	var counter = 0;

	function step() {
		counter++;
		if (Ui.mainStep(false)) {
			if (boosted) {
				setImmediate(step);
				boosted = false;
			} else {
				setTimeout(step);
			}
		} else if (cb) {
			console.log('exit')
			cb();
		}
	}

	if (loopRunning) {
		return;
	}

	frequencyCheck = setInterval(function () {
		console.log(counter + "Hz");
		counter = 0;
	}, 1000);

	loopRunning = true;
	Ui.mainSteps();
	step();
}

function Color(r, g, b, a) {
	this.r = r;
	this.g = g;
	this.b = b;
	this.a = a;
}

Color.prototype.fromJS = function fromJS(output) {
	output(this.r, this.g, this.b, this.a);
};

binding.bind('Color', Color);

function Point(x, y) {
	this.x = x;
	this.y = y;
}

Point.prototype.fromJS = function fromJS(output) {
	output(this.x, this.y);
};

binding.bind('Point', Point);

function PointDouble(x, y) {
	this.x = x;
	this.y = y;
}

PointDouble.prototype.fromJS = function fromJS(output) {
	output(this.x, this.y);
};

binding.bind('PointDouble', PointDouble);

function Size(w, h) {
	this.w = w;
	this.h = h;
}

Size.prototype.fromJS = function fromJS(output) {
	output(this.w, this.h);
};

binding.bind('Size', Size);

function SizeDouble(w, h) {
	this.w = w;
	this.h = h;
}

SizeDouble.prototype.fromJS = function fromJS(output) {
	output(this.w, this.h);
};

binding.bind('SizeDouble', SizeDouble);

var textWeight = {
	thin: 0,
	ultraLight: 1,
	light: 2,
	book: 3,
	normal: 4,
	medium: 5,
	semiBold: 6,
	bold: 7,
	utraBold: 8,
	heavy: 9,
	ultraHeavy: 10
};

var textItalic = {
	normal: 0,
	oblique: 1,
	italic: 2
};

var textStretch = {
	ultraCondensed: 0,
	extraCondensed: 1,
	condensed: 2,
	semiCondensed: 3,
	normal: 4,
	semiExpanded: 5,
	expanded: 6,
	extraExpanded: 7,
	ultraExpanded: 8
};

module.exports.boost = boost;
module.exports.textStretch = textStretch;
module.exports.textItalic = textItalic;
module.exports.textWeight = textWeight;
module.exports.Size = Size;
module.exports.Point = Point;
module.exports.Color = Color;
module.exports.startLoop = startLoop;
module.exports.stopLoop = stopLoop;
<|endoftext|>


<commit_before>var smagenBot = require('./bin/smagenBot'),
    config    = require('./config.json');

var bot = new smagenBot(config);

function check() {
  bot.getUpdates(function (err, body) {
    if (!err) {
      if (body.result.length > 0) {
        //Watch the last message
        var current = body.result[body.result.length-1];
        //From my chat and nobody else
        if(current.update_id >= bot.offset) {
          bot.chatId = current.message.chat.id;
          bot.offset = current.update_id + 1;
          if(!bot.username) {
            bot.makeAction(current.message.text);
          } else {
            if (bot.username.indexOf(current.message.from.username) !== -1) {
              bot.makeAction(current.message.text);
            } else {
              bot.sendMessage("Only "+JSON.stringify(config.username)+" can use me!");
            }
          }
        }
      }
    }
  });
}

setInterval(check, config.interval || 1000);
<commit_msg>error on body<commit_after>var smagenBot = require('./bin/smagenBot'),
    config    = require('./config.json');

var bot = new smagenBot(config);

function check() {
  bot.getUpdates(function (err, body) {
    if (!err && body !== null) {
      if (body.result.length > 0) {
        //Watch the last message
        var current = body.result[body.result.length-1];
        //From my chat and nobody else
        if(current.update_id >= bot.offset) {
          bot.chatId = current.message.chat.id;
          bot.offset = current.update_id + 1;
          if(!bot.username) {
            bot.makeAction(current.message.text);
          } else {
            if (bot.username.indexOf(current.message.from.username) !== -1) {
              bot.makeAction(current.message.text);
            } else {
              bot.sendMessage("Only "+JSON.stringify(config.username)+" can use me!");
            }
          }
        }
      }
    } else {
      throw new Error("Error on getUpdates");
    }
  });
}

setInterval(check, config.interval || 1000);
<|endoftext|>


<commit_before>'use strict'

const ms = require('ms')
const Koa = require('koa')
const body = require('koa-bodyparser')
const _static = require('koa-static')
const session = require('koa-session')
const compress = require('koa-compress')

// Wrap up an express app.
const ozymandias = module.exports = function () {
  const app = new Koa()

  // Secrets!
  app.keys = [process.env.SECRET]

  // Trust proxy headers.
  app.proxy = true

  // Handle errors.
  app.use(require('./errors'))

  // Security headers
  app.use(require('./security'))

  // Compress responses by default.
  app.use(compress())

  // Add CORS headers to assets for subresource integrity check.
  app.use(require('./assets/cors'))

  // Static Assets
  app.use(_static('public', {maxAge: ms('1y')}))

  // S3 Assets
  app.use(require('./assets/proxy'))

  // Parse the request body.
  app.use(body())

  // Cookie Session
  app.use(session(app, {
    key: process.env.ID,
    maxAge: ms('30d')
  }))

  app.use(async (_, next) => {
    // Vary on the accept header
    _.vary('accept')

    // No caching by default
    _.set('cache-control', 'private, no-store, no-cache, max-age=0, must-revalidate')

    await next()
  })

  // Extend context.
  Object.assign(app.context,
    require('./helpers'),
    require('./mail'),
    require('./react')
  )

  // Client state!
  app.use(async (_, next) => {
    _.state.client = {}
    await next()
  })

  // Who's the user?
  app.use(require('./current-user'))

  return app
}

// DB instance
ozymandias.db = require('./db/instance')
<commit_msg>clean up<commit_after>'use strict'

const ms = require('ms')
const Koa = require('koa')
const body = require('koa-bodyparser')
const _static = require('koa-static')
const session = require('koa-session')
const compress = require('koa-compress')

// Wrap up an express app.
const ozymandias = module.exports = function () {
  const app = new Koa()

  // Secrets!
  app.keys = [process.env.SECRET]

  // Trust proxy headers.
  app.proxy = true

  // Handle errors.
  app.use(require('./errors'))

  // Security headers
  app.use(require('./security'))

  // Compress responses by default.
  app.use(compress())

  // Add CORS headers to assets for subresource integrity check.
  app.use(require('./assets/cors'))

  // Static Assets
  app.use(_static('public', {maxAge: ms('1y')}))

  // S3 Assets
  app.use(require('./assets/proxy'))

  // Parse the request body.
  app.use(body())

  // Cookie Session
  app.use(session(app, {
    key: process.env.ID,
    maxAge: ms('30d')
  }))

  app.use(async (_, next) => {
    // Vary on the accept header
    _.vary('accept')

    // No caching by default
    _.set('cache-control', 'private, no-store, no-cache, max-age=0, must-revalidate')

    // Client state!
    _.state.client = {}

    await next()
  })

  // Extend context.
  Object.assign(app.context,
    require('./helpers'),
    require('./mail'),
    require('./react')
  )

  // Who's the user?
  app.use(require('./current-user'))

  return app
}

// DB instance
ozymandias.db = require('./db/instance')
<|endoftext|>


<commit_before>var babelify = require('babelify');
var brfs = require('brfs');
var browserify = require('browserify');
var chalk = require('chalk');
var del = require('del');
var gulp = require('gulp');
var gutil = require('gulp-util');
var less = require('gulp-less');
var merge = require('merge-stream');
var plumber = require('gulp-plumber');
var shell = require('gulp-shell');
var source = require('vinyl-source-stream');
var watchify = require('watchify');

/**
 * Check that a compatible version of gulp is available in the project
 */

function fatal(err) {
	var msg = '\n\n';
	if (Array.isArray(err)) {
		err.forEach(function(i) {
			msg += i + '\n\n';
		});
	} else {
		msg += (err || 'Fatal error, bailing.') + '\n\n';
	}
	console.log(msg);
	process.exit(1);
}

try {
	var projectGulpVersion = require(module.parent.paths[0] + '/gulp/package.json').version;
} catch(e) {
	// If we can't find gulp in the parent project, it's a fatal problem.
	fatal(
		'You do not seem to have Gulp installed in your project.',
		'Please add gulp ^' + packageGulpVersion + ' to your package.json, npm install and try again.'
	);
}

/**
 * This package exports a function that binds tasks to a gulp instance
 */

module.exports = function(gulp) {

	/**
	* Clean
	*/

	gulp.task('clean', function() {
		del(['./www/*']);
	});

	/**
	* Preview Server
	*/

	gulp.task('serve', function() {
		var express = require('express');
		var app = express();

		app.use(express.static('./www'));

		var server = app.listen(process.env.PORT || 8000, function() {
			console.log('Local Server ready on port %d', server.address().port);
		});
	});

	/**
	* Build
	*/

	gulp.task('less', function() {
		return gulp.src('src/css/app.less')
		.pipe(less())
		.pipe(gulp.dest('www/css'));
	});

	gulp.task('html', function() {
		return gulp.src('src/index.html')
		.pipe(gulp.dest('www'));
	});

	gulp.task('images', function() {
		return gulp.src('src/img/**')
		.pipe(gulp.dest('www/img'));
	});

	gulp.task('fonts', function() {
		return gulp.src('src/fonts/**')
		.pipe(gulp.dest('www/fonts'));
	});

	function doBundle(target, name, dest) {
		return target.bundle()
			.on('error', function(e) {
				gutil.log('Browserify Error', e.message);
			})
			.pipe(source(name))
			.pipe(gulp.dest(dest));
	}

	function watchBundle(target, name, dest) {
		return watchify(target)
			.on('update', function (scriptIds) {
				scriptIds = scriptIds
				.filter(function(i) { return i.substr(0,2) !== './' })
				.map(function(i) { return chalk.blue(i.replace(__dirname, '')) });
				if (scriptIds.length > 1) {
					gutil.log(scriptIds.length + ' Scripts updated:\n* ' + scriptIds.join('\n* ') + '\nrebuilding...');
				} else {
					gutil.log(scriptIds[0] + ' updated, rebuilding...');
				}
				doBundle(target, name, dest);
			})
			.on('time', function (time) {
				gutil.log(chalk.green(name + ' built in ' + (Math.round(time / 10) / 100) + 's'));
			});
	}

	function buildApp(dev) {

		var opts = dev ? {
			cache: {},
			packageCache: {},
			debug: process.env.NODE_ENV !== 'production'
		} : {};

		var src = './src/js';
		var dest = './www/js';
		var name = 'app.js';

		var appBundle = browserify(opts)
			.add([src, name].join('/'))
			.transform(babelify)
			.transform(brfs);

		var reactBundle = browserify();
		['react','react/addons'].forEach(function(pkg) {
			appBundle.exclude(pkg);
			reactBundle.require(pkg);
		});

		if (dev) {
			watchBundle(appBundle, name, dest);
		}

		return merge(
			doBundle(reactBundle, 'react.js', dest),
			doBundle(appBundle, name, dest)
		);

	}

	gulp.task('scripts', function() {
		return buildApp();
	});

	gulp.task('watch-scripts', function() {
		return buildApp(true);
	});

	gulp.task('build', ['html', 'images', 'fonts', 'less', 'scripts']);

	gulp.task('watch', ['html', 'images', 'fonts', 'less', 'watch-scripts'], function() {
		gulp.watch(['src/index.html'], ['html']);
		gulp.watch(['src/css/**/*.less'], ['less']);
		gulp.watch(['src/img/**/*.*'], ['images']);
		gulp.watch(['src/fonts/**/*.*'], ['fonts']);
	});

	gulp.task('dev', ['watch', 'serve']);

	/**
	* Cordova
	*/

	gulp.task('prepare', ['html', 'images', 'fonts', 'less', 'scripts'], function() {
		return gulp.src('')
		.pipe(plumber())
		.pipe(shell(['cordova prepare'], { cwd: __dirname }));
	});

}
<commit_msg>remove unnecessary gulp check<commit_after>var babelify = require('babelify');
var brfs = require('brfs');
var browserify = require('browserify');
var chalk = require('chalk');
var del = require('del');
var gutil = require('gulp-util');
var less = require('gulp-less');
var merge = require('merge-stream');
var plumber = require('gulp-plumber');
var shell = require('gulp-shell');
var source = require('vinyl-source-stream');
var watchify = require('watchify');

/**
 * This package exports a function that binds tasks to a gulp instance
 */

module.exports = function(gulp) {

	/**
	* Clean
	*/

	gulp.task('clean', function() {
		del(['./www/*']);
	});

	/**
	* Preview Server
	*/

	gulp.task('serve', function() {
		var express = require('express');
		var app = express();

		app.use(express.static('./www'));

		var server = app.listen(process.env.PORT || 8000, function() {
			console.log('Local Server ready on port %d', server.address().port);
		});
	});

	/**
	* Build
	*/

	gulp.task('less', function() {
		return gulp.src('src/css/app.less')
		.pipe(less())
		.pipe(gulp.dest('www/css'));
	});

	gulp.task('html', function() {
		return gulp.src('src/index.html')
		.pipe(gulp.dest('www'));
	});

	gulp.task('images', function() {
		return gulp.src('src/img/**')
		.pipe(gulp.dest('www/img'));
	});

	gulp.task('fonts', function() {
		return gulp.src('src/fonts/**')
		.pipe(gulp.dest('www/fonts'));
	});

	function doBundle(target, name, dest) {
		return target.bundle()
			.on('error', function(e) {
				gutil.log('Browserify Error', e.message);
			})
			.pipe(source(name))
			.pipe(gulp.dest(dest));
	}

	function watchBundle(target, name, dest) {
		return watchify(target)
			.on('update', function (scriptIds) {
				scriptIds = scriptIds
				.filter(function(i) { return i.substr(0,2) !== './' })
				.map(function(i) { return chalk.blue(i.replace(__dirname, '')) });
				if (scriptIds.length > 1) {
					gutil.log(scriptIds.length + ' Scripts updated:\n* ' + scriptIds.join('\n* ') + '\nrebuilding...');
				} else {
					gutil.log(scriptIds[0] + ' updated, rebuilding...');
				}
				doBundle(target, name, dest);
			})
			.on('time', function (time) {
				gutil.log(chalk.green(name + ' built in ' + (Math.round(time / 10) / 100) + 's'));
			});
	}

	function buildApp(dev) {

		var opts = dev ? {
			cache: {},
			packageCache: {},
			debug: process.env.NODE_ENV !== 'production'
		} : {};

		var src = './src/js';
		var dest = './www/js';
		var name = 'app.js';

		var appBundle = browserify(opts)
			.add([src, name].join('/'))
			.transform(babelify)
			.transform(brfs);

		var reactBundle = browserify();
		['react','react/addons'].forEach(function(pkg) {
			appBundle.exclude(pkg);
			reactBundle.require(pkg);
		});

		if (dev) {
			watchBundle(appBundle, name, dest);
		}

		return merge(
			doBundle(reactBundle, 'react.js', dest),
			doBundle(appBundle, name, dest)
		);

	}

	gulp.task('scripts', function() {
		return buildApp();
	});

	gulp.task('watch-scripts', function() {
		return buildApp(true);
	});

	gulp.task('build', ['html', 'images', 'fonts', 'less', 'scripts']);

	gulp.task('watch', ['html', 'images', 'fonts', 'less', 'watch-scripts'], function() {
		gulp.watch(['src/index.html'], ['html']);
		gulp.watch(['src/css/**/*.less'], ['less']);
		gulp.watch(['src/img/**/*.*'], ['images']);
		gulp.watch(['src/fonts/**/*.*'], ['fonts']);
	});

	gulp.task('dev', ['watch', 'serve']);

	/**
	* Cordova
	*/

	gulp.task('prepare', ['html', 'images', 'fonts', 'less', 'scripts'], function() {
		return gulp.src('')
		.pipe(plumber())
		.pipe(shell(['cordova prepare'], { cwd: __dirname }));
	});

}
<|endoftext|>