<commit_before>var logger = require('../lib/logger')
var Trace = require('./trace')
var utils = require('../lib/utils')

var Transaction = function (queue, name, type, options) {
  this.metadata = {}
  this.name = name
  this.type = type
  this.ended = false
  this._markDoneAfterLastTrace = false
  this._isDone = false
  this._options = options
  this.uuid = utils.generateUuid()

  this.traces = []
  this._activeTraces = {}
  this._queue = queue

  logger.log('- %c opbeat.instrumentation.transaction.ctor', 'color: #3360A3', this.name)

  // A transaction should always have a root trace spanning the entire transaction.
  this._rootTrace = this.startTrace('transaction', 'transaction', this._options)
  this._startStamp = this._rootTrace._startStamp
  this._start = this._rootTrace._start

  this.duration = this._rootTrace.duration.bind(this._rootTrace)
}

Transaction.prototype.end = function () {
  if (this.ended) {
    return
  }

  this.ended = true

  logger.log('- %c opbeat.instrumentation.transaction.end', 'color: #3360A3', this.name, Object.keys(this._activeTraces).length)

  if (Object.keys(this._activeTraces).length > 0) {
    this._markDoneAfterLastTrace = true
  } else {
    this._markAsDone()
  }
}

Transaction.prototype._markAsDone = function () {
  logger.log('- %c opbeat.instrumentation.transaction._markAsDone', 'color: #3360A3', this.name)

  if (this._isDone) {
    return
  }

  this._isDone = true

  // When all traces are finished, the transaction can be added to the queue
  var whenAllTracesFinished = this.traces.map(function (trace) {
    return trace._isFinish
  })

  Promise.all(whenAllTracesFinished).then(function () {
    logger.log('- %c opbeat.instrumentation.transaction.whenAllTracesFinished', 'color: #3360A3', this.name)

    this._rootTrace.end()

    this._adjustStartToEarliestTrace()
    this._adjustDurationToLongestTrace()

    this._queue.add(this)
  }.bind(this))
}

Transaction.prototype._adjustStartToEarliestTrace = function () {
  var trace = getEarliestTrace(this.traces)

  if (trace) {
    this._rootTrace._start = trace._start
    this._rootTrace._startStamp = trace._startStamp
    this._rootTrace.calcDiff()

    this._startStamp = this._rootTrace._startStamp
    this._start = this._rootTrace._start
  }
}

Transaction.prototype._adjustDurationToLongestTrace = function () {
  var trace = getLongestTrace(this.traces)

  if (trace) {
    var currentDuration = this._rootTrace._diff
    var maxDuration = trace.duration()
    if (maxDuration > currentDuration) {
      this._rootTrace._diff = maxDuration
    }
  }
}

Transaction.prototype.startTrace = function (signature, type) {
  var trace = new Trace(this, signature, type, this._options)
  if (this._rootTrace) {
    trace.setParent(this._rootTrace)
  }

  this._activeTraces[trace.getFingerprint()] = trace

  logger.log('- %c  opbeat.instrumentation.transaction.startTrace', 'color: #3360A3', trace.signature)

  return trace
}

Transaction.prototype._onTraceEnd = function (trace) {
  this.traces.push(trace)

  logger.log('- %c  opbeat.instrumentation.transaction._endTrace', 'color: #3360A3', trace.signature)

  // Remove trace from _activeTraces
  delete this._activeTraces[trace.getFingerprint()]

  if (this._markDoneAfterLastTrace && isActiveTraceRootTrace(this._activeTraces, this._rootTrace)) {
    this._markAsDone()
  }
}

function isActiveTraceRootTrace (activeTraces, rootTrace) {
  if (Object.keys(activeTraces).length === 1) {
    var key = Object.keys(activeTraces)[0]
    return activeTraces[key] === rootTrace
  }

  return false
}

function getLongestTrace (traces) {
  var match = null

  traces.forEach(function (trace) {
    if (!match) {
      match = trace
    }
    if (match && match.duration() < trace.duration()) {
      match = trace
    }
  })

  return match
}

function getEarliestTrace (traces) {
  var earliestTrace = null

  traces.forEach(function (trace) {
    if (!earliestTrace) {
      earliestTrace = trace
    }
    if (earliestTrace && earliestTrace._start > trace._start) {
      earliestTrace = trace
    }
  })

  return earliestTrace
}

module.exports = Transaction
<commit_msg>Move startTrace method to top<commit_after>var logger = require('../lib/logger')
var Trace = require('./trace')
var utils = require('../lib/utils')

var Transaction = function (queue, name, type, options) {
  this.metadata = {}
  this.name = name
  this.type = type
  this.ended = false
  this._markDoneAfterLastTrace = false
  this._isDone = false
  this._options = options
  this.uuid = utils.generateUuid()

  this.traces = []
  this._activeTraces = {}
  this._queue = queue

  logger.log('- %c opbeat.instrumentation.transaction.ctor', 'color: #3360A3', this.name)

  // A transaction should always have a root trace spanning the entire transaction.
  this._rootTrace = this.startTrace('transaction', 'transaction', this._options)
  this._startStamp = this._rootTrace._startStamp
  this._start = this._rootTrace._start

  this.duration = this._rootTrace.duration.bind(this._rootTrace)
}

Transaction.prototype.startTrace = function (signature, type) {
  var trace = new Trace(this, signature, type, this._options)
  if (this._rootTrace) {
    trace.setParent(this._rootTrace)
  }

  this._activeTraces[trace.getFingerprint()] = trace

  logger.log('- %c  opbeat.instrumentation.transaction.startTrace', 'color: #3360A3', trace.signature)

  return trace
}

Transaction.prototype.end = function () {
  if (this.ended) {
    return
  }

  this.ended = true

  logger.log('- %c opbeat.instrumentation.transaction.end', 'color: #3360A3', this.name, Object.keys(this._activeTraces).length)

  if (Object.keys(this._activeTraces).length > 0) {
    this._markDoneAfterLastTrace = true
  } else {
    this._markAsDone()
  }
}

Transaction.prototype._markAsDone = function () {
  logger.log('- %c opbeat.instrumentation.transaction._markAsDone', 'color: #3360A3', this.name)

  if (this._isDone) {
    return
  }

  this._isDone = true

  // When all traces are finished, the transaction can be added to the queue
  var whenAllTracesFinished = this.traces.map(function (trace) {
    return trace._isFinish
  })

  Promise.all(whenAllTracesFinished).then(function () {
    logger.log('- %c opbeat.instrumentation.transaction.whenAllTracesFinished', 'color: #3360A3', this.name)

    this._rootTrace.end()

    this._adjustStartToEarliestTrace()
    this._adjustDurationToLongestTrace()

    this._queue.add(this)
  }.bind(this))
}

Transaction.prototype._adjustStartToEarliestTrace = function () {
  var trace = getEarliestTrace(this.traces)

  if (trace) {
    this._rootTrace._start = trace._start
    this._rootTrace._startStamp = trace._startStamp
    this._rootTrace.calcDiff()

    this._startStamp = this._rootTrace._startStamp
    this._start = this._rootTrace._start
  }
}

Transaction.prototype._adjustDurationToLongestTrace = function () {
  var trace = getLongestTrace(this.traces)

  if (trace) {
    var currentDuration = this._rootTrace._diff
    var maxDuration = trace.duration()
    if (maxDuration > currentDuration) {
      this._rootTrace._diff = maxDuration
    }
  }
}

Transaction.prototype._onTraceEnd = function (trace) {
  this.traces.push(trace)

  logger.log('- %c  opbeat.instrumentation.transaction._endTrace', 'color: #3360A3', trace.signature)

  // Remove trace from _activeTraces
  delete this._activeTraces[trace.getFingerprint()]

  if (this._markDoneAfterLastTrace && isActiveTraceRootTrace(this._activeTraces, this._rootTrace)) {
    this._markAsDone()
  }
}

function isActiveTraceRootTrace (activeTraces, rootTrace) {
  if (Object.keys(activeTraces).length === 1) {
    var key = Object.keys(activeTraces)[0]
    return activeTraces[key] === rootTrace
  }

  return false
}

function getLongestTrace (traces) {
  var match = null

  traces.forEach(function (trace) {
    if (!match) {
      match = trace
    }
    if (match && match.duration() < trace.duration()) {
      match = trace
    }
  })

  return match
}

function getEarliestTrace (traces) {
  var earliestTrace = null

  traces.forEach(function (trace) {
    if (!earliestTrace) {
      earliestTrace = trace
    }
    if (earliestTrace && earliestTrace._start > trace._start) {
      earliestTrace = trace
    }
  })

  return earliestTrace
}

module.exports = Transaction
<|endoftext|>


<commit_before>import { EVENT_TYPES, EVENT_NAMES } from './constants'
import { updateLastActive, isEventActiveEvent } from '../utils'

class Analytics {
    _initDataLoaded
    _setDataLoaded

    constructor({ serverConnector }) {
        this._serverConnector = serverConnector

        this._initDataLoaded = new Promise(
            resolve => (this._setDataLoaded = resolve),
        )
    }

    _eventStats = {
        [EVENT_NAMES.SUCCESSFUL_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.UNSUCCESSFUL_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.DATEPICKER]: {
            count: 0,
        },
        [EVENT_NAMES.BOOKMARK_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.TAG_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.DOMAIN_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.TAGGING]: {
            count: 0,
        },
        [EVENT_NAMES.BOOKMARK]: {
            count: 0,
        },
        [EVENT_NAMES.BLACKLIST]: {
            count: 0,
        },
        [EVENT_NAMES.ADDRESS_BAR_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.DATEPICKER_NLP]: {
            count: 0,
        },
        [EVENT_NAMES.NLP_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.OVERVIEW_TOOLTIP]: {
            count: 0,
        },
    }

    async registerOperations(eventLog) {
        this.eventLog = eventLog

        for (const event of Object.keys(this._eventStats)) {
            await this.loadInitialData(event)
        }

        this._setDataLoaded()
    }

    async fromDexie(notifType) {
        await this.loadInititalData(notifType, true)
    }

    /**
     * Track any user-invoked events internally.
     *
     * @param {EventTrackInfo} eventArgs
     */
    async storeEventLogStatistics(eventArgs) {
        // Create notificaitions params
        const notifParams = {
            latestTime: eventArgs.time,
            notifType: EVENT_TYPES[eventArgs.type].notifType,
        }

        // Store the event in dexie
        await this.eventLog.storeEvent(eventArgs)

        if (EVENT_TYPES[eventArgs.type].notifType) {
            this.incrementValue(notifParams)
        }
    }

    /**
     * Load Initial data from dexie for the particular event type
     * Query to dexie and store into _eventStats
     * @param {notifType} type of notif event
     */
    async loadInitialData(notifType, isCacheUpdate = false) {
        const latestTimeWithCount = await this.eventLog.getLatestTimeWithCount({
            notifType,
        })

        if (!latestTimeWithCount) {
            return
        }

        this.updateValue(notifType, latestTimeWithCount)
    }

    // Update the value when the memeory variables is out of update or load initial data
    updateValue(notifType, value) {
        this._eventStats[notifType] = value
    }

    incrementValue(event) {
        this._eventStats[event.notifType] = {
            count: this._eventStats[event.notifType].count + 1,
            latestTime: event.latestTime,
        }
    }

    getCountNotif(notifType) {
        return this._eventStats[notifType]
    }

    /**
     * Track any user-invoked events internally.
     *
     * @param {EventTrackInfo} eventArgs
     */
    async processEvent(eventArgs) {
        await this._initDataLoaded

        if (isEventActiveEvent(eventArgs.type)) {
            updateLastActive()
        }

        // Prepare the event to store the event in dexie db.
        const time = Date.now()

        const params = {
            ...eventArgs,
            time,
        }

        await this.storeEventLogStatistics(params)

        // Send the data to analytics server
        await this._serverConnector.trackEvent(params, params.force)
    }
}

export default Analytics
<commit_msg>Disable internal analytics<commit_after>import { EVENT_TYPES, EVENT_NAMES } from './constants'
// import { updateLastActive, isEventActiveEvent } from '../utils'

class Analytics {
    _initDataLoaded
    _setDataLoaded

    constructor({ serverConnector }) {
        this._serverConnector = serverConnector

        // this._initDataLoaded = new Promise(
        //     resolve => (this._setDataLoaded = resolve),
        // )
    }

    _eventStats = {
        [EVENT_NAMES.SUCCESSFUL_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.UNSUCCESSFUL_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.DATEPICKER]: {
            count: 0,
        },
        [EVENT_NAMES.BOOKMARK_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.TAG_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.DOMAIN_FILTER]: {
            count: 0,
        },
        [EVENT_NAMES.TAGGING]: {
            count: 0,
        },
        [EVENT_NAMES.BOOKMARK]: {
            count: 0,
        },
        [EVENT_NAMES.BLACKLIST]: {
            count: 0,
        },
        [EVENT_NAMES.ADDRESS_BAR_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.DATEPICKER_NLP]: {
            count: 0,
        },
        [EVENT_NAMES.NLP_SEARCH]: {
            count: 0,
        },
        [EVENT_NAMES.OVERVIEW_TOOLTIP]: {
            count: 0,
        },
    }

    async registerOperations(eventLog) {
        // this.eventLog = eventLog
        // for (const event of Object.keys(this._eventStats)) {
        //     await this.loadInitialData(event)
        // }
        // this._setDataLoaded()
    }

    async fromDexie(notifType) {
        await this.loadInititalData(notifType, true)
    }

    /**
     * Track any user-invoked events internally.
     *
     * @param {EventTrackInfo} eventArgs
     */
    async storeEventLogStatistics(eventArgs) {
        // Create notificaitions params
        const notifParams = {
            latestTime: eventArgs.time,
            notifType: EVENT_TYPES[eventArgs.type].notifType,
        }

        // Store the event in dexie
        await this.eventLog.storeEvent(eventArgs)

        if (EVENT_TYPES[eventArgs.type].notifType) {
            this.incrementValue(notifParams)
        }
    }

    /**
     * Load Initial data from dexie for the particular event type
     * Query to dexie and store into _eventStats
     * @param {notifType} type of notif event
     */
    async loadInitialData(notifType, isCacheUpdate = false) {
        const latestTimeWithCount = await this.eventLog.getLatestTimeWithCount({
            notifType,
        })

        if (!latestTimeWithCount) {
            return
        }

        this.updateValue(notifType, latestTimeWithCount)
    }

    // Update the value when the memeory variables is out of update or load initial data
    updateValue(notifType, value) {
        this._eventStats[notifType] = value
    }

    incrementValue(event) {
        this._eventStats[event.notifType] = {
            count: this._eventStats[event.notifType].count + 1,
            latestTime: event.latestTime,
        }
    }

    getCountNotif(notifType) {
        return this._eventStats[notifType]
    }

    /**
     * Track any user-invoked events internally.
     *
     * @param {EventTrackInfo} eventArgs
     */
    async processEvent(eventArgs) {
        // await this._initDataLoaded
        // if (isEventActiveEvent(eventArgs.type)) {
        //     updateLastActive()
        // }
        // // Prepare the event to store the event in dexie db.
        // const time = Date.now()
        // const params = {
        //     ...eventArgs,
        //     time,
        // }
        // await this.storeEventLogStatistics(params)
        // // Send the data to analytics server
        // await this._serverConnector.trackEvent(params, params.force)
    }
}

export default Analytics
<|endoftext|>


<commit_before>var crypto = require('crypto-js/md5');
var request = require('request');
var MovieDB = require('moviedb')('866913fcc5a950bed785551769c37f7c');
var async = require('async');

function ivaURL() {
  // TODO: make bash scripts to export variables at some point for secret values
  var secret = 'vnwjrhxowupaujpy';

  this.baseUrl = 'http://video.internetvideoarchive.net/video.mp4?';
  this.cmd = 'cmd=6'; //required,  6, alternative = 3.
  // kbitrate, MP4 – 80, 212, 450, 750, 1500, 2500(HD sources only) Kbps
  this.videoKbitrate = '&videokbrate=750'; // required, default 750
  this.publishId = '&publishedid='; // required, unique video id, 91
  this.customerId = '&customerid='; // required, 12345
  this.format = '&fmt=4'; //required, video format, default 4=mp4
  // Date when video expires, 1970 format,
  this.urlExpires = '&e=1457508799'; // required, default 1457508799, march 15th 2016
  this.hash = '&h='; //298y9386666

  this.setCmd = function(val) {
    this.cmd = 'cmd=' + val;
  };

  this.setVideoKbitrate = function(val) {
    this.videoKbitrate = 'videokbrate=' + val;
  };

  this.setPublishId = function(val) {
    this.publishId = 'publishedid=' + val;
  };

  this.setCustomerId = function(val) {
    this.customerId = 'customerId=' + val;
  };

  this.setFormat = function(val) {
    this.format = 'fmt=' + val;
  };

  this.setUrlExpires = function(val) {
    this.urlExpires = 'e=' + val;
  };

  this.outputUrl = function() {
    var url = this.baseUrl +
    this.customerId     + '&' +
    this.cmd            + '&' +
    this.format         + '&' +
    this.videoKbitrate  + '&' +
    this.publishId      + '&' +
    this.urlExpires;

    var hashedUrl = crypto(secret + url.toLowerCase());
    url += '&h=' + hashedUrl;

    return url;
  };
}

exports.getVideo = function(req, res) {
  var url = new ivaURL();
  url.setVideoKbitrate('750');
  // make a request for the id.
  url.setPublishId('33230');
  url.setCustomerId('995688');
  url.setFormat('4');
  url.setUrlExpires('1457508799');

      res.render('cinema', {
        title: 'Cinemality',
        url: url.outputUrl(),
        // info: info,
      });

  // request(options, callback);

//866913fcc5a950bed785551769c37f7c
// TMDb api key

};

exports.getMovie = function(req, res) {
  res.render('cinemaSearch', {

  });
};

exports.getKeywords = function(req, res) {
  res.render('keywords', {

  });
};

// idtype=68 for TMDb
exports.postKeywords = function(req, res) {
  var renderKeywords = [];
  MovieDB.searchMovie({query: req.body.title }, function(err, result){
    if(err)
    console.log(result.results[0].original_title);
    MovieDB.movieKeywords({id: result.results[0].id}, function(err, keywords) {
      // console.log(keywords.keywords);
      renderKeywords = keywords.keywords.slice();
      MovieDB.keywordMovies({id: keywords.keywords[0].id}, function(err, relatedKeywords) {

        // do ao thing with loops here
        var url = 'https://ee.internetvideoarchive.net/api/expresspro/';

        console.log('the url');
        console.log(url);
        var options = {
          // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms' + encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
          // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms',
          url: url,
          method: 'GET',
          headers: {
            'Content-Type': 'json',
            Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
            'X-Api-Version': '1'
          },
          // path: encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
        };

        request(options, function callback(error, response, body) {
          if (!error && response.statusCode == 200) {
            var info = JSON.parse(body);
            console.log(info[0]);
            res.render('cinemaSearch', {
              title: 'Cinemality',
              info: info[0],
            });
          } else {
            console.log('error: ');
            console.log(error);
            res.render('cinemaSearch', {
              title: 'Cinemality',
              error: error,
              response: response,
              body: body
            });
          }
        });

        // console.log('related keywords');
        // console.log(relatedKeywords);
        // res.render('keywords', {
        //   result: relatedKeywords.results,
        //   keywords: renderKeywords,
        //   movieTitle: result.results[0].original_title,
        // });
      });
    });
  });
};

exports.postMovie = function(req, res) {
  console.log('awefwafawfwe');
  // $.ajax({
  //   dataType: "json",
  //   headers: {
  //     Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
  //    'X-Api-Version': '1'
  //   },
  //   url: 'https://ee.internetvideoarchive.net/api/expresspro/actions/search/',
  var url = 'https://ee.internetvideoarchive.net/api/expresspro/actions/search/?appid=2c0bfc22&term=' + encodeURIComponent(req.body.title);

  console.log('the url');
  console.log(url);
  var options = {
    // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms' + encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
    // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms',
    url: url,
    method: 'GET',
    headers: {
      'Content-Type': 'json',
      Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
      'X-Api-Version': '1'
    },
    // path: encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
  };

  request(options, function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
      var info = JSON.parse(body);
      console.log(info[0]);
      res.render('cinemaSearch', {
        title: 'Cinemality',
        info: info[0],
      });
    } else {
      console.log('error: ');
      console.log(error);
      res.render('cinemaSearch', {
        title: 'Cinemality',
        error: error,
        response: response,
        body: body
      });
    }
  });

};

// rovi
// gracenote - meta info, TMS id from Grace note > search IVA; pinpoint api
<commit_msg>cinemakeywords not working<commit_after>var crypto = require('crypto-js/md5');
var request = require('request');
var MovieDB = require('moviedb')('866913fcc5a950bed785551769c37f7c');
var async = require('async');

function ivaURL() {
  // TODO: make bash scripts to export variables at some point for secret values
  var secret = 'vnwjrhxowupaujpy';

  this.baseUrl = 'http://video.internetvideoarchive.net/video.mp4?';
  this.cmd = 'cmd=6'; //required,  6, alternative = 3.
  // kbitrate, MP4 – 80, 212, 450, 750, 1500, 2500(HD sources only) Kbps
  this.videoKbitrate = '&videokbrate=750'; // required, default 750
  this.publishId = '&publishedid='; // required, unique video id, 91
  this.customerId = '&customerid='; // required, 12345
  this.format = '&fmt=4'; //required, video format, default 4=mp4
  // Date when video expires, 1970 format,
  this.urlExpires = '&e=1457508799'; // required, default 1457508799, march 15th 2016
  this.hash = '&h='; //298y9386666

  this.setCmd = function(val) {
    this.cmd = 'cmd=' + val;
  };

  this.setVideoKbitrate = function(val) {
    this.videoKbitrate = 'videokbrate=' + val;
  };

  this.setPublishId = function(val) {
    this.publishId = 'publishedid=' + val;
  };

  this.setCustomerId = function(val) {
    this.customerId = 'customerId=' + val;
  };

  this.setFormat = function(val) {
    this.format = 'fmt=' + val;
  };

  this.setUrlExpires = function(val) {
    this.urlExpires = 'e=' + val;
  };

  this.outputUrl = function() {
    var url = this.baseUrl +
    this.customerId     + '&' +
    this.cmd            + '&' +
    this.format         + '&' +
    this.videoKbitrate  + '&' +
    this.publishId      + '&' +
    this.urlExpires;

    var hashedUrl = crypto(secret + url.toLowerCase());
    url += '&h=' + hashedUrl;

    return url;
  };
}

exports.getVideo = function(req, res) {
  var url = new ivaURL();
  url.setVideoKbitrate('750');
  // make a request for the id.
  url.setPublishId('33230');
  url.setCustomerId('995688');
  url.setFormat('4');
  url.setUrlExpires('1457508799');

      res.render('cinema', {
        title: 'Cinemality',
        url: url.outputUrl(),
        // info: info,
      });

  // request(options, callback);

//866913fcc5a950bed785551769c37f7c
// TMDb api key

};

exports.getMovie = function(req, res) {
  res.render('cinemaSearch', {

  });
};

exports.getKeywords = function(req, res) {
  res.render('keywords', {

  });
};

// idtype=68 for TMDb
exports.postKeywords = function(req, res) {
  var renderKeywords = [];
  var trailerLinks = [];
  var relatedKeywords = [];

  MovieDB.searchMovie({query: req.body.title }, function(err, result){
    if(err) console.log(err);
    // console.log(result.results[0].original_title);
    MovieDB.movieKeywords({id: result.results[0].id}, function(err, keywords) {
      // console.log(keywords.keywords);
      if(err) console.log(err);
      renderKeywords = keywords.keywords.slice();

      async.each(keywords.keywords,
        function(item, cb) {

          MovieDB.keywordMovies({ id: item.id }, function(err, moviesUnderKeyword) {
            if(err) console.log(err);
            // do ao thing with loops here
            // var url = 'https://ee.internetvideoarchive.net/api/expresspro/';
            // console.log(moviesUnderKeyword);
            // relatedKeywords = moviesUnderKeyword.slice();
            var url = 'https://ee.internetvideoarchive.net/api/expresspro/' + moviesUnderKeyword.results[0].id +
            '?idtype=1&appid=2c0bfc22';

            console.log('the url');
            console.log(url);
            var options = {
              // expresspro/1756?idtype=1&appid=12345.
              // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms' + encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
              // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms',
              url: url,
              method: 'GET',
              headers: {
                'Content-Type': 'json',
                Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
                'X-Api-Version': '1'
              },
              // path: encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
            };

            request(options, function callback(error, response, body) {
              if (!error && response.statusCode == 200) {
                var info = JSON.parse(body);
                console.log('kILL ME ====================================');
                // console.log(info);

                cb()
              } else {
                console.log('error: ');
                console.log(error);

                cb()
              }
            });
          })
          // loop through keywords.keywords (list of keywords)
          // id/keyword pairs. example:
          // { id: 603, name: 'elves' },
          //  { id: 604, name: 'dwarves' },
          //  { id: 606, name: 'orcs' },
          //  { id: 609, name: 'middle-earth (tolkien)' },

          // afterwards search by keyword for a list of related movies
          // then get one movie from the array of listed movies
          // then get the id from the one movie per keyword
          // and find the related trailer
          // add the trailer URL to an array

        }, function done(){
          res.render('keywords', {
            result: relatedKeywords.results,
            keywords: renderKeywords,
            movieTitle: result.results[0].original_title,
          });
        });

        // console.log('related keywords');
        // console.log(relatedKeywords);
        // res.render('keywords', {
        //   result: relatedKeywords.results,
        //   keywords: renderKeywords,
        //   movieTitle: result.results[0].original_title,
    });
  });
};

exports.postMovie = function(req, res) {
  console.log('awefwafawfwe');
  // $.ajax({
  //   dataType: "json",
  //   headers: {
  //     Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
  //    'X-Api-Version': '1'
  //   },
  //   url: 'https://ee.internetvideoarchive.net/api/expresspro/actions/search/',
  var url = 'https://ee.internetvideoarchive.net/api/expresspro/actions/search/?appid=2c0bfc22&term=' + encodeURIComponent(req.body.title);

  console.log('the url');
  console.log(url);
  var options = {
    // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms' + encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
    // url: 'http://api.internetvideoarchive.com/2.0/DataService/EntertainmentPrograms',
    url: url,
    method: 'GET',
    headers: {
      'Content-Type': 'json',
      Authorization: 'Bearer ' + 'CRM2BrKREqDkoZUwYKhGG99QA2_d2vAi7flH9v8iaLVn5vpLpbag3vPfUbRetn-0w3qgSAEXP5fYOlf6i8tjuVk82zT5dqTsUn_1MTga6F-ithuTQGy0FQGhgkWNzPa20OyYsKFa_7Z8vb32zph7gWA5RcbENbnNbwzJiI4S8jUARgxKexj4Z28HCKDVONscjG606UgHpwWiIVWIMEP60Pkyf5_wB7VTyWgBjnJDudNNGhOtaod_YeIJhUv2o7eGeMuElTzbn7tvQZokNi4bpgEYeuQ',
      'X-Api-Version': '1'
    },
    // path: encodeURIComponent('()?$filter=substringof("Jurassic World",Title) and StreamLengthinseconds gt 0&$expand=MovieCategory, Description, ProgramToPerformerMaps/Performer, VideoAssets&format=json@developerid=105db639-eb8e-4cb0-b900-afb8ad519bb1'),
  };

  request(options, function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
      var info = JSON.parse(body);
      console.log(info[0]);
      res.render('cinemaSearch', {
        title: 'Cinemality',
        info: info[0],
      });
    } else {
      console.log('error: ');
      console.log(error);
      res.render('cinemaSearch', {
        title: 'Cinemality',
        error: error,
        response: response,
        body: body
      });
    }
  });

};

// rovi
// gracenote - meta info, TMS id from Grace note > search IVA; pinpoint api
<|endoftext|>


<commit_before>//
//     npm-pulse
//     Copyright(c) 2013 Applejacks
//     Charlie Key, Taron Foxworth, Matt Hernandez
//     MIT Licensed
//

var request = require('request')
  , util    = require('util')
  , Q       = require('q')
  , path    = require('path');

const GITHUB_ROOT_URL = 'https://api.github.com';
const REPORT_CARD_URL = 'http://osrc.dfm.io/';
const UA_STRING       = 'applejacks/npm-pulse';

//
// Helper for getting data from GitHub.
//
var get = function get(uri) {
  var deferred = Q.defer();
  var opts = {
    methid: 'GET'
  , url: GITHUB_ROOT_URL + uri
  , json: true
  , headers: {
      'User-Agent': UA_STRING
    }
  };

  request(opts, function(err, response, body) {
    if (err) return deferred.reject(err);
    if (response.statusCode !== 200) return deferred.reject(new Error(body.message));

    deferred.resolve(body);
  });

  return deferred.promise;
};

//
// Get releases for the specified repository.
//
var getRepo = function(meta) {
  return get(util.format('/repos/%s/%s', meta.user, meta.name));
};

//
// Get contributors array for the specified repository.
//
var getContributors = function(meta) {
  return get(util.format('/repos/%s/%s/stats/contributors', meta.user, meta.name));
};

//
// Split the repo object into something usable by the GitHub API.
//
var getRepoMeta = function(repo) {
  if (!repo || repo.length === 0) return '';

  var bits = repo.url.split('/');

  return {
    user: bits[3]
  , name: bits[4].replace('.git', '')
  };
};

//
// Calculate the popularity of the repo based on watchers, stars, forks, downloads
//
var calculatePopularity = function(watchers, stars, forks, downloads) {
  var totalActivity = watchers + stars + forks + downloads;

  var watchersPercent = watchers/totalActivity;
  var starsPercent = stars/totalActivity;
  var forksPercent = forks/totalActivity;
  var downloadsPercent = downloads/totalActivity;

  var watchersPoints = watchers * ( 1 - watchersPercent);
  var starsPoints = stars * ( 1 - starsPercent);
  var forksPoints = forks * ( 1 - forksPercent);
  var downloadsPoints = downloads * ( 1 - downloadsPercent);

  var topPoints = 47505.05444166553; // Express

  return ((watchersPoints + starsPoints + forksPoints + downloadsPoints)/topPoints);

};

//
// Calculate the quality of the repo based on popularity and issues
//
var calculatePopularity = function(popularity, closed_issues, open_issues, last_commit) {
  var totalActivity = watchers + stars + forks + downloads;

  var watchersPercent = watchers/totalActivity;
  var starsPercent = stars/totalActivity;
  var forksPercent = forks/totalActivity;
  var downloadsPercent = downloads/totalActivity;

  var watchersPoints = watchers * ( 1 - watchersPercent);
  var starsPoints = stars * ( 1 - starsPercent);
  var forksPoints = forks * ( 1 - forksPercent);
  var downloadsPoints = downloads * ( 1 - downloadsPercent);

  var topPoints = 47505.05444166553; // Express

  return ((watchersPoints + starsPoints + forksPoints + downloadsPoints)/topPoints);

};

//
// GitHub constructor used to work with repositories.
//
var GitHub = function() {
};

//
// Aggregate the data from each endpoint and return the compiled JSON object
//    for the module object.
//
GitHub.prototype.getRepo = function(module, fn) {
  if (typeof module.repository === 'undefined') return fn(new Error('No repository specified for that module.'));
  if (module.repository.type !== 'git' ||
      module.repository.url.indexOf('github') === -1) return fn(new Error('The specified module is not stored on GitHub.'));

  var meta     = getRepoMeta(module.repository)
    , data     = {}
    , versions = Object.keys(module.time);

  //
  // Attach data from the npm registry.
  //
  data.name = module.name;
  data.description = module.description;
  data.report_card = REPORT_CARD_URL + meta.user;
  data.initial_release = {
    version: versions[0]
  , date: module.time[versions[0]]
  };
  data.latest_release = {
    version: versions[versions.length - 1]
  , date: module.time[versions[versions.length - 1]]
  };
  data.author = {
    name: module.author.name
  };
  data.versions = module.time;

  getRepo(meta)
    .then(function(repo) {
      //
      // Attach data from GitHub.
      //
      data.stars = repo.stargazers_count;
      data.issues = repo.open_issues;
      data.watchers = repo.watchers_count;
      data.forks = repo.forks_count;
      data.author.avatar_url = repo.owner.avatar_url;
      data.author.username = repo.owner.login;
      data.author.url = repo.owner.html_url;
      data.url = repo.html_url;
      data.issues_url = path.join(repo.html_url, 'issues');
      data.fork = path.join(repo.html_url, 'fork');
      data.network_url = path.join(repo.html_url, 'network');
      data.star = path.join(repo.html_url, 'star');
      data.stargazers = path.join(repo.html_url, 'stargazers');

      data.popularity = calculatePopularity(data.watchers,data.stars,data.forks,881818);

      return getContributors(meta);
    })
    .then(function(contributors) {
      data.contributors = contributors;

      fn(null, data);
    })
    .fail(function(err) {
      console.error(err.message);
      console.error(err.stack);
      fn(err);
    })
    .done();
};

//
// Returns a new GitHub instance.
//
module.exports = function() {
  return new GitHub();
};
<commit_msg>Fixed  merge confilct<commit_after>//
//     npm-pulse
//     Copyright(c) 2013 Applejacks
//     Charlie Key, Taron Foxworth, Matt Hernandez
//     MIT Licensed
//

var request = require('request')
  , util    = require('util')
  , Q       = require('q')
  , path    = require('path');

const GITHUB_ROOT_URL = 'https://api.github.com';
const REPORT_CARD_URL = 'http://osrc.dfm.io/';
const UA_STRING       = 'applejacks/npm-pulse';

//
// Helper for getting data from GitHub.
//
var get = function get(uri) {
  var deferred = Q.defer();
  var opts = {
    methid: 'GET'
  , url: GITHUB_ROOT_URL + uri
  , json: true
  , headers: {
      'User-Agent': UA_STRING
    }
  };

  request(opts, function(err, response, body) {
    if (err) return deferred.reject(err);
    if (response.statusCode !== 200) return deferred.reject(new Error(body.message));

    deferred.resolve(body);
  });

  return deferred.promise;
};

//
// Get releases for the specified repository.
//
var getRepo = function(meta) {
  return get(util.format('/repos/%s/%s', meta.user, meta.name));
};

//
// Get contributors array for the specified repository.
//
var getContributors = function(meta) {
  return get(util.format('/repos/%s/%s/stats/contributors', meta.user, meta.name));
};

//
// Get commit data for the specified repository.
//
var getCommits = function(meta) {
  return get(util.format('/repos/%s/%s/commits', meta.user, meta.name));
};

//
// Get the last week of commits.
//
var getLastWeekCommits = function(meta, since) {
  return get(util.format('/repos/%s/%s/commits?since=%s', meta.user, meta.name, since));
};

//
// Get all closed issues for the specified repository.
//
var getClosedIssues = function(meta) {
  return get(util.format('/repos/%s/%s/issues?state=closed', meta.user, meta.name));
};

//
// Split the repo object into something usable by the GitHub API.
//
var getRepoMeta = function(repo) {
  if (!repo || repo.length === 0) return '';

  var bits = repo.url.split('/');

  return {
    user: bits[3]
  , name: bits[4].replace('.git', '')
  };
};

// Calculate popularity based on watchers, stars, forks and downloads.

var calculatePopularity = function(watchers, stars, forks, downloads) {
  var totalActivity = watchers + stars + forks + downloads;

  var watchersPercent = watchers/totalActivity;
  var starsPercent = stars/totalActivity;
  var forksPercent = forks/totalActivity;
  var downloadsPercent = downloads/totalActivity;

  var watchersPoints = watchers * ( 1 - watchersPercent);
  var starsPoints = stars * ( 1 - starsPercent);
  var forksPoints = forks * ( 1 - forksPercent);
  var downloadsPoints = downloads * ( 1 - downloadsPercent);

  var topPoints = 47505.05444166553; // Express

  return ((watchersPoints + starsPoints + forksPoints + downloadsPoints)/topPoints);

};

//
// Calculate the quality of the repo based on popularity and issues
//
var calculatePopularity = function(popularity, closed_issues, open_issues, last_commit) {
  var totalActivity = watchers + stars + forks + downloads;

  var watchersPercent = watchers/totalActivity;
  var starsPercent = stars/totalActivity;
  var forksPercent = forks/totalActivity;
  var downloadsPercent = downloads/totalActivity;

  var watchersPoints = watchers * ( 1 - watchersPercent);
  var starsPoints = stars * ( 1 - starsPercent);
  var forksPoints = forks * ( 1 - forksPercent);
  var downloadsPoints = downloads * ( 1 - downloadsPercent);

  var topPoints = 47505.05444166553; // Express

  return ((watchersPoints + starsPoints + forksPoints + downloadsPoints)/topPoints);

};

//
// GitHub constructor used to work with repositories.
//
var GitHub = function() {
};

//
// Aggregate the data from each endpoint and return the compiled JSON object
//    for the module object.
//
GitHub.prototype.getRepo = function(module, fn) {
  if (typeof module.repository === 'undefined') return fn(new Error('No repository specified for that module.'));
  if (module.repository.type !== 'git' ||
      module.repository.url.indexOf('github') === -1) return fn(new Error('The specified module is not stored on GitHub.'));

  var meta     = getRepoMeta(module.repository)
    , data     = {}
    , versions = Object.keys(module.time);

  //
  // Attach data from the npm registry.
  //
  data.name = module.name;
  data.description = module.description;
  data.report_card = REPORT_CARD_URL + meta.user;
  data.initial_release = {
    version: versions[0]
  , date: module.time[versions[0]]
  };
  data.latest_release = {
    version: versions[versions.length - 1]
  , date: module.time[versions[versions.length - 1]]
  };
  data.author = {
    name: module.author.name
  };
  data.versions = module.time;

  getRepo(meta)
    .then(function(repo) {
      data.stars = repo.stargazers_count;
      data.issues = repo.open_issues;
      data.watchers = repo.watchers_count;
      data.forks = repo.forks_count;
      data.author.avatar_url = repo.owner.avatar_url;
      data.author.username = repo.owner.login;
      data.author.url = repo.owner.html_url;
      data.url = repo.html_url;
      data.issues_url = path.join(repo.html_url, 'issues');
      data.fork = path.join(repo.html_url, 'fork');
      data.network_url = path.join(repo.html_url, 'network');
      data.star = path.join(repo.html_url, 'star');
      data.stargazers = path.join(repo.html_url, 'stargazers');

      data.popularity = calculatePopularity(data.watchers,data.stars,data.forks,881818);

      return getContributors(meta);
    })
    .then(function(contributors) {
      data.contributors = contributors;

      // Get commit data and attach it to the data object.
      return getCommits(meta);
    })
    .then(function(commits) {
      data.commits = {};
      data.commits.total = commits.length;
      data.commits.most_recent = commits[0].commit.committer.date;

      var today = new Date()
        , lastWeek = new Date(today.getTime() - (1000 * 60 * 60 * 24 * 7));

      // Get the last week of commit activity.
      return getLastWeekCommits(meta, lastWeek);
    })
    .then(function(lastWeek) {
      data.commits.last_week = lastWeek;

      // Get all closed issues.
      return getClosedIssues(meta);
    })
    .then(function(closedIssues) {
      data.closed_issues = closedIssues ? closedIssues.length : 0;

      fn(null, data);
    })
    .fail(function(err) {
      console.error(err.message);
      console.error(err.stack);
      fn(err);
    })
    .done();
};

//
// Returns a new GitHub instance.
//
module.exports = function() {
  return new GitHub();
};
<|endoftext|>


<commit_before>import fs from 'mz/fs';
import fsExtra from 'fs-extra';
import chalk from 'chalk';
import inquirer from 'inquirer';
import semver from 'semver';
import { resolveProject, resolveRoot } from '../../util/resolve-util';
import logger from '../../../shared/logger';
import { execSync } from '../../util/process-util';

// TODO: handle NPM install crashes if module not found
// TODO: while running, print that the task is running
// TODO init git if package.json contains a repo ?
// TODO: Hide NPM's STDOUT if verbosity isn't debug.

export default function registerCommand(commander) {

  commander
    .command('init')
    .description('Setups your project')
    .action(() => {
      runInitScripts();
    });
}

const scripts = {
  'Install peer dependencies': {
    isReady() {
      return false;
    },

    async run() {
      const { peerDependencies } = await fsExtra.readJson(resolveRoot('package.json'));
      const projectPkg = await fsExtra.readJson(resolveProject('package.json'));

      const installed = projectPkg.dependencies || {};

      const toInstall = [];
      for (const depName of Object.keys(peerDependencies)) {
        const depVersionRange = peerDependencies[depName];

        if (!installed[depName] || !semver.satisfies(installed[depName], depVersionRange)) {
          toInstall.push(`${depName}@${depVersionRange}`);
        }
      }

      if (toInstall.length > 0) {
        logger.info(`Installing peer dependencies ${toInstall.map(dep => chalk.blue(dep)).join(', ')}`);
        execSync(`npm install --save ${toInstall.join(' ')}`);
      }
    },
  },

  'Install .gitignore': {

    /**
     * Check that the project contains a .gitignore file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.gitignore'));
    },

    run() {
      return fsExtra.copy(
        resolveRoot('resources/.gitignore.raw'),
        resolveProject('.gitignore')
      );
    },
  },

  'Install .browserslistrc': {

    /**
     * Check that the project contains a .browserslistrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.browserslistrc'));
    },

    run() {
      return fsExtra.copy(
        resolveRoot('resources/.browserslistrc.raw'),
        resolveProject('.browserslistrc')
      );
    },
  },

  'Install eslint': {

    /**
     * Check that the project contains a .eslintrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.eslintrc'));
    },

    async run() {
      const { preset } = await inquirer.prompt([{
        type: 'input',
        message: 'What ESLint preset do you want to use ? (blank for none).',
        name: 'preset',
        default() {
          return '';
        },
      }]);

      if (!preset) {
        return;
      }

      execSync(`npm install --save-dev eslint ${preset}`);

      return void fs.writeFile(
        resolveProject('.eslintrc'),
        `{
  "extends": "${preset}"
}`
      );
    },
  },

  'Install stylelint': {

    /**
     * Check that the project contains a .stylelintrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.stylelintrc'));
    },

    async run() {
      const { preset } = await inquirer.prompt([{
        type: 'input',
        message: 'What Stylelint preset do you want to use ? (blank for none).',
        name: 'preset',
        default() {
          return '';
        },
      }]);

      if (!preset) {
        return;
      }

      execSync(`npm install --save-dev stylelint ${preset}`);

      return void fs.writeFile(
        resolveProject('.stylelintrc'),
        `{
  "extends": "${preset}"
}`
      );
    },
  },

  'Install stage-lint': {
    async isReady() {

      const pck = await fsExtra.readJson(resolveProject('package.json'));

      // pre-commit disabled
      if (pck['pre-commit'] === false) {
        return true;
      }

      if (!pck.devDependencies['lint-staged']) {
        return false;
      }

      return pck.devDependencies.husky !== void 0;
    },

    async run() {
      execSync('npm install --save-dev husky lint-staged');

      const pckFile = resolveProject('package.json');

      const pkg = await fsExtra.readJson(pckFile);

      // NPM script to run
      pkg.scripts = pkg.scripts || {};
      pkg.scripts.precommit = pkg.scripts.precommit || 'lint-staged';

      await fsExtra.writeJson(pckFile, pkg);

      // lint-staged config
      if (!await fs.exists('.lintstagedrc')) {
        await fsExtra.copy(
          resolveRoot('resources/.lintstagedrc.raw'),
          resolveProject('.lintstagedrc')
        );
      }
    },
  },

  'Configure PostCss': {
    isReady() {
      return fs.exists(resolveProject('postcss.config.js'));
    },

    run() {
      execSync('npm install --save-dev @reworkjs/postcss-preset-reworkjs');

      return fsExtra.copy(
        resolveRoot('resources/postcss.config.js.raw'),
        resolveProject('postcss.config.js')
      );
    },
  },

  // 'Add README': {
  //   isReady() {
  //     // check there is a README file
  //   },
  //
  //   run() {
  //     /*
  //      - Add README.md
  //      */
  //   },
  // },
};

const emptyPromise = Promise.resolve();
function runInitScripts() {

  let promise = emptyPromise;
  for (const scriptName of Object.keys(scripts)) {
    // run sequentially, don't Promise.all this.
    promise = promise.then(() => {
      return runScript(scriptName, scripts[scriptName]);
    });
  }

  /*
   - print "Project ready, use `rjs start --env dev` to launch your project. Read more at <getting started doc url>"
   */
}

async function runScript(scriptName, script) {
  try {
    if (typeof script.isReady === 'function') {
      const isReady = await script.isReady();
      if (typeof isReady !== 'boolean') {
        logger.info(`${chalk.red('✘')} ${scriptName} - Script has a bug.`);
        return;
      }

      if (isReady) {
        logger.info(`${chalk.green('✓')} ${scriptName}`);
        return;
      }
    }

    await script.run();

    logger.info(`${chalk.green('✓')} ${scriptName}`);
  } catch (e) {
    logger.info(`${chalk.red('✘')} ${scriptName} - Script crashed.`);
    throw e;
  }
}
<commit_msg>fix: Clean range before testing<commit_after>import fs from 'mz/fs';
import fsExtra from 'fs-extra';
import chalk from 'chalk';
import inquirer from 'inquirer';
import semver from 'semver';
import { resolveProject, resolveRoot } from '../../util/resolve-util';
import logger from '../../../shared/logger';
import { execSync } from '../../util/process-util';

// TODO: handle NPM install crashes if module not found
// TODO: while running, print that the task is running
// TODO init git if package.json contains a repo ?
// TODO: Hide NPM's STDOUT if verbosity isn't debug.

export default function registerCommand(commander) {

  commander
    .command('init')
    .description('Setups your project')
    .action(() => {
      runInitScripts();
    });
}

const scripts = {
  'Install peer dependencies': {
    isReady() {
      return false;
    },

    async run() {
      const { peerDependencies } = await fsExtra.readJson(resolveRoot('package.json'));
      const projectPkg = await fsExtra.readJson(resolveProject('package.json'));

      const installed = projectPkg.dependencies || {};

      const toInstall = [];
      for (const depName of Object.keys(peerDependencies)) {
        const depVersionRange = peerDependencies[depName];

        if (!installed[depName] || !semver.satisfies(semver.clean(installed[depName]), depVersionRange)) {
          toInstall.push(`${depName}@${depVersionRange}`);
        }
      }

      if (toInstall.length > 0) {
        logger.info(`Installing peer dependencies ${toInstall.map(dep => chalk.blue(dep)).join(', ')}`);
        execSync(`npm install --save ${toInstall.join(' ')}`);
      }
    },
  },

  'Install .gitignore': {

    /**
     * Check that the project contains a .gitignore file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.gitignore'));
    },

    run() {
      return fsExtra.copy(
        resolveRoot('resources/.gitignore.raw'),
        resolveProject('.gitignore')
      );
    },
  },

  'Install .browserslistrc': {

    /**
     * Check that the project contains a .browserslistrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.browserslistrc'));
    },

    run() {
      return fsExtra.copy(
        resolveRoot('resources/.browserslistrc.raw'),
        resolveProject('.browserslistrc')
      );
    },
  },

  'Install eslint': {

    /**
     * Check that the project contains a .eslintrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.eslintrc'));
    },

    async run() {
      const { preset } = await inquirer.prompt([{
        type: 'input',
        message: 'What ESLint preset do you want to use ? (blank for none).',
        name: 'preset',
        default() {
          return '';
        },
      }]);

      if (!preset) {
        return;
      }

      execSync(`npm install --save-dev eslint ${preset}`);

      return void fs.writeFile(
        resolveProject('.eslintrc'),
        `{
  "extends": "${preset}"
}`
      );
    },
  },

  'Install stylelint': {

    /**
     * Check that the project contains a .stylelintrc file.
     * @async
     * @returns {!boolean}
     */
    isReady() {
      return fs.exists(resolveProject('.stylelintrc'));
    },

    async run() {
      const { preset } = await inquirer.prompt([{
        type: 'input',
        message: 'What Stylelint preset do you want to use ? (blank for none).',
        name: 'preset',
        default() {
          return '';
        },
      }]);

      if (!preset) {
        return;
      }

      execSync(`npm install --save-dev stylelint ${preset}`);

      return void fs.writeFile(
        resolveProject('.stylelintrc'),
        `{
  "extends": "${preset}"
}`
      );
    },
  },

  'Install stage-lint': {
    async isReady() {

      const pck = await fsExtra.readJson(resolveProject('package.json'));

      // pre-commit disabled
      if (pck['pre-commit'] === false) {
        return true;
      }

      if (!pck.devDependencies['lint-staged']) {
        return false;
      }

      return pck.devDependencies.husky !== void 0;
    },

    async run() {
      execSync('npm install --save-dev husky lint-staged');

      const pckFile = resolveProject('package.json');

      const pkg = await fsExtra.readJson(pckFile);

      // NPM script to run
      pkg.scripts = pkg.scripts || {};
      pkg.scripts.precommit = pkg.scripts.precommit || 'lint-staged';

      await fsExtra.writeJson(pckFile, pkg);

      // lint-staged config
      if (!await fs.exists('.lintstagedrc')) {
        await fsExtra.copy(
          resolveRoot('resources/.lintstagedrc.raw'),
          resolveProject('.lintstagedrc')
        );
      }
    },
  },

  'Configure PostCss': {
    isReady() {
      return fs.exists(resolveProject('postcss.config.js'));
    },

    run() {
      execSync('npm install --save-dev @reworkjs/postcss-preset-reworkjs');

      return fsExtra.copy(
        resolveRoot('resources/postcss.config.js.raw'),
        resolveProject('postcss.config.js')
      );
    },
  },

  // 'Add README': {
  //   isReady() {
  //     // check there is a README file
  //   },
  //
  //   run() {
  //     /*
  //      - Add README.md
  //      */
  //   },
  // },
};

const emptyPromise = Promise.resolve();
function runInitScripts() {

  let promise = emptyPromise;
  for (const scriptName of Object.keys(scripts)) {
    // run sequentially, don't Promise.all this.
    promise = promise.then(() => {
      return runScript(scriptName, scripts[scriptName]);
    });
  }

  /*
   - print "Project ready, use `rjs start --env dev` to launch your project. Read more at <getting started doc url>"
   */
}

async function runScript(scriptName, script) {
  try {
    if (typeof script.isReady === 'function') {
      const isReady = await script.isReady();
      if (typeof isReady !== 'boolean') {
        logger.info(`${chalk.red('✘')} ${scriptName} - Script has a bug.`);
        return;
      }

      if (isReady) {
        logger.info(`${chalk.green('✓')} ${scriptName}`);
        return;
      }
    }

    await script.run();

    logger.info(`${chalk.green('✓')} ${scriptName}`);
  } catch (e) {
    logger.info(`${chalk.red('✘')} ${scriptName} - Script crashed.`);
    throw e;
  }
}
<|endoftext|>


<commit_before>var request = require('superagent')
var logger = require('../common/logger')
var config = require('../config')
var token = require('../common/token')

var User = require('../models/user')

/**
 * 发送模板消息
 * @param {String} studentId 学号
 * @param {String} templateId 消息模板id
 * @param {String} formId 表单id
 * @param {String} data 模板消息内容
 */
exports.notify = function (req, res, next) {
  var params = req.body

  if (!params.studentId) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  // 模板数据
  var msgData = {
    // 接收者openId
    touser: '',
    // 模板id
    template_id: config.templateId[params.templateId],
    // 表单id
    form_id: params.formId,
    // 模板内容
    data: params.data,
    // 需要放大的关键词
    emphasis_keyword: 'keyword2.DATA'
  }

  // 查询用户是否注册
  Promise.resolve(
      User.find({
        studentId: params.studentId
      })
    )
    .then(person => {
      if (person) {
        // 确定接受者id
        msgData.touser = person.openId
      } else {
        return Promise.reject(new Error('用户不存在'))
      }
    })
    // 获取access_token
    .then(() => {
      return token.getAccessToken()
    })
    .then(accessToken => {
      logger.info(JSON.stringify(msgData))
      // 发送模板消息
      return request
        .post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' + accessToken)
        .send(JSON.stringify(msgData))
    })
    .then(data => {
      if (data.body.errcode === 0) {
        return res.status(200).json({
          statusCode: 200,
          errMsg: '发送成功'
        })
      } else {
        logger.info(data)

        return res.status(400).json({
          statusCode: 400,
          errMsg: '发送失败'
        })
      }
    })
    .catch(err => {
      logger.error(err)

      return res.status(500).json({
        statusCode: 500,
        errMsg: '内部错误'
      })
    })
}
<commit_msg>Hot fix: 定位invalid openid hint<commit_after>var request = require('superagent')
var logger = require('../common/logger')
var config = require('../config')
var token = require('../common/token')

var User = require('../models/user')

/**
 * 发送模板消息
 * @param {String} studentId 学号
 * @param {String} templateId 消息模板id
 * @param {String} formId 表单id
 * @param {String} data 模板消息内容
 */
exports.notify = function (req, res, next) {
  var params = req.body

  if (!params.studentId) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  // 接收者openId
  var touser = ''
  // 模板数据
  var msgData = {
    // 模板id
    template_id: config.templateId[params.templateId],
    // 表单id
    form_id: params.formId,
    // 模板内容
    data: params.data,
    // 需要放大的关键词
    emphasis_keyword: 'keyword2.DATA'
  }

  // 查询用户是否注册
  Promise.resolve(
      User.find({
        studentId: params.studentId
      })
    )
    .then(person => {
      if (person) {
        // 确定接受者id
        touser = person.openId
      } else {
        return Promise.reject(new Error('用户不存在'))
      }
    })
    // 获取access_token
    .then(() => {
      return token.getAccessToken()
    })
    .then(accessToken => {
      logger.info(JSON.stringify(msgData))
      logger.info(JSON.stringify({
        touser: touser
      }))
      // 发送模板消息
      return request
        .post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' + accessToken)
        .send(JSON.stringify({
          touser: touser
        }))
        .send(JSON.stringify(msgData))
    })
    .then(data => {
      if (data.body.errcode === 0) {
        return res.status(200).json({
          statusCode: 200,
          errMsg: '发送成功'
        })
      } else {
        logger.info(data)

        return res.status(400).json({
          statusCode: 400,
          errMsg: '发送失败'
        })
      }
    })
    .catch(err => {
      logger.error(err)

      return res.status(500).json({
        statusCode: 500,
        errMsg: '内部错误'
      })
    })
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var logger = require('../lib/logFactory').logger;
var conf = require('../config/confLoader').conf;

var UserController = require('./user');
var KListController = require('./klist');

/**
 * The Router manage controllers' action dispatch regarding URL routing.
 * @exports controllers/router
 */
var Router = {

    /**
     * Contains the routes mapping
     * @type {Object}
     */
    routes : {
        'user/:login' : {
            method : 'get',
            action : UserController.get
        },
        'klist/:id' : {
            method : 'get',
            action : KListController.get
        }
    },

    /**
     * Dispatch the routes
     * @public
     * @param {HttpServer} server - to apply the routes to
     */
    dispatch : function(server){
        var apiPath = conf.get('server').apiPath;
        logger.debug("Dispatch routes into %s",apiPath);

        _.forEach(this.routes, function(mapping, route){
            if(!/\/$/.test(apiPath) && !/^\//.test(route)){
                apiPath += '/';
            }
            route = apiPath + route;
            if(typeof server[mapping.method] === 'function' && typeof mapping.action === 'function'){
                logger.debug("Serve %s on using %j", route, mapping);
                server[mapping.method](route, mapping.action);
            }
        });
    }
};

module.exports = exports = Router;
<commit_msg>add list board to router<commit_after>var _ = require('lodash');
var logger = require('../lib/logFactory').logger;
var conf = require('../config/confLoader').conf;

var UserController = require('./user');
var KListController = require('./klist');

/**
 * The Router manage controllers' action dispatch regarding URL routing.
 * @exports controllers/router
 */
var Router = {

    /**
     * Contains the routes mapping
     * @type {Object}
     */
    routes : {
        'user/:login' : {
            method : 'get',
            action : UserController.get
        },
        'klist/:id' : {
            method : 'get',
            action : KListController.get
        },
        'klists' : {
            method : 'get',
            action : KListController.getLists
        }
    },

    /**
     * Dispatch the routes
     * @public
     * @param {HttpServer} server - to apply the routes to
     */
    dispatch : function(server){
        var apiPath = conf.get('server').apiPath;
        logger.debug("Dispatch routes into %s",apiPath);

        _.forEach(this.routes, function(mapping, route){
            if(!/\/$/.test(apiPath) && !/^\//.test(route)){
                apiPath += '/';
            }
            route = apiPath + route;
            if(typeof server[mapping.method] === 'function' && typeof mapping.action === 'function'){
                logger.debug("Serve %s on using %j", route, mapping);
                server[mapping.method](route, mapping.action);
            }
        });
    }
};

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


<commit_before>/**
 * Basic.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:false, scripturl:true, browser:true */
/*global define:true */

define('moxie/core/utils/Basic', [], function() {
	/**
	Get DOM Element by it's id.

	@method byId
	@param {String} id Identifier of the DOM Element
	@return {DOMElement}
	*/
	var byId = function(id) {
		if (typeof id !== 'string') {
			return id;
		}
		return document.getElementById(id);
	};

	/**
	Gets the true type of the built-in object (better version of typeof).
	@author Angus Croll (http://javascriptweblog.wordpress.com/)

	@method typeOf
	@for Utils
	@static
	@param {Object} o Object to check.
	@return {String} Object [[Class]]
	*/
	var typeOf = function(o) {
		// the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
		var undef;
		if (o === undef) {
			return 'undefined';
		} else if (o === null) {
			return 'null';
		} else if (o.nodeType) {
			return 'node';
		}
		return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
	};

	/**
	Extends the specified object with another object.

	@method extend
	@static
	@param {Object} target Object to extend.
	@param {Object} [obj]* Multiple objects to extend with.
	@return {Object} Same as target, the extended object.
	*/
	var extend = function(target) {
		each(arguments, function(arg, i) {
			if (i > 0) {
				each(arg, function(value, key) {
					if (value !== undefined) {
						if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) {
							extend(target[key], value);
						} else {
							target[key] = value;
						}
					}
				});
			}
		});
		return target;
	};

	/**
	Executes the callback function for each item in array/object. If you return false in the
	callback it will break the loop.

	@method each
	@static
	@param {Object} obj Object to iterate.
	@param {function} callback Callback function to execute for each item.
	*/
	var each = function(obj, callback) {
		var length, key, i;

		if (obj) {
			try {
				length = obj.length;
			} catch(ex) {
				length = undefined;
			}

			if (length === undefined) {
				// Loop object items
				for (key in obj) {
					if (obj.hasOwnProperty(key)) {
						if (callback(obj[key], key) === false) {
							return;
						}
					}
				}
			} else {
				// Loop array items
				for (i = 0; i < length; i++) {
					if (callback(obj[i], i) === false) {
						return;
					}
				}
			}
		}
	};

	/**
	Checks if object is empty.

	@method isEmptyObj
	@static
	@param {Object} o Object to check.
	@return {Boolean}
	*/
	var isEmptyObj = function(obj) {
		if (!obj || typeOf(obj) !== 'object') {
			return true;
		}

		for (var prop in obj) {
			return false;
		}

		return true;
	};

	/**
	Recieve an array of functions (usually async) to call in sequence, each  function
	receives a callback as first argument that it should call, when it completes. Finally,
	after everything is complete, main callback is called. Passing truthy value to the
	callback as a first argument will interrupt the sequence and invoke main callback
	immediately.

	@method inSeries
	@static
	@param {Array} queue Array of functions to call in sequence
	@param {Function} cb Main callback that is called in the end, or in case of erro
	*/
	var inSeries = function(queue, cb) {
		var i = 0, length = queue.length;

		if (typeOf(cb) !== 'function') {
			cb = function() {};
		}

		function callNext(i) {
			if (typeOf(queue[i]) === 'function') {
				queue[i](function(error) {
					++i < length && !error ? callNext(i) : cb(error);
				});
			}
		}
		callNext(i);
	};

	/**
	Find an element in array and return it's index if present, otherwise return -1.

	@method inArray
	@static
	@param {Mixed} needle Element to find
	@param {Array} array
	@return {Int} Index of the element, or -1 if not found
	*/
	var inArray = function(needle, array) {
		if (array) {
			if (Array.prototype.indexOf) {
				return Array.prototype.indexOf.call(array, needle);
			}

			for (var i = 0, length = array.length; i < length; i++) {
				if (array[i] === needle) {
					return i;
				}
			}
		}
		return -1;
	};

	/**
	Forces anything into an array.

	@method toArray
	@static
	@param {Object} obj Object with length field.
	@return {Array} Array object containing all items.
	*/
	var toArray = function(obj) {
		var i, arr = [];

		for (i = 0; i < obj.length; i++) {
			arr[i] = obj[i];
		}

		return arr;
	};

	/**
	Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
	The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
	to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
	It's more probable for the earth to be hit with an ansteriod. Y

	@method guid
	@static
	@param {String} prefix to prepend (by default 'o' will be prepended).
	@method guid
	@return {String} Virtually unique id.
	*/
	var guid = (function() {
		var counter = 0;

		return function(prefix) {
			var guid = new Date().getTime().toString(32), i;

			for (i = 0; i < 5; i++) {
				guid += Math.floor(Math.random() * 65535).toString(32);
			}

			return (prefix || 'o_') + guid + (counter++).toString(32);
		};
	}());

	/**
	Trims white spaces around the string

	@method trim
	@static
	@param {String} str
	@return {String}
	*/
	var trim = function(str) {
		if (!str) {
			return str;
		}
		return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
	};

	/**
	Parses the specified size string into a byte value. For example 10kb becomes 10240.

	@method parseSizeStr
	@static
	@param {String/Number} size String to parse or number to just pass through.
	@return {Number} Size in bytes.
	*/
	var parseSizeStr = function(size) {
		if (typeof(size) !== 'string') {
			return size;
		}

		var muls = {
				t: 1099511627776,
				g: 1073741824,
				m: 1048576,
				k: 1024
			},
			mul;

		size = /^([0-9]+)([mgk]?)$/.exec(size.toLowerCase().replace(/[^0-9mkg]/g, ''));
		mul = size[2];
		size = +size[1];

		if (muls.hasOwnProperty(mul)) {
			size *= muls[mul];
		}
		return size;
	};

	return {
		byId: byId,
		guid: guid,
		typeOf: typeOf,
		extend: extend,
		each: each,
		isEmptyObj: isEmptyObj,
		inSeries: inSeries,
		inArray: inArray,
		toArray: toArray,
		trim: trim
	};
});<commit_msg>Basic.inSeries(): Invoke the callback instantly for empty queue.<commit_after>/**
 * Basic.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:false, scripturl:true, browser:true */
/*global define:true */

define('moxie/core/utils/Basic', [], function() {
	/**
	Get DOM Element by it's id.

	@method byId
	@param {String} id Identifier of the DOM Element
	@return {DOMElement}
	*/
	var byId = function(id) {
		if (typeof id !== 'string') {
			return id;
		}
		return document.getElementById(id);
	};

	/**
	Gets the true type of the built-in object (better version of typeof).
	@author Angus Croll (http://javascriptweblog.wordpress.com/)

	@method typeOf
	@for Utils
	@static
	@param {Object} o Object to check.
	@return {String} Object [[Class]]
	*/
	var typeOf = function(o) {
		// the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
		var undef;
		if (o === undef) {
			return 'undefined';
		} else if (o === null) {
			return 'null';
		} else if (o.nodeType) {
			return 'node';
		}
		return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
	};

	/**
	Extends the specified object with another object.

	@method extend
	@static
	@param {Object} target Object to extend.
	@param {Object} [obj]* Multiple objects to extend with.
	@return {Object} Same as target, the extended object.
	*/
	var extend = function(target) {
		each(arguments, function(arg, i) {
			if (i > 0) {
				each(arg, function(value, key) {
					if (value !== undefined) {
						if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) {
							extend(target[key], value);
						} else {
							target[key] = value;
						}
					}
				});
			}
		});
		return target;
	};

	/**
	Executes the callback function for each item in array/object. If you return false in the
	callback it will break the loop.

	@method each
	@static
	@param {Object} obj Object to iterate.
	@param {function} callback Callback function to execute for each item.
	*/
	var each = function(obj, callback) {
		var length, key, i;

		if (obj) {
			try {
				length = obj.length;
			} catch(ex) {
				length = undefined;
			}

			if (length === undefined) {
				// Loop object items
				for (key in obj) {
					if (obj.hasOwnProperty(key)) {
						if (callback(obj[key], key) === false) {
							return;
						}
					}
				}
			} else {
				// Loop array items
				for (i = 0; i < length; i++) {
					if (callback(obj[i], i) === false) {
						return;
					}
				}
			}
		}
	};

	/**
	Checks if object is empty.

	@method isEmptyObj
	@static
	@param {Object} o Object to check.
	@return {Boolean}
	*/
	var isEmptyObj = function(obj) {
		if (!obj || typeOf(obj) !== 'object') {
			return true;
		}

		for (var prop in obj) {
			return false;
		}

		return true;
	};

	/**
	Recieve an array of functions (usually async) to call in sequence, each  function
	receives a callback as first argument that it should call, when it completes. Finally,
	after everything is complete, main callback is called. Passing truthy value to the
	callback as a first argument will interrupt the sequence and invoke main callback
	immediately.

	@method inSeries
	@static
	@param {Array} queue Array of functions to call in sequence
	@param {Function} cb Main callback that is called in the end, or in case of erro
	*/
	var inSeries = function(queue, cb) {
		var i = 0, length = queue.length;

		if (typeOf(cb) !== 'function') {
			cb = function() {};
		}

		if (!queue || !queue.length) {
			cb();
		}

		function callNext(i) {
			if (typeOf(queue[i]) === 'function') {
				queue[i](function(error) {
					++i < length && !error ? callNext(i) : cb(error);
				});
			}
		}
		callNext(i);
	};

	/**
	Find an element in array and return it's index if present, otherwise return -1.

	@method inArray
	@static
	@param {Mixed} needle Element to find
	@param {Array} array
	@return {Int} Index of the element, or -1 if not found
	*/
	var inArray = function(needle, array) {
		if (array) {
			if (Array.prototype.indexOf) {
				return Array.prototype.indexOf.call(array, needle);
			}

			for (var i = 0, length = array.length; i < length; i++) {
				if (array[i] === needle) {
					return i;
				}
			}
		}
		return -1;
	};

	/**
	Forces anything into an array.

	@method toArray
	@static
	@param {Object} obj Object with length field.
	@return {Array} Array object containing all items.
	*/
	var toArray = function(obj) {
		var i, arr = [];

		for (i = 0; i < obj.length; i++) {
			arr[i] = obj[i];
		}

		return arr;
	};

	/**
	Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
	The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
	to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
	It's more probable for the earth to be hit with an ansteriod. Y

	@method guid
	@static
	@param {String} prefix to prepend (by default 'o' will be prepended).
	@method guid
	@return {String} Virtually unique id.
	*/
	var guid = (function() {
		var counter = 0;

		return function(prefix) {
			var guid = new Date().getTime().toString(32), i;

			for (i = 0; i < 5; i++) {
				guid += Math.floor(Math.random() * 65535).toString(32);
			}

			return (prefix || 'o_') + guid + (counter++).toString(32);
		};
	}());

	/**
	Trims white spaces around the string

	@method trim
	@static
	@param {String} str
	@return {String}
	*/
	var trim = function(str) {
		if (!str) {
			return str;
		}
		return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
	};

	/**
	Parses the specified size string into a byte value. For example 10kb becomes 10240.

	@method parseSizeStr
	@static
	@param {String/Number} size String to parse or number to just pass through.
	@return {Number} Size in bytes.
	*/
	var parseSizeStr = function(size) {
		if (typeof(size) !== 'string') {
			return size;
		}

		var muls = {
				t: 1099511627776,
				g: 1073741824,
				m: 1048576,
				k: 1024
			},
			mul;

		size = /^([0-9]+)([mgk]?)$/.exec(size.toLowerCase().replace(/[^0-9mkg]/g, ''));
		mul = size[2];
		size = +size[1];

		if (muls.hasOwnProperty(mul)) {
			size *= muls[mul];
		}
		return size;
	};

	return {
		byId: byId,
		guid: guid,
		typeOf: typeOf,
		extend: extend,
		each: each,
		isEmptyObj: isEmptyObj,
		inSeries: inSeries,
		inArray: inArray,
		toArray: toArray,
		trim: trim
	};
});<|endoftext|>


<commit_before>import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import CoreAbilities from 'Parser/Core/Modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    return [
      {
        spell: SPELLS.MONGOOSE_BITE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 12 / (1 + haste),
        charges: 3,
        isOnGCD: true,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.THROWING_AXES_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 15 / (1 + haste),
        charges: 2,
        enabled: this.combatants.selected.hasTalent(SPELLS.THROWING_AXES_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.FLANKING_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: haste => 6 / (1 + haste),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.CARVE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        enabled: !this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id),
      },
      {
        spell: SPELLS.FURY_OF_THE_EAGLE_TRAIT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: 45,
      },
      {
        spell: SPELLS.EXPLOSIVE_TRAP_CAST,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: 24,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .75,
        },
      },
      {
        spell: SPELLS.A_MURDER_OF_CROWS_TALENT_SURVIVAL,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 60,
        enabled: this.combatants.selected.hasTalent(SPELLS.A_MURDER_OF_CROWS_TALENT_SURVIVAL.id),
        isOnGCD: true,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.SNAKE_HUNTER_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 120,
        isOnGCD: false,
        enabled: this.combatants.selected.hasTalent(SPELLS.SNAKE_HUNTER_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.CALTROPS_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 12,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.CALTROPS_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.6,
        },
      },
      {
        spell: SPELLS.STEEL_TRAP_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 48,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.STEEL_TRAP_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.STICKY_BOMB_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 25,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.STICKY_BOMB_TALENT.id),
      },
      {
        spell: SPELLS.RANGERS_NET_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 1,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.RANGERS_NET_TALENT.id),
      },
      {
        spell: SPELLS.BUTCHERY_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 12 / (1 + haste),
        charges: 3,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.DRAGONSFIRE_GRENADE_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 30,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.DRAGONSFIRE_GRENADE_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.SPITTING_COBRA_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 60,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.SPITTING_COBRA_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.RAPTOR_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.HATCHET_TOSS,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.LACERATE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_EAGLE,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 120 - (120 * 0.2) : 120;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_CHEETAH,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 180 - (180 * 0.2) : 180;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_TURTLE,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 180 - (180 * 0.2) : 180;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.EXHILARATION,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        isOnGCD: false,
      },
      {
        spell: SPELLS.HARPOON,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        isOnGCD: true,
        cooldown: 20,
      },
      {
        spell: SPELLS.MUZZLE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 15,
        isOnGCD: false,
      },
      {
        spell: SPELLS.DISENGAGE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 20,
        isOnGCD: false,
      },
      {
        spell: SPELLS.FREEZING_TRAP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 24,
        enabled: !this.combatants.selected.hasTalent(SPELLS.STEEL_TRAP_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.TAR_TRAP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 24,
        enabled: !this.combatants.selected.hasTalent(SPELLS.CALTROPS_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.FLARE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 20,
        isOnGCD: true,
      },
      {
        spell: SPELLS.WING_CLIP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: !this.combatants.selected.hasTalent(SPELLS.RANGERS_NET_TALENT.id),
        isOnGCD: true,
      },
    ];
  }
}

export default Abilities;
<commit_msg>slight CE adjustments<commit_after>import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import CoreAbilities from 'Parser/Core/Modules/Abilities';

class Abilities extends CoreAbilities {
  spellbook() {
    return [
      {
        spell: SPELLS.MONGOOSE_BITE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 12 / (1 + haste),
        charges: 3,
        isOnGCD: true,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.THROWING_AXES_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 15 / (1 + haste),
        charges: 2,
        enabled: this.combatants.selected.hasTalent(SPELLS.THROWING_AXES_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.FLANKING_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: haste => 6 / (1 + haste),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .9,
        },
      },
      {
        spell: SPELLS.CARVE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        enabled: !this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id),
      },
      {
        spell: SPELLS.FURY_OF_THE_EAGLE_TRAIT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: 45,
      },
      {
        spell: SPELLS.EXPLOSIVE_TRAP_CAST,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
        cooldown: 24,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .75,
        },
      },
      {
        spell: SPELLS.A_MURDER_OF_CROWS_TALENT_SURVIVAL,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 60,
        enabled: this.combatants.selected.hasTalent(SPELLS.A_MURDER_OF_CROWS_TALENT_SURVIVAL.id),
        isOnGCD: true,
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.SNAKE_HUNTER_TALENT,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: 120,
        isOnGCD: false,
        enabled: this.combatants.selected.hasTalent(SPELLS.SNAKE_HUNTER_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.85,
        },
      },
      {
        spell: SPELLS.CALTROPS_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 12,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.CALTROPS_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.6,
        },
      },
      {
        spell: SPELLS.STEEL_TRAP_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 48,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.STEEL_TRAP_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.STICKY_BOMB_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 25,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.STICKY_BOMB_TALENT.id),
      },
      {
        spell: SPELLS.RANGERS_NET_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 1,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.RANGERS_NET_TALENT.id),
      },
      {
        spell: SPELLS.BUTCHERY_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: haste => 12 / (1 + haste),
        charges: 3,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: 0.95,
        },
      },
      {
        spell: SPELLS.DRAGONSFIRE_GRENADE_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 30,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.DRAGONSFIRE_GRENADE_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.SPITTING_COBRA_TALENT,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        cooldown: 60,
        isOnGCD: true,
        enabled: this.combatants.selected.hasTalent(SPELLS.SPITTING_COBRA_TALENT.id),
        castEfficiency: {
          suggestion: true,
          recommendedEfficiency: .95,
        },
      },
      {
        spell: SPELLS.RAPTOR_STRIKE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.HATCHET_TOSS,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.LACERATE,
        category: Abilities.SPELL_CATEGORIES.ROTATIONAL,
        isOnGCD: true,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_EAGLE,
        category: Abilities.SPELL_CATEGORIES.COOLDOWNS,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 120 - (120 * 0.2) : 120;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_CHEETAH,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 180 - (180 * 0.2) : 180;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.ASPECT_OF_THE_TURTLE,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: () => {
          const hasEmbrace = this.combatants.selected.traitsBySpellId[SPELLS.EMBRACE_OF_THE_ASPECTS.id];
          const cooldownAfterEmbrace = hasEmbrace ? 180 - (180 * 0.2) : 180;
          const hasCallOfTheWild = this.combatants.selected.hasWrists(ITEMS.CALL_OF_THE_WILD.id);
          return cooldownAfterEmbrace * (1 - (hasCallOfTheWild ? 0.35 : 0));
        },
        isOnGCD: false,
      },
      {
        spell: SPELLS.EXHILARATION,
        category: Abilities.SPELL_CATEGORIES.DEFENSIVE,
        cooldown: 120,
        isOnGCD: false,
      },
      {
        spell: SPELLS.HARPOON,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        isOnGCD: true,
        cooldown: 20,
      },
      {
        spell: SPELLS.MUZZLE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 15,
        isOnGCD: false,
      },
      {
        spell: SPELLS.DISENGAGE_TALENT,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 20,
        isOnGCD: false,
      },
      {
        spell: SPELLS.FREEZING_TRAP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 24,
        enabled: !this.combatants.selected.hasTalent(SPELLS.STEEL_TRAP_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.TAR_TRAP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 24,
        enabled: !this.combatants.selected.hasTalent(SPELLS.CALTROPS_TALENT.id),
        isOnGCD: true,
      },
      {
        spell: SPELLS.FLARE,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        cooldown: 20,
        isOnGCD: true,
      },
      {
        spell: SPELLS.WING_CLIP,
        category: Abilities.SPELL_CATEGORIES.UTILITY,
        enabled: !this.combatants.selected.hasTalent(SPELLS.RANGERS_NET_TALENT.id),
        isOnGCD: true,
      },
    ];
  }
}

export default Abilities;
<|endoftext|>