<commit_before>//index.js
//sass-lifter-loader
//lift sass from dependencies and write css to fs
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var loaderUtils = require("loader-utils");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var gutil = require('gulp-util');
var _ = require('lodash');
var sass = require('node-sass');
var CachePlugin = require("webpack/lib/CachePlugin");
var myCache = {};

var myWebpackConfig = {
    name: 'lift sass webpack',
    target: 'node',
    output: {
        libraryTarget: 'commonjs2',
        path: path.join(__dirname, 'example', 'dist'),
        filename: 'sass-lifter-loader-output'
    },
    resolve: {
        root: __dirname,
        fallback: __dirname + '/node_modules',
        modulesDirectories: ['node_modules'],
        extensions: ['', '.json', '.js', '.jsx', '.scss', '.png', '.jpg', '.jpeg', '.gif']
    },
    plugins: [
        new CachePlugin(myCache)
    ],
    resolveLoader: {
        root: __dirname,
        alias: {
            'lift-sass': 'passthru-loader',
            'passthru-loader': path.join(__dirname, 'passthru-loader')
        }
    },
    module: {
        loaders: [
                {
                    test: /\.scss$/,
                    loaders: [
                        'noop-loader'
                    ]
                }
                , {
                    test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'passthru-loader'
                    ]
                }
                , {
                    test: /\.json$/,
                    loaders: ['json-loader']
                }
                , {
                    test: /\.jsx$/,
                    loaders: ['babel']
                }
            ]
    },
    bail: true,
    cache: true,
    debug: true,
    externals: [{ 'react/addons' : true, 'newrelic' : true }]
};

module.exports = function(moduleSource) {

    if(this.cacheable) this.cacheable();

    var query = loaderUtils.parseQuery(this.query);
    var testString = query.testString || 'scss';
    var re = new RegExp('' + testString + '', 'g');
    var callback = this.async();
    var self = this;
    var fileName = this.resourcePath.split('/').splice(-1)[0];
    var manifest = path.join(query.outputDir, query.manifest);

    gutil.log('sass-lifter: lifting', gutil.colors.blue(fileName));

    myWebpackConfig.entry = {
        'lift-sass-loader-entry': this.resourcePath
    };

    webpack(myWebpackConfig, function (err, stats) {

        if (err) throw err;

        stats.compilation.entries.map(function(entry) {

            var deps = entry.dependencies;
            //storage for recursive dependencies and output
            var visited = {};
            var cssOutput = [];

            function getNodes(root)  {
                //console.log('getNodes', root.userRequest);
                if (root.dependencies.length > 0) {
                    //console.log('has deps');
                    root.dependencies.forEach(function (child) {
                        //console.log('get child nodes');
                        if ( child.module && child.module.userRequest && !visited[child.module.userRequest]) {
                            visited[child.module.userRequest] = true;
                            getNodes(child.module);
                        }
                    });
                } else {
                    //console.log('no deps', root.userRequest);
                    visited[root.userRequest] = true;
                }
            }

            function replaceImages(source, options, cb) {

                var manifest = require(path.join(options.outputDir, options.manifest));
                var urlRE = new RegExp('[\\w.\\/\\-]*(png|gif|jpg|jpeg|svg)', 'gi');
                var urls = source.match(urlRE) || [];

                urls.map(function(url){
                    var fileRE = new RegExp(url);
                    var prefix = options.prefix || '';
                    if (manifest[url]) {
                        source = source.replace(fileRE, path.join(prefix, manifest[url]));
                    }
                });
                cb(source);
            }

            for (var i = 0; i < deps.length; i++) {
                //console.log('depsi', deps[i].userRequest);
                if (deps[i].userRequest) {
                    //console.log('deps.........', deps[i].module.userRequest);
                    getNodes(deps[i].module);
                }
            }

            //get paths for match
            var foundPaths = [];
            _.mapKeys(visited, function (value, key) {
                if (re.test(key.toString())) {
                    //console.log('scss', key);
                    foundPaths.push(key);
                }
            });

            for (var j = 0; j < foundPaths.length; j++) {

                self.addDependency(foundPaths[j]);

                var result = sass.renderSync({
                    file: foundPaths[j]
                });

                if (query.manifest) {
                    //console.log('replacing images', manifest);
                    replaceImages(result.css.toString(), query, function(str){
                        //console.log(str);
                        cssOutput.push(str);
                    });

                } else {
                    cssOutput.push(result.css.toString());
                }
            }

            //create outputs
            var outputFileNameBasic = fileName +'.css';
            var outputFileName = path.join(query.outputDir, fileName + '.css');
            var outputManifestFile = path.join(query.outputDir, 'sass-loader-manifest.json');

            //create current manifest
            var outputManifest = {};
            outputManifest[fileName.split('.')[0]] = fileName + '.css';

            //join with previous manifest
            try {
                var readManifest = fs.readFileSync(outputManifestFile, 'utf8');
                outputManifest = _.extend(outputManifest, JSON.parse(readManifest));
                //console.log('output manifest joined', outputManifest);
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch (err) {
                    gutil.log('sass-lifter:', gutil.colors.red('error appending manifest'), err);
                }
            } catch (err) {
                gutil.log('sass-lifter:', gutil.colors.blue('manifest not found, creating manifest...'));
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch(err) {
                    gutil.log('sass-lifter:', gutil.colors.red('could not create manifest'), err);
                }
            }

            //write css
            fs.writeFile(outputFileName, cssOutput.join(''), function (err) {
                if (err) {
                    return console.log(err);
                }
                gutil.log('sass-lifter:', gutil.colors.green(outputFileName), 'was saved');
            });

            callback(null, moduleSource);

        });
    });

};<commit_msg>adding externals<commit_after>//index.js
//sass-lifter-loader
//lift sass from dependencies and write css to fs
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var loaderUtils = require("loader-utils");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var gutil = require('gulp-util');
var _ = require('lodash');
var sass = require('node-sass');
var CachePlugin = require("webpack/lib/CachePlugin");
var myCache = {};

//require common.js for node_modules (better for server)
var node_modules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' });
function node_externals(context, request, cb) {
    if(node_modules.indexOf(request) !== -1) {
        cb(null, 'commonjs ' + request);
        return;
    }
    cb();
}

var myWebpackConfig = {
    name: 'lift sass webpack',
    target: 'node',
    output: {
        libraryTarget: 'commonjs2',
        path: path.join(__dirname, 'example', 'dist'),
        filename: 'sass-lifter-loader-output'
    },
    resolve: {
        root: __dirname,
        fallback: __dirname + '/node_modules',
        modulesDirectories: ['node_modules'],
        extensions: ['', '.json', '.js', '.jsx', '.scss', '.png', '.jpg', '.jpeg', '.gif']
    },
    plugins: [
        new CachePlugin(myCache)
    ],
    resolveLoader: {
        root: __dirname,
        alias: {
            'lift-sass': 'passthru-loader',
            'passthru-loader': path.join(__dirname, 'passthru-loader')
        }
    },
    module: {
        loaders: [
                {
                    test: /\.scss$/,
                    loaders: [
                        'noop-loader'
                    ]
                }
                , {
                    test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'passthru-loader'
                    ]
                }
                , {
                    test: /\.json$/,
                    loaders: ['json-loader']
                }
                , {
                    test: /\.jsx$/,
                    loaders: ['babel']
                }
            ]
    },
    bail: true,
    cache: true,
    debug: true,
    externals: [{ 'react/addons' : true, 'newrelic' : true }, node_externals]
};

module.exports = function(moduleSource) {

    if(this.cacheable) this.cacheable();

    var query = loaderUtils.parseQuery(this.query);
    var testString = query.testString || 'scss';
    var re = new RegExp('' + testString + '', 'g');
    var callback = this.async();
    var self = this;
    var fileName = this.resourcePath.split('/').splice(-1)[0];
    var manifest = path.join(query.outputDir, query.manifest);

    gutil.log('sass-lifter: lifting', gutil.colors.blue(fileName));

    myWebpackConfig.entry = {
        'lift-sass-loader-entry': this.resourcePath
    };

    webpack(myWebpackConfig, function (err, stats) {

        if (err) throw err;

        stats.compilation.entries.map(function(entry) {

            var deps = entry.dependencies;
            //storage for recursive dependencies and output
            var visited = {};
            var cssOutput = [];

            function getNodes(root)  {
                //console.log('getNodes', root.userRequest);
                if (root.dependencies.length > 0) {
                    //console.log('has deps');
                    root.dependencies.forEach(function (child) {
                        //console.log('get child nodes');
                        if ( child.module && child.module.userRequest && !visited[child.module.userRequest]) {
                            visited[child.module.userRequest] = true;
                            getNodes(child.module);
                        }
                    });
                } else {
                    //console.log('no deps', root.userRequest);
                    visited[root.userRequest] = true;
                }
            }

            function replaceImages(source, options, cb) {

                var manifest = require(path.join(options.outputDir, options.manifest));
                var urlRE = new RegExp('[\\w.\\/\\-]*(png|gif|jpg|jpeg|svg)', 'gi');
                var urls = source.match(urlRE) || [];

                urls.map(function(url){
                    var fileRE = new RegExp(url);
                    var prefix = options.prefix || '';
                    if (manifest[url]) {
                        source = source.replace(fileRE, path.join(prefix, manifest[url]));
                    }
                });
                cb(source);
            }

            for (var i = 0; i < deps.length; i++) {
                //console.log('depsi', deps[i].userRequest);
                if (deps[i].userRequest) {
                    //console.log('deps.........', deps[i].module.userRequest);
                    getNodes(deps[i].module);
                }
            }

            //get paths for match
            var foundPaths = [];
            _.mapKeys(visited, function (value, key) {
                if (re.test(key.toString())) {
                    //console.log('scss', key);
                    foundPaths.push(key);
                }
            });

            for (var j = 0; j < foundPaths.length; j++) {

                self.addDependency(foundPaths[j]);

                var result = sass.renderSync({
                    file: foundPaths[j]
                });

                if (query.manifest) {
                    //console.log('replacing images', manifest);
                    replaceImages(result.css.toString(), query, function(str){
                        //console.log(str);
                        cssOutput.push(str);
                    });

                } else {
                    cssOutput.push(result.css.toString());
                }
            }

            //create outputs
            var outputFileNameBasic = fileName +'.css';
            var outputFileName = path.join(query.outputDir, fileName + '.css');
            var outputManifestFile = path.join(query.outputDir, 'sass-loader-manifest.json');

            //create current manifest
            var outputManifest = {};
            outputManifest[fileName.split('.')[0]] = fileName + '.css';

            //join with previous manifest
            try {
                var readManifest = fs.readFileSync(outputManifestFile, 'utf8');
                outputManifest = _.extend(outputManifest, JSON.parse(readManifest));
                //console.log('output manifest joined', outputManifest);
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch (err) {
                    gutil.log('sass-lifter:', gutil.colors.red('error appending manifest'), err);
                }
            } catch (err) {
                gutil.log('sass-lifter:', gutil.colors.blue('manifest not found, creating manifest...'));
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch(err) {
                    gutil.log('sass-lifter:', gutil.colors.red('could not create manifest'), err);
                }
            }

            //write css
            fs.writeFile(outputFileName, cssOutput.join(''), function (err) {
                if (err) {
                    return console.log(err);
                }
                gutil.log('sass-lifter:', gutil.colors.green(outputFileName), 'was saved');
            });

            callback(null, moduleSource);

        });
    });

};<|endoftext|>


<commit_before>'use strict';

var NAME = 'gulp-less-json-import';

var through2        = require('through2');
var gutil           = require('gulp-util');
var StringDecoder   = require('string_decoder').StringDecoder;
var Buffer = require('buffer').Buffer;
var path            = require('path');
var fs              = require('fs');

var PluginError    = gutil.PluginError;

var importMatcher = /^\s?@json-import "(.*?)";/;

module.exports = function () {
    return through2.obj(function(file, encoding, callback){

        if(file.isStream()){
            return callback(new PluginError(NAME, 'Stream mode not supported'));
        }

        var decoder = new StringDecoder(encoding);
        var fileDir = path.dirname(file.path);

        var content = decoder.write(file.contents).split('\n');

        for(var i = 0; i < content.length; i++){
            var match = importMatcher.exec(content[i]);
            if(!match) continue;

            var jsonPath = path.resolve(path.join(fileDir, match[1]));

            if(path.parse(jsonPath).ext != '.json'){
                jsonPath += '.json';
            }

            var jsonContent = {};

            try{
                jsonContent = require(jsonPath);
            } catch (e){
                gutil.log(NAME, 'can\'t load "'+jsonPath+'"');
            }

            var lessContent = [];
            for(var key in jsonContent){
                lessContent.push('@');
                lessContent.push(key);
                lessContent.push(': ');
                lessContent.push(jsonContent[key]);
                lessContent.push(';\n');
            }

            content[i] = lessContent.join('');

        }

        file.contents = new Buffer(content.join('\n'));

        this.push(file);

        callback();
    });
};<commit_msg>Implement new processor call + overridable  var name formatter.<commit_after>'use strict';

var NAME = 'gulp-less-json-import';

var through2        = require('through2');
var gutil           = require('gulp-util');
var StringDecoder   = require('string_decoder').StringDecoder;
var Buffer          = require('buffer').Buffer;
var path            = require('path');
var fs              = require('fs');

var PluginError    = gutil.PluginError;

var importMatcher = /^\s?@json-import "(.*?)";/;
var defaultNameFormatter = function(path){
    return path.join('-');
};

module.exports = function (options) {
    var nameFormatter = defaultNameFormatter;
    if(options && options.nameFormatter) nameFormatter = options.nameFormatter;

    return through2.obj(function(file, encoding, callback){

        if(file.isStream()){
            return callback(new PluginError(NAME, 'Stream mode not supported'));
        }

        var decoder = new StringDecoder(encoding);
        var fileDir = path.dirname(file.path);

        var content = decoder.write(file.contents).split('\n');

        for(var i = 0; i < content.length; i++){
            var match = importMatcher.exec(content[i]);
            if(!match) continue;

            var jsonPath = path.resolve(path.join(fileDir, match[1]));

            if(path.parse(jsonPath).ext != '.json'){
                jsonPath += '.json';
            }

            var jsonContent = {};

            try{
                jsonContent = require(jsonPath);
            } catch (e){
                gutil.log(NAME, 'can\'t load "'+jsonPath+'"');
            }

            var lessContent = [];

            (function exploreJson(currentLevel, path){
                for(var key in currentLevel){
                    switch (typeof currentLevel){
                        default:
                            lessContent.push('@');
                            lessContent.push(nameFormatter(path.concat(key)));
                            lessContent.push(': ');
                            lessContent.push(currentLevel[key]);
                            lessContent.push(';\n');
                    }
                }
            })(jsonContent, []);

            content[i] = lessContent.join('');

        }

        file.contents = new Buffer(content.join('\n'));

        this.push(file);

        callback();
    });
};<|endoftext|>


<commit_before>/**
 * Handlebars Helpers: {{include}}
 * Copyright (c) 2013 Jon Schlinkert
 * Licensed under the MIT License (MIT).
 */

var path = require('path');
var _ = require('lodash');
var yfm = require('assemble-yaml');
var minimatch = require('minimatch');

// Export helpers
module.exports.register = function (Handlebars, options, params) {

  'use strict';

  var assemble = params.assemble;
  var grunt = params.grunt;
  var opts = options || {};

  /**
   * {{partial}}
   * Alternative to {{> partial }}
   *
   * @param  {String} name    The name of the partial to use
   * @param  {Object} context The context to pass to the partial
   * @return {String}         Returns compiled HTML
   * @xample: {{partial 'foo' bar}}
   */
  Handlebars.registerHelper('include', function(name, context) {

    if(!Array.isArray(assemble.partials)) {
      assemble.partials = [assemble.partials];
    }

    // first try to match on the full name in the assemble.partials array
    var filepaths = _.filter(assemble.partials, function(filepath) {
      return path.basename(filepath, path.extname(filepath)) === name;
    });

    // if no matches, then try minimatch
    if (!filepaths || filepaths.length <= 0) {
      filepaths = assemble.partials.filter(minimatch.filter(name));
    }

    //var partials = grunt.file.expand(fullpath).map(function(filepath) {
    var partials = filepaths.map(function(filepath) {
      name = path.basename(filepath, path.extname(filepath));

      // Process context, using YAML front-matter, grunt config and Assemble
      // options.data
      var pageObj = yfm.extract(filepath) || {};
      var metadata = pageObj.context || {};

      // `context`           = the given context (second parameter)
      // `metadata`          = YAML front matter of the partial
      // `opts.data[name]`   = JSON/YAML data file defined in Assemble
      //                       options.data with a basename
      //                       matching the name of the partial, e.g
      //                       {{partial 'foo'}} => foo.json
      // `this`              = Typically either YAML front matter of
      //                       the "inheriting" page, or a block
      //                       expression wrapping the helper
      // `opts`              = Custom properties defined in Assemble options
      // `grunt.config.data` = Data from grunt.config.data
      //                       (e.g. pkg: grunt.file.readJSON('package.json'))

      var ctx = _.extend({}, grunt.config.data, opts, this, opts.data[name], metadata, context);
      ctx = grunt.config.process(ctx);

      var template = Handlebars.partials[name];
      var fn = Handlebars.compile(template);

      var output = fn(ctx).replace(/^\s+/, '');

      // Prepend output with the filepath to the original partial
      var include = opts.include || opts.data.include || {};
      if(include.origin === true) {
        output = '<!-- ' + filepath + ' -->\n' + output;
      }

      return output;
    }).join('\n');

    return new Handlebars.SafeString(partials);
  });
};<commit_msg>another stray comment<commit_after>/**
 * Handlebars Helpers: {{include}}
 * Copyright (c) 2013 Jon Schlinkert
 * Licensed under the MIT License (MIT).
 */

var path = require('path');
var _ = require('lodash');
var yfm = require('assemble-yaml');
var minimatch = require('minimatch');

// Export helpers
module.exports.register = function (Handlebars, options, params) {

  'use strict';

  var assemble = params.assemble;
  var grunt = params.grunt;
  var opts = options || {};

  /**
   * {{partial}}
   * Alternative to {{> partial }}
   *
   * @param  {String} name    The name of the partial to use
   * @param  {Object} context The context to pass to the partial
   * @return {String}         Returns compiled HTML
   * @xample: {{partial 'foo' bar}}
   */
  Handlebars.registerHelper('include', function(name, context) {

    if(!Array.isArray(assemble.partials)) {
      assemble.partials = [assemble.partials];
    }

    // first try to match on the full name in the assemble.partials array
    var filepaths = _.filter(assemble.partials, function(filepath) {
      return path.basename(filepath, path.extname(filepath)) === name;
    });

    // if no matches, then try minimatch
    if (!filepaths || filepaths.length <= 0) {
      filepaths = assemble.partials.filter(minimatch.filter(name));
    }

    var partials = filepaths.map(function(filepath) {
      name = path.basename(filepath, path.extname(filepath));

      // Process context, using YAML front-matter, grunt config and Assemble
      // options.data
      var pageObj = yfm.extract(filepath) || {};
      var metadata = pageObj.context || {};

      // `context`           = the given context (second parameter)
      // `metadata`          = YAML front matter of the partial
      // `opts.data[name]`   = JSON/YAML data file defined in Assemble
      //                       options.data with a basename
      //                       matching the name of the partial, e.g
      //                       {{partial 'foo'}} => foo.json
      // `this`              = Typically either YAML front matter of
      //                       the "inheriting" page, or a block
      //                       expression wrapping the helper
      // `opts`              = Custom properties defined in Assemble options
      // `grunt.config.data` = Data from grunt.config.data
      //                       (e.g. pkg: grunt.file.readJSON('package.json'))

      var ctx = _.extend({}, grunt.config.data, opts, this, opts.data[name], metadata, context);
      ctx = grunt.config.process(ctx);

      var template = Handlebars.partials[name];
      var fn = Handlebars.compile(template);

      var output = fn(ctx).replace(/^\s+/, '');

      // Prepend output with the filepath to the original partial
      var include = opts.include || opts.data.include || {};
      if(include.origin === true) {
        output = '<!-- ' + filepath + ' -->\n' + output;
      }

      return output;
    }).join('\n');

    return new Handlebars.SafeString(partials);
  });
};<|endoftext|>


<commit_before>'use strict';
const electron = require('electron');
const app = electron.app;

// report crashes to the Electron project
require('crash-reporter').start();

// adds debug features like hotkeys for triggering dev tools and reload
require('electron-debug')();

// prevent window being garbage collected
let mainWindow;

function onClosed() {
	// dereference the window
	// for multiple windows store them in an array
	mainWindow = null;
}

function createMainWindow() {
	const win = new electron.BrowserWindow({
		width: 600,
		height: 400
	});

	win.loadURL(`file://${__dirname}/index.html`);
	win.on('closed', onClosed);

	return win;
}

app.on('window-all-closed', () => {
	if (process.platform !== 'darwin') {
		app.quit();
	}
});

app.on('activate', () => {
	if (!mainWindow) {
		mainWindow = createMainWindow();
	}
});

app.on('ready', () => {
	mainWindow = createMainWindow();
});
<commit_msg>20151224<commit_after>'use strict';
const electron = require('electron');
const app = electron.app;
const globalShortcut = electron.globalShortcut;

// report crashes to the Electron project
require('crash-reporter').start();

// adds debug features like hotkeys for triggering dev tools and reload
require('electron-debug')();

// prevent window being garbage collected
let mainWindow;

function onClosed() {
	// dereference the window
	// for multiple windows store them in an array
	mainWindow = null;
}

function createMainWindow() {
	const win = new electron.BrowserWindow({
		width: 600,
		height: 400
	});

	win.loadURL(`file://${__dirname}/index.html`);
	win.on('closed', onClosed);

	return win;
}

app.on('window-all-closed', () => {
	if (process.platform !== 'darwin') {
		app.quit();
	}
});

app.on('activate', () => {
	if (!mainWindow) {
		mainWindow = createMainWindow();
	}
});

app.on('ready', () => {
	mainWindow = createMainWindow();
  globalShortcut.register('ctrl+n',() => {
    console.log('ctrl+n pushed!');
  });
});
<|endoftext|>


<commit_before>'use strict';

const RtmClient = require('@slack/client').RtmClient;
  const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
  const RTM_EVENTS = require('@slack/client').RTM_EVENTS;
const WebClient = require('@slack/client').WebClient;
const Time = require('./time')
const NodeCache = require( "node-cache" );

const token = process.env.SLACK_BOT_TOKEN || '';
const rtm = new RtmClient(token)
const web = new WebClient(token)

const channelCacheTTL = 1 * 60 * 60 // 1 hour, in seconds
const userCacheTTL = 4 * 60 * 60 // 4 hours, in seconds
const cache = new NodeCache({ stdTTL: 30*60, checkperiod: 15*60 });

function getChannelInfo(channelID) {
  const cached = cache.get(channelID)
  if (cached != undefined) {
    console.log(`Got cached info for channel ${channelID}`)
    return Promise.resolve(cached)
  } else {
    return web.channels.info(channelID).catch((error) => {
      if (error.message == 'channel_not_found') {
        console.log(`[DEBUG] ${channelID} may be a private channel; trying to look that up…`)
        return web.groups.info(channelID)
      } else {
        console.log(`Cannot recover from error looking up ${channelID}: ${error}`)
      }
    }).then((response) => {
      const channelInfo = response.channel != undefined ? response.channel : response.group
      cache.set(channelID, channelInfo, channelCacheTTL)
      return channelInfo
    })
  }
}

function getUserInfo(userID) {
  const cached = cache.get(userID)
  if (cached != undefined) {
    console.log(`Got cached info for user ${userID}`)
    return Promise.resolve(cached)
  } else {
    return web.users.info(userID).then((response) => {
      const userInfo = response.user
      cache.set(userID, userInfo, userCacheTTL)
      return userInfo
    })
  }
}

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (rtmStartData) => {
  console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}`)
})

rtm.on(RTM_EVENTS.MESSAGE, (message) => {
  const localTime = Time.parseTime(message.text)
  if (localTime === null) return

  console.log(`[DEBUG] Got message with time ${Time.formatTime(localTime)} in channel ${message.channel}`)

  getChannelInfo(message.channel).then((channel) => {
    var usersToLookup = channel.members.slice(0)
    if (!usersToLookup.includes(message.user)) {
      usersToLookup.push(message.user)
    }

    Promise.all(usersToLookup.map((userID) => { return getUserInfo(userID) })).then((users) => {
      var targetZones = []
      var localZone

      users.forEach((user) => {
        if (user.is_bot) return

        const userZone = {
          'tz_label': user.tz_label,
          'tz_offset': user.tz_offset
        }

        if (user.id == message.user) {
          localZone = userZone
        } else if (!targetZones.includes(userZone)) {
          targetZones.push(userZone)
        }
      })

      targetZones.sort((a, b) => {
        return a.tz_offset - b.tz_offset
      })

      var reply = `*${Time.formatTime(localTime)}* in ${localZone.tz_label} is:`
      targetZones.forEach((zone) => {
        const offsetFromLocal = zone.tz_offset - localZone.tz_offset
        reply = reply + `\n${Time.formatTime(Time.applyOffsetToTime(localTime, offsetFromLocal))} in ${zone.tz_label}`
      })

      rtm.sendMessage(reply, message.channel)
    })
  })
})

rtm.start()
<commit_msg>Fix zone deduplication logic<commit_after>'use strict';

const RtmClient = require('@slack/client').RtmClient;
  const CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
  const RTM_EVENTS = require('@slack/client').RTM_EVENTS;
const WebClient = require('@slack/client').WebClient;
const Time = require('./time')
const NodeCache = require( "node-cache" );

const token = process.env.SLACK_BOT_TOKEN || '';
const rtm = new RtmClient(token)
const web = new WebClient(token)

const channelCacheTTL = 1 * 60 * 60 // 1 hour, in seconds
const userCacheTTL = 4 * 60 * 60 // 4 hours, in seconds
const cache = new NodeCache({ stdTTL: 30*60, checkperiod: 15*60 });

function getChannelInfo(channelID) {
  const cached = cache.get(channelID)
  if (cached != undefined) {
    console.log(`Got cached info for channel ${channelID}`)
    return Promise.resolve(cached)
  } else {
    return web.channels.info(channelID).catch((error) => {
      if (error.message == 'channel_not_found') {
        console.log(`[DEBUG] ${channelID} may be a private channel; trying to look that up…`)
        return web.groups.info(channelID)
      } else {
        console.log(`Cannot recover from error looking up ${channelID}: ${error}`)
      }
    }).then((response) => {
      const channelInfo = response.channel != undefined ? response.channel : response.group
      cache.set(channelID, channelInfo, channelCacheTTL)
      return channelInfo
    })
  }
}

function getUserInfo(userID) {
  const cached = cache.get(userID)
  if (cached != undefined) {
    console.log(`Got cached info for user ${userID}`)
    return Promise.resolve(cached)
  } else {
    return web.users.info(userID).then((response) => {
      const userInfo = response.user
      cache.set(userID, userInfo, userCacheTTL)
      return userInfo
    })
  }
}

function pushUniqueZone(zones, zone) {
  if (zones.find((element, idx, array) => { return element.tz_offset == zone.tz_offset }) == undefined) {
    zones.push(zone)
  }
}

function removeZone(zones, zone) {
  const idx = zones.findIndex((element, idx, array) => { return element.tz_offset == zone.tz_offset })
  console.log(idx)
  if (idx > -1) {
    zones.splice(idx, 1)
  }
}

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (rtmStartData) => {
  console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}`)
})

rtm.on(RTM_EVENTS.MESSAGE, (message) => {
  const localTime = Time.parseTime(message.text)
  if (localTime === null) return

  console.log(`[DEBUG] Got message with time ${Time.formatTime(localTime)} in channel ${message.channel}`)

  getChannelInfo(message.channel).then((channel) => {
    var usersToLookup = channel.members.slice(0)
    if (!usersToLookup.includes(message.user)) {
      usersToLookup.push(message.user)
    }

    Promise.all(usersToLookup.map((userID) => { return getUserInfo(userID) })).then((users) => {
      var targetZones = []
      var localZone

      users.forEach((user) => {
        if (user.is_bot) return

        const userZone = {
          'tz_label': user.tz_label,
          'tz_offset': user.tz_offset
        }

        if (user.id == message.user) {
          localZone = userZone
        } else {
          pushUniqueZone(targetZones, userZone)
        }
      })

      removeZone(targetZones, localZone)

      targetZones.sort((a, b) => {
        return a.tz_offset - b.tz_offset
      })

      var reply = `*${Time.formatTime(localTime)}* in ${localZone.tz_label} is:`
      targetZones.forEach((zone) => {
        const offsetFromLocal = zone.tz_offset - localZone.tz_offset
        reply = reply + `\n${Time.formatTime(Time.applyOffsetToTime(localTime, offsetFromLocal))} in ${zone.tz_label}`
      })

      rtm.sendMessage(reply, message.channel)
    })
  })
})

rtm.start()
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash'),
  debug = require('debug')('markov-strings');

class Generator {
  /**
   * Constructor
   * @param data An array of strings or objects. If 'data' is an array of objects, each object must have a 'string' attribute
   * @param options An object of options. If not set, sensible defaults will be used.
   */
  constructor(data, options = {}) {
    this.data = data;

    this.corpus = undefined;
    this.startWords = [];
    this.endWords = [];

    this.defaultOptions = {
      stateSize: 2,
      maxLength: 0,
      minWords: 0,
      maxWords: 0,
      minScore: 0,
      minScorePerWord: 0,
      maxTries: 10000
    };

    // Save options
    this.options = this.defaultOptions;
    _.assignIn(this.options, options);
  }

  formatData(data) {
    if (_.isString(data[0])) {
      // If data is an array of strings, wrap them into objects
      const newData = [];
      data.forEach(string => {
        newData.push({
          string: string
        })
      })
      return newData;
    }
    if (!data[0].hasOwnProperty('string')) {
      throw new Error('Objects in your corpus must have a "string" property');
    }
    return data;
  }

  buildCorpus() {
    return new Promise((resolve, reject) => {
      resolve(this.buildCorpusSync());
    });
  }

  buildCorpusSync() {
    const options = this.options;

    this.data = this.formatData(this.data);

    this.corpus = {};
    this.data.forEach(item => {
      const line = item.string;
      const words = line.split(' ');

      // Start words
      const start = _.slice(words, 0, options.stateSize).join(' ');
      const oldStartObj = _.find(this.startWords, o => o.words == start);
      if (oldStartObj) {
        if (!_.includes(oldStartObj.refs, item)) { oldStartObj.refs.push(item); }
      } else {
        this.startWords.push({ words: start, refs: [item] });
      }

      // End words
      const end = _.slice(words, words.length - options.stateSize, words.length).join(' ');
      const oldEndObj = _.find(this.endWords, o => o.words == end);
      if (oldEndObj) {
        if (!_.includes(oldEndObj.refs, item)) { oldEndObj.refs.push(item); }
      } else {
        this.endWords.push({ words: end, refs: [item] });
      }

      // Build corpus
      for (let i = 0; i < words.length - 1; i++) {
        const curr = _.slice(words, i, i + options.stateSize).join(' ');
        const next = _.slice(words, i + options.stateSize, i + options.stateSize * 2).join(' ');
        if (!next || next.split(' ').length != options.stateSize) {
          continue;
        }

        // Add block to corpus
        if (this.corpus.hasOwnProperty(curr)) {
          // If corpus already owns this chain
          const oldObj = _.find(this.corpus[curr], o => o.words == next);
          if (oldObj) {
            oldObj.refs.push(item);
          } else {
            this.corpus[curr].push({ words: next, refs: [item] })
          }
        } else {
          this.corpus[curr] = [{ words: next, refs: [item] }];
        }
      }
    });
  }

  generateSentence(options) {
    return new Promise((resolve, reject) => {
      try {
        const result = this.generateSentenceSync(options);
        resolve(result);
      } catch (e) {
        reject(e);
      }
    });
  }

  generateSentenceSync(options = {}) {
    if (!this.corpus) {
      throw new Error('Corpus is not built.')
    }
    const newOptions = {};
    _.assignIn(newOptions, this.options, options);
    options = newOptions;

    const corpus = _.cloneDeep(this.corpus);
    const max = options.maxTries;

    // Loop for maximum tries
    for (let i = 0; i < max; i++) {
      let ended = false;
      const arr = [_.sample(this.startWords)];
      let score = 0;

      // Loop to build sentence
      let limit = 0;
      while (limit < max) {
        const block = arr[arr.length - 1]; // Last value in array
        const state = _.sample(corpus[block.words]);

        // Sentence cannot be finished
        if (!state) {
          break;
        }

        // Add new state to list
        arr.push(state);

        // Increment score
        score += corpus[block.words].length - 1; // Increment score

        // Is sentence finished?
        const endObj = _.some(this.endWords, { words: state.words });
        if (endObj) {
          arr.push(endObj);
          ended = true;
          break;
        }
        limit++;
      }
      const scorePerWord = parseInt(score / arr.length);

      const sentence = _.map(arr, 'words').join(' ').trim();

      // Sentence is not ended or incorrect
      if (!ended ||
        typeof options.checker === 'function' && !options.checker(sentence) || // checker cb returns false
        options.minWords > 0 && sentence.split(' ').length < options.minWords ||
        options.maxWords > 0 && sentence.split(' ').length > options.maxWords ||
        options.maxLength > 0 && sentence.length > options.maxLength ||
        score < options.minScore ||
        scorePerWord < options.minScorePerWord
      ) {
        continue;
      }

      return {
        string: sentence,
        score: score,
        scorePerWord: scorePerWord,
        refs: _.uniqBy(_.flatten(_.map(arr, 'refs')), 'string')
      };
    }
    throw new Error('Cannot build sentence with current corpus and options');
  }
}

module.exports = Generator;
<commit_msg>Fixed bug introduced in previous commit<commit_after>'use strict';

const _ = require('lodash'),
  debug = require('debug')('markov-strings');

class Generator {
  /**
   * Constructor
   * @param data An array of strings or objects. If 'data' is an array of objects, each object must have a 'string' attribute
   * @param options An object of options. If not set, sensible defaults will be used.
   */
  constructor(data, options = {}) {
    this.data = data;

    this.corpus = undefined;
    this.startWords = [];
    this.endWords = [];

    this.defaultOptions = {
      stateSize: 2,
      maxLength: 0,
      minWords: 0,
      maxWords: 0,
      minScore: 0,
      minScorePerWord: 0,
      maxTries: 10000
    };

    // Save options
    this.options = this.defaultOptions;
    _.assignIn(this.options, options);
  }

  formatData(data) {
    if (_.isString(data[0])) {
      // If data is an array of strings, wrap them into objects
      const newData = [];
      data.forEach(string => {
        newData.push({
          string: string
        })
      })
      return newData;
    }
    if (!data[0].hasOwnProperty('string')) {
      throw new Error('Objects in your corpus must have a "string" property');
    }
    return data;
  }

  buildCorpus() {
    return new Promise((resolve, reject) => {
      resolve(this.buildCorpusSync());
    });
  }

  buildCorpusSync() {
    const options = this.options;

    this.data = this.formatData(this.data);

    this.corpus = {};
    this.data.forEach(item => {
      const line = item.string;
      const words = line.split(' ');

      // Start words
      const start = _.slice(words, 0, options.stateSize).join(' ');
      const oldStartObj = _.find(this.startWords, o => o.words == start);
      if (oldStartObj) {
        if (!_.includes(oldStartObj.refs, item)) { oldStartObj.refs.push(item); }
      } else {
        this.startWords.push({ words: start, refs: [item] });
      }

      // End words
      const end = _.slice(words, words.length - options.stateSize, words.length).join(' ');
      const oldEndObj = _.find(this.endWords, o => o.words == end);
      if (oldEndObj) {
        if (!_.includes(oldEndObj.refs, item)) { oldEndObj.refs.push(item); }
      } else {
        this.endWords.push({ words: end, refs: [item] });
      }

      // Build corpus
      for (let i = 0; i < words.length - 1; i++) {
        const curr = _.slice(words, i, i + options.stateSize).join(' ');
        const next = _.slice(words, i + options.stateSize, i + options.stateSize * 2).join(' ');
        if (!next || next.split(' ').length != options.stateSize) {
          continue;
        }

        // Add block to corpus
        if (this.corpus.hasOwnProperty(curr)) {
          // If corpus already owns this chain
          const oldObj = _.find(this.corpus[curr], o => o.words == next);
          if (oldObj) {
            oldObj.refs.push(item);
          } else {
            this.corpus[curr].push({ words: next, refs: [item] })
          }
        } else {
          this.corpus[curr] = [{ words: next, refs: [item] }];
        }
      }
    });
  }

  generateSentence(options) {
    return new Promise((resolve, reject) => {
      try {
        const result = this.generateSentenceSync(options);
        resolve(result);
      } catch (e) {
        reject(e);
      }
    });
  }

  generateSentenceSync(options = {}) {
    if (!this.corpus) {
      throw new Error('Corpus is not built.')
    }
    const newOptions = {};
    _.assignIn(newOptions, this.options, options);
    options = newOptions;

    const corpus = _.cloneDeep(this.corpus);
    const max = options.maxTries;

    // Loop for maximum tries
    for (let i = 0; i < max; i++) {
      let ended = false;
      const arr = [_.sample(this.startWords)];
      let score = 0;

      // Loop to build sentence
      let limit = 0;
      while (limit < max) {
        const block = arr[arr.length - 1]; // Last value in array
        const state = _.sample(corpus[block.words]);

        // Sentence cannot be finished
        if (!state) {
          break;
        }

        // Add new state to list
        arr.push(state);

        // Increment score
        score += corpus[block.words].length - 1; // Increment score

        // Is sentence finished?
        if (_.some(this.endWords, { words: state.words })) {
          ended = true;
          break;
        }
        limit++;
      }
      const scorePerWord = parseInt(score / arr.length);

      const sentence = _.map(arr, 'words').join(' ').trim();

      // Sentence is not ended or incorrect
      if (!ended ||
        typeof options.checker === 'function' && !options.checker(sentence) || // checker cb returns false
        options.minWords > 0 && sentence.split(' ').length < options.minWords ||
        options.maxWords > 0 && sentence.split(' ').length > options.maxWords ||
        options.maxLength > 0 && sentence.length > options.maxLength ||
        score < options.minScore ||
        scorePerWord < options.minScorePerWord
      ) {
        continue;
      }

      return {
        string: sentence,
        score: score,
        scorePerWord: scorePerWord,
        refs: _.uniqBy(_.flatten(_.map(arr, 'refs')), 'string')
      };
    }
    throw new Error('Cannot build sentence with current corpus and options');
  }
}

module.exports = Generator;
<|endoftext|>


<commit_before>'use strict'

var fs = require('fs')
var path = require('path')
var exec = require('child_process').exec
var execSync = require('child_process').execSync
var afterAll = require('after-all-results')

// Prevent from failing on windows
var nullPath = /^win/.test(process.platform) ? 'nul' : '/dev/null'

// Consider EOL as \n because either Windows or *nix, this escape char will be there
var EOL = /\r?\n/

exports.isGit = function (dir, cb) {
  fs.exists(path.join(dir, '.git'), cb)
}

exports.isGitSync = function (dir) {
  return fs.existsSync(path.join(dir, '.git'))
}

exports.checkSync = function (repo) {
  var branch = exports.branchSync(repo)
  var ahead = exports.aheadSync(repo)
  var status = statusSync(repo)
  var stashes = exports.stashesSync(repo)

  return {
    branch: branch,
    ahead: ahead,
    dirty: status.dirty,
    untracked: status.untracked,
    stashes: stashes
  }
}

exports.check = function (repo, cb) {
  var next = afterAll(function (err, results) {
    if (err) return cb(err)

    var branch = results[0]
    var ahead = results[1]
    var stashes = results[2]
    var status = results[3]

    cb(null, {
      branch: branch,
      ahead: ahead,
      dirty: status.dirty,
      untracked: status.untracked,
      stashes: stashes
    })
  })

  exports.branch(repo, next())
  exports.ahead(repo, next())
  exports.stashes(repo, next())
  status(repo, next())
}

exports.untracked = function (repo, cb) {
  status(repo, function (err, result) {
    if (err) return cb(err)
    cb(null, result.untracked)
  })
}

exports.dirty = function (repo, cb) {
  status(repo, function (err, result) {
    if (err) return cb(err)
    cb(null, result.dirty)
  })
}

exports.branch = function (repo, cb) {
  exec('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb() // most likely the git repo doesn't have any commits yet
    cb(null, stdout.trim())
  })
}

exports.ahead = function (repo, cb) {
  exec('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(null, NaN) // depending on the state of the git repo, the command might return non-0 exit code
    stdout = stdout.trim()
    cb(null, !stdout ? 0 : parseInt(stdout.split(EOL).length, 10))
  })
}

var status = function (repo, cb) {
  exec('git status -s', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var status = { dirty: 0, untracked: 0 }
    stdout.trim().split(EOL).filter(truthy).forEach(function (file) {
      if (file.substr(0, 2) === '??') status.untracked++
      else status.dirty++
    })
    cb(null, status)
  })
}

var truthy = function (obj) {
  return !!obj
}

exports.commit = function (repo, cb) {
  exec('git rev-parse --short HEAD', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var commitHash = stdout.trim()
    cb(null, commitHash)
  })
}

exports.stashes = function (repo, cb) {
  exec('git stash list', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var stashes = stdout.trim().split(EOL).filter(truthy)
    cb(null, stashes.length)
  })
}

//* SYNC methods *//
exports.untrackedSync = function (repo) {
  return statusSync(repo).untracked
}

exports.dirtySync = function (repo) {
  return statusSync(repo).dirty
}

exports.branchSync = function (repo) {
  try {
    var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', { cwd: repo }).toString()
    return stdout.trim()
  } catch (err) {
    return null // most likely the git repo doesn't have any commits yet
  }
}

exports.aheadSync = function (repo) {
  try {
    var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', { cwd: repo }).toString()
    stdout = stdout.trim()
    return !stdout ? 0 : parseInt(stdout.split(EOL).length, 10)
  } catch (err) {
    return NaN
  }
}

// Throws error
var statusSync = function (repo) {
  var stdout = execSync('git status -s', { cwd: repo }).toString()
  var status = { dirty: 0, untracked: 0 }
  stdout.trim().split(EOL).filter(truthy).forEach(function (file) {
    if (file.substr(0, 2) === '??') status.untracked++
    else status.dirty++
  })
  return status
}

// Throws error
exports.commitSync = function (repo) {
  var stdout = execSync('git rev-parse --short HEAD', { cwd: repo }).toString()
  var commitHash = stdout.trim()
  return commitHash
}

// Throws error
exports.stashesSync = function (repo) {
  var stdout = execSync('git stash list', { cwd: repo }).toString()
  var stashes = stdout.trim().split(EOL).filter(truthy)
  return stashes.length
}
<commit_msg>Name all functions<commit_after>'use strict'

var fs = require('fs')
var path = require('path')
var exec = require('child_process').exec
var execSync = require('child_process').execSync
var afterAll = require('after-all-results')

// Prevent from failing on windows
var nullPath = /^win/.test(process.platform) ? 'nul' : '/dev/null'

// Consider EOL as \n because either Windows or *nix, this escape char will be there
var EOL = /\r?\n/

exports.isGit = function isGit (dir, cb) {
  fs.exists(path.join(dir, '.git'), cb)
}

exports.isGitSync = function isGitSync (dir) {
  return fs.existsSync(path.join(dir, '.git'))
}

exports.checkSync = function checkSync (repo) {
  var branch = exports.branchSync(repo)
  var ahead = exports.aheadSync(repo)
  var status = statusSync(repo)
  var stashes = exports.stashesSync(repo)

  return {
    branch: branch,
    ahead: ahead,
    dirty: status.dirty,
    untracked: status.untracked,
    stashes: stashes
  }
}

exports.check = function check (repo, cb) {
  var next = afterAll(function (err, results) {
    if (err) return cb(err)

    var branch = results[0]
    var ahead = results[1]
    var stashes = results[2]
    var status = results[3]

    cb(null, {
      branch: branch,
      ahead: ahead,
      dirty: status.dirty,
      untracked: status.untracked,
      stashes: stashes
    })
  })

  exports.branch(repo, next())
  exports.ahead(repo, next())
  exports.stashes(repo, next())
  status(repo, next())
}

exports.untracked = function untracked (repo, cb) {
  status(repo, function (err, result) {
    if (err) return cb(err)
    cb(null, result.untracked)
  })
}

exports.dirty = function dirty (repo, cb) {
  status(repo, function (err, result) {
    if (err) return cb(err)
    cb(null, result.dirty)
  })
}

exports.branch = function branch (repo, cb) {
  exec('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb() // most likely the git repo doesn't have any commits yet
    cb(null, stdout.trim())
  })
}

exports.ahead = function ahead (repo, cb) {
  exec('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(null, NaN) // depending on the state of the git repo, the command might return non-0 exit code
    stdout = stdout.trim()
    cb(null, !stdout ? 0 : parseInt(stdout.split(EOL).length, 10))
  })
}

function status (repo, cb) {
  exec('git status -s', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var status = { dirty: 0, untracked: 0 }
    stdout.trim().split(EOL).filter(truthy).forEach(function (file) {
      if (file.substr(0, 2) === '??') status.untracked++
      else status.dirty++
    })
    cb(null, status)
  })
}

function truthy (obj) {
  return !!obj
}

exports.commit = function commit (repo, cb) {
  exec('git rev-parse --short HEAD', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var commitHash = stdout.trim()
    cb(null, commitHash)
  })
}

exports.stashes = function stashes (repo, cb) {
  exec('git stash list', { cwd: repo }, function (err, stdout, stderr) {
    if (err) return cb(err)
    var stashes = stdout.trim().split(EOL).filter(truthy)
    cb(null, stashes.length)
  })
}

//* SYNC methods *//
exports.untrackedSync = function untrackedSync (repo) {
  return statusSync(repo).untracked
}

exports.dirtySync = function dirtySync (repo) {
  return statusSync(repo).dirty
}

exports.branchSync = function branchSync (repo) {
  try {
    var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-parse --abbrev-ref HEAD', { cwd: repo }).toString()
    return stdout.trim()
  } catch (err) {
    return null // most likely the git repo doesn't have any commits yet
  }
}

exports.aheadSync = function aheadSync (repo) {
  try {
    var stdout = execSync('git show-ref >' + nullPath + ' 2>&1 && git rev-list HEAD --not --remotes', { cwd: repo }).toString()
    stdout = stdout.trim()
    return !stdout ? 0 : parseInt(stdout.split(EOL).length, 10)
  } catch (err) {
    return NaN
  }
}

// Throws error
var statusSync = function statusSync (repo) {
  var stdout = execSync('git status -s', { cwd: repo }).toString()
  var status = { dirty: 0, untracked: 0 }
  stdout.trim().split(EOL).filter(truthy).forEach(function (file) {
    if (file.substr(0, 2) === '??') status.untracked++
    else status.dirty++
  })
  return status
}

// Throws error
exports.commitSync = function commitSync (repo) {
  var stdout = execSync('git rev-parse --short HEAD', { cwd: repo }).toString()
  var commitHash = stdout.trim()
  return commitHash
}

// Throws error
exports.stashesSync = function stashesSync (repo) {
  var stdout = execSync('git stash list', { cwd: repo }).toString()
  var stashes = stdout.trim().split(EOL).filter(truthy)
  return stashes.length
}
<|endoftext|>


<commit_before>'use strict';

var Cleaner  = require('clean-css');
var defaultCleaner = new Cleaner();

var versions = {};

exports.name = 'remarkable';
exports.outputFormat = 'html';
exports.render = function (str, options) {
  var cleaner;
  if (!options ||
      (typeof options === 'object' && Object.keys(options).length === 0)) {
    cleaner = defaultCleaner;
  } else {
    cleaner = new Cleaner(options);
  }
  return cleaner.minify(str).styles;
};
<commit_msg>fix(~): Update the name and outputFormat<commit_after>'use strict';

var Cleaner  = require('clean-css');
var defaultCleaner = new Cleaner();

exports.name = 'clean-css';
exports.outputFormat = 'css';
exports.render = function (str, options) {
  var cleaner;
  if (!options ||
      (typeof options === 'object' && Object.keys(options).length === 0)) {
    cleaner = defaultCleaner;
  } else {
    cleaner = new Cleaner(options);
  }
  return cleaner.minify(str).styles;
};
<|endoftext|>


<commit_before>var fs = require('fs')
var path = require('path')
var camelcase = require('camelcase')
var pascalcase = require('uppercamelcase')

module.exports = load

function load(dir, options) {
    var modules = {}

    options = options || {}
    if (typeof options === 'function') {
        options = {init: options}
    }
    switch (options.naming) {
        case 'camel':
            options.naming = camelcase
            break
        case 'pascal':
            options.naming = pascalcase
            break
        default:
            options.naming = identify
            break
    }
    options = merge(options, {
        lazy: true,
        init: identify,
    })

    fs.readdirSync(dir).forEach(function(filename) {
        // filter index and dotfiles
        var stat = fs.statSync(path.join(dir, filename))
        var isModule = stat.isFile() && path.extname(filename) === '.js' &&
            filename !== 'index.js' && filename[0] !== '.'
        if (stat.isDirectory() || isModule) {
            var moduleName = path.basename(filename, path.extname(filename))
            var modulePath = path.join(dir, moduleName)
            var exportName = options.naming(moduleName)
            // lazy load
            if (options.lazy) {
                Object.defineProperty(modules, exportName, {
                    get: function() {
                        return options.init(require(modulePath))
                    }
                })
            } else {
                modules[exportName] = options.init(require(modulePath))
            }
        }
    })

    return modules
}

function merge(obj, src) {
    for (var key in src) {
        if (src.hasOwnProperty(key) && obj[key] === undefined) {
            obj[key] = src[key]
        }
    }
    return obj
}

function identify(value) {
    return value
}
<commit_msg>feat: support recursive require<commit_after>var fs = require('fs')
var path = require('path')
var camelcase = require('camelcase')
var pascalcase = require('uppercamelcase')

module.exports = load

function load(dir, options) {
    options = options || {}
    if (typeof options === 'function') {
        options = {init: options}
    }
    switch (options.naming) {
        case 'camel':
            options.naming = camelcase
            break
        case 'pascal':
            options.naming = pascalcase
            break
        default:
            options.naming = identify
            break
    }
    options = merge(options, {
        lazy: true,
        init: identify,
    })

    var modules = options.exports || {}
    fs.readdirSync(dir).forEach(function(filename) {
        // filter index and dotfiles
        var stat = fs.statSync(path.join(dir, filename))
        var isModule = stat.isFile() && path.extname(filename) === '.js' &&
            filename !== 'index.js' && filename[0] !== '.'
        if (stat.isDirectory() || isModule) {
            var moduleName = path.basename(filename, path.extname(filename))
            var modulePath = path.join(dir, moduleName)
            var exportName = options.naming(moduleName)
            // lazy load
            if (options.lazy) {
                Object.defineProperty(modules, exportName, {
                    get: function() {
                        return options.init(require(modulePath))
                    }
                })
            } else {
                modules[exportName] = options.init(require(modulePath))
            }
        }
    })

    return modules
}

function merge(obj, src) {
    for (var key in src) {
        if (src.hasOwnProperty(key) && obj[key] === undefined) {
            obj[key] = src[key]
        }
    }
    return obj
}

function identify(value) {
    return value
}
<|endoftext|>


<commit_before>'use strict';
// var util = require('util');
var zag_agent = require('zag-agent');
var xtend = require('xtend');

var default_key_rules = {
	'statsd.': 'statsd>'
};
var default_config = {
	daemons: ['127.0.0.1:8876']
};

function ZagBackend(startupTime, config, emitter) {
	var self = this;
	this.stats = {
		last_flush: startupTime,
		last_exception: startupTime
	};
	this.config = xtend(default_config, config.zag || {});
	this.key_rules = xtend(default_key_rules, this.config.key_rules);
	this.key_map = {};

	this.agent = zag_agent(this.config.daemons);

	emitter.on('flush', function(timestamp, metrics) { self.flush(timestamp, metrics); });
	emitter.on('status', function(callback) { self.status(callback); });
}

ZagBackend.prototype.map_key = function map_key(key) {
	var self = this;
	var zag_key = statsd_key;
	if (self.key_map[statsd_key]) {
		return self.key_map[statsd_key];
	}
	Object.keys(self.key_rules).forEach(function (rule) {
		zag_key = zag_key.replace(rule, self.key_rules[rule]);
	});
	self.key_map[statsd_key] = zag_key;
	return zag_key;
};

ZagBackend.prototype.flush = function (timestamp, metrics) {
	var self = this;
	this.stats.last_flush = timestamp;

	// Counters
	Object.keys(metrics.counters).forEach(function(key) {
		var val = metrics.counters[key];
		if (val !== 0) {
			self.agent.counter(self.map_key(key), val);
		}
	});

	// Gauges
	Object.keys(metrics.gauges).forEach(function(key) {
		var val = metrics.gauges[key];
		self.agent.histogram(self.map_key(key+'.gauge'), val);
	});

	// Timers
	Object.keys(metrics.timers).forEach(function(key) {
		metrics.timers[key].forEach(function (val) {
			self.agent.histogram(self.map_key(key), val);
		});
	});

	// Sets
	Object.keys(metrics.sets).forEach(function(key) {
		var set = metrics.sets[key];
		set.values().forEach(function (val) {
			var value_key = key + '.set|' + val;
			self.agent.counter(self.map_key(value_key), 1);
		});
	});
};

ZagBackend.prototype.status = function (callback) {
	this.stats.forEach(function(key) {
		callback(null, 'console', key, this[key]);
	}, this);
};

exports.init = function(startupTime, config, events) {
	var instance = new ZagBackend(startupTime, config, events);
	return instance && true;
};
<commit_msg>Debug mode logging<commit_after>'use strict';
var util = require('util');
var zag_agent = require('zag-agent');
var xtend = require('xtend');

var default_key_rules = {
	'statsd.': 'statsd>'
};
var default_config = {
	daemons: ['127.0.0.1:8876']
};

function ZagBackend(startupTime, config, emitter) {
	var self = this;
	this.stats = {
		last_flush: startupTime,
		last_exception: startupTime
	};
	this.config = xtend(default_config, config.zag || {});
	this.config.debug = config.debug;
	this.key_rules = xtend(default_key_rules, this.config.key_rules);
	this.key_map = {};

	this.agent = zag_agent(this.config.daemons);

	// TODO: Have a config option so se parse 'packet' raw data instead of 'flush' aggregated data.
	emitter.on('flush', function(timestamp, metrics) { self.flush(timestamp, metrics); });
	emitter.on('status', function(callback) { self.status(callback); });
}

ZagBackend.prototype.log = function debug(msg) {
	if (this.config.debug) {
		util.log('[ZagBackend] ' + msg);
	}
};

ZagBackend.prototype.map_key = function map_key(statsd_key) {
	var self = this;
	var zag_key = statsd_key;
	if (self.key_map[statsd_key]) {
		return self.key_map[statsd_key];
	}
	Object.keys(self.key_rules).forEach(function (rule) {
		zag_key = zag_key.replace(rule, self.key_rules[rule]);
	});
	self.log.debug('Rewriting "'+statsd_key+'" as "'+zag_key+'" and caching');
	self.key_map[statsd_key] = zag_key;
	return zag_key;
};

ZagBackend.prototype.flush = function (timestamp, metrics) {
	var self = this;
	this.stats.last_flush = timestamp;

	// Counters
	Object.keys(metrics.counters).forEach(function(key) {
		var val = metrics.counters[key];
		if (val !== 0) {
			self.agent.counter(self.map_key(key), val);
		}
	});

	// Gauges
	Object.keys(metrics.gauges).forEach(function(key) {
		var val = metrics.gauges[key];
		self.agent.histogram(self.map_key(key+'.gauge'), val);
	});

	// Timers
	Object.keys(metrics.timers).forEach(function(key) {
		metrics.timers[key].forEach(function (val) {
			self.agent.histogram(self.map_key(key), val);
		});
	});

	// Sets
	Object.keys(metrics.sets).forEach(function(key) {
		var set = metrics.sets[key];
		set.values().forEach(function (val) {
			var value_key = key + '.set|' + val;
			self.agent.counter(self.map_key(value_key), 1);
		});
	});
};

ZagBackend.prototype.status = function (callback) {
	this.stats.forEach(function(key) {
		callback(null, 'console', key, this[key]);
	}, this);
};

exports.init = function(startupTime, config, events) {
	var instance = new ZagBackend(startupTime, config, events);
	return instance && true;
};
<|endoftext|>


<commit_before>var express = require('express');
var url = require('url');
var app = express();
var setUp = require('./appset');
setUp(app, 'prod');
var proxy = require('express-http-proxy');
app.use('/my-project/mlife-guide-re/', proxy('www.mlife.top', {
    forwardPath: function(req, res) {
        return '/my-project/mlife-guide-re/' + url.parse(req.url).path;
    }
}));
app.listen(process.env.PORT || 5050);<commit_msg>ceshi<commit_after>var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World')
})

app.listen(process.env.PORT || 5050)
<|endoftext|>


<commit_before>// datasheet: http://www.nxp.com/documents/short_data_sheet/PN532_C1_SDS.pdf
// user manual: http://www.nxp.com/documents/user_manual/141520.pdf

var tm = process.binding('tm');
var tessel = require('tessel');
var events = require('events');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var PN532_COMMAND_INLISTPASSIVETARGET = 0x4A;
var PN532_COMMAND_GETFIRMWAREVERSION = 0x02;
var PN532_COMMAND_SAMCONFIGURATION = 0x14;
var PN532_I2C_READY = 0x01;
var PN532_PREAMBLE = 0x00;
var PN532_STARTCODE1 = 0x00;
var PN532_STARTCODE2 = 0xFF;
var PN532_POSTAMBLE = 0x00;
var PN532_I2C_ADDRESS = 0x48 >> 1;
var PN532_I2C_READBIT = 0x01;
var PN532_I2C_BUSY = 0x00;
var PN532_I2C_READY = 0x01;
var PN532_I2C_READYTIMEOUT = 20;
var PN532_HOSTTOPN532 = 0xD4;
var PN532_MIFARE_ISO14443A = 0x00;
var WAKE_UP_TIME = 100;

var led1 = tessel.led(1).output().low();
var led2 = tessel.led(2).output().low();

var packetBuffer = [];

function RFID (hardware, next) {
  var self = this;

  self.hardware = hardware;
  self.irq = hardware.gpio(3);
  self.nRST = hardware.gpio(2);
  self.numListeners = 0;
  self.listening = false;

  self.nRST.output();
  self.nRST.low(); // toggle reset every time we initialize

  self.i2c = new hardware.I2C(PN532_I2C_ADDRESS);
  self.i2c.initialize();

  self.irq.input();
  setTimeout(function () {
    self.nRST.high();
    self.getFirmwareVersion(function (version) {
      if (!version) {
        throw "Cannot connect to pn532.";
      } else {
        self.emit('connected', version);
      }
    });
  }, WAKE_UP_TIME);

  // If we get a new listener
  self.on('newListener', function(event) {
    if (event == "data") {
      // Add to the number of things listening
      self.numListeners += 1;
      // If we're not already listening
      if (!self.listening) {
        // Start listening
        self.setListening();
      }
    }
  });

  // If we remove a listener
  self.on('removeListener', function(event) {
    if (event == "data") {
      // Remove from the number of things listening
      self.numListeners -= 1;
      // Because we listen in a while loop, if this.listening goes to 0, we'll stop listening automatically
      if (self.numListeners < 1) {
        self.listening = false;
      }
    }
  });

  self.on('removeAllListeners', function(event) {
    self.numListeners = 0;
    self.listening = false;
  });
}

util.inherits(RFID, events.EventEmitter);

RFID.prototype.initialize = function (hardware, next) {
  this.getFirmwareVersion(function(firmware){
    next(firmware);
  });
  // TODO: Do something with the bank to determine the IRQ and RESET lines
  // Once Reset actually works...
}

/**************************************************************************/
/*!
    @brief  Checks the firmware version of the PN5xx chip

    @returns  The chip's firmware version and ID
*/
/**************************************************************************/
RFID.prototype.getFirmwareVersion = function (next) {
  var self = this;
  var response;

  // console.log("Starting firmware check...");

  var commandBuffer = [PN532_COMMAND_GETFIRMWAREVERSION];

  self.sendCommandCheckAck(commandBuffer, 1, function(ack){
    if (!ack){
      return next(0);
    }

    self.wirereaddata(12, function (firmware){
      // console.log("FIRMWARE: ", firmware);
      // console.log("cleaned firmware: ", response);
      self.SAMConfig(next);
    });
  });

  // read data packet

  // check some basic stuff
 //  if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
 //    #ifdef PN532DEBUG
 //    Serial.println("Firmware doesn't match!");
  // #endif
 //    return 0;
 //  }

  // response = firmware[7];
  // response <<= 8;
  // response |= firmware[8];
  // response <<= 8;
  // response |= firmware[9];
  // response <<= 8;
  // response |= firmware[10];

  // console.log("cleaned firmware: ", response);
  // return response;
}

/**************************************************************************/
/*!
    Waits for an ISO14443A target to enter the field

    @param  cardBaudRate  Baud rate of the card
    @param  uid           Pointer to the array that will be populated
                          with the card's UID (up to 7 bytes)
    @param  uidLength     Pointer to the variable that will hold the
                          length of the card's UID.

    @returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
RFID.prototype.readPassiveTargetID = function (cardbaudrate, next) {
  var self = this
  var commandBuffer = [
    PN532_COMMAND_INLISTPASSIVETARGET,
    1,
    cardbaudrate
  ];

  self.sendCommandCheckAck(commandBuffer, 3, function(ack){
    if (!ack) {
      return next(0x0);
    }
     // Wait for a card to enter the field
    var status = PN532_I2C_BUSY;
    var waitLoop = setInterval(function(){
      if (self.wirereadstatus() == PN532_I2C_READY){
        clearInterval(waitLoop);

        // check some basic stuff
        /* ISO14443A card response should be in the following format:

          byte            Description
          -------------   ------------------------------------------
          b0..6           Frame header and preamble
          b7              Tags Found
          b8              Tag Number (only one used in this example)
          b9..10          SENS_RES
          b11             SEL_RES
          b12             NFCID Length
          b13..NFCIDLen   NFCID                                      */

        // read data packet
        self.wirereaddata(20, function(response){
          // console.log("got response", response);
          // if (response[7] != 1){
            // return next(0x0);
          // }

          var uid = [];
          for (var i=0; i < response[12]; i++)
          {
            uid[i] = response[13+i];
          }
          next(uid);
        });
      }
    },10);
  });
}

/**************************************************************************/
/*!
    @brief  Configures the SAM (Secure Access Module)
*/
/**************************************************************************/
RFID.prototype.SAMConfig = function (next) {
  var self = this;
  var commandBuffer = [
    PN532_COMMAND_SAMCONFIGURATION,
    0x01,
    0x14,
    0x01
  ];

  self.sendCommandCheckAck(commandBuffer, 4, function(ack){
    if (!ack){
      return next(false);
    }
    // read data packet
    self.wirereaddata(8, function(response){
      next(response);
      led1.high();
    });
  });
}

/**************************************************************************/
/*!
    @brief  Sends a command and waits a specified period for the ACK

    @param  cmd       Pointer to the command buffer
    @param  cmdlen    The size of the command in bytes
    @param  timeout   timeout before giving up

    @returns  1 if everything is OK, 0 if timeout occured before an
              ACK was recieved
*/
/**************************************************************************/
// default timeout of one second
RFID.prototype.sendCommandCheckAck = function (cmd, cmdlen, next) {
  var timer = 0;
  var timeout = 500;
  // write the command
  this.wiresendcommand(cmd, cmdlen);

  // Wait for chip to say its ready!
  while (this.wirereadstatus() != PN532_I2C_READY) {
    if (timeout) {
      // console.log('timeout')
      timer+=10;
      if (timer > timeout) {
        // console.log("about to return false")
        return false;
      }
    }
    // console.log("sleeping");
    tessel.sleep(10);
  }

  // read acknowledgement
  this.readackframe(function(ackbuff){
    if (!ackbuff){
      next(false);
    }
    next(true);
  });
}

/**************************************************************************/
/*!
    @brief  Writes a command to the PN532, automatically inserting the
            preamble and required frame details (checksum, len, etc.)

    @param  cmd       Pointer to the command buffer
*/
/**************************************************************************/
RFID.prototype.wiresendcommand = function (cmd, cmdlen) {
  var checksum;

  cmdlen++;
  tessel.sleep(2);     // or whatever the delay is for waking up the board

  // I2C START
  // checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; // 0 + 0 + FF
  checksum = -1;

  var sendCommand = [PN532_PREAMBLE,
    PN532_PREAMBLE,
    PN532_STARTCODE2,
    cmdlen,
    (255 - cmdlen) + 1,
    PN532_HOSTTOPN532];

  checksum += PN532_HOSTTOPN532;

  for (var i=0; i<cmdlen-1; i++) {
    sendCommand.push(cmd[i]);
    checksum += cmd[i];
  }
  checksum = checksum % 256;
  sendCommand.push((255 - checksum));
  sendCommand.push(PN532_POSTAMBLE);
  this.write_register(sendCommand);
}

/**************************************************************************/
/*!
    @brief  Tries to read the PN532 ACK frame (not to be confused with
          the I2C ACK signal)
*/
/**************************************************************************/
RFID.prototype.readackframe = function (next) {

   this.wirereaddata(6, function(ackbuff){
    next(ackbuff);
   });
}

RFID.prototype.wirereadstatus = function () {
  var x = this.irq.read();

  // console.log("IRQ", x);

  if (x == 1)
    return PN532_I2C_BUSY;
  else
    return PN532_I2C_READY;
}

/**************************************************************************/
/*!
    @brief  Reads n bytes of data from the PN532 via I2C

    @param  buff      Pointer to the buffer where data will be written
    @param  n         Number of bytes to be read
*/
/**************************************************************************/
RFID.prototype.wirereaddata = function (numBytes, next) {

  tessel.sleep(2);

  this.read_registers([], numBytes+2, function(err, response){
    next(response);
  });
}

/**************************************************************************/
/*!
    @brief  I2C Helper Functions Below
*/
/**************************************************************************/
RFID.prototype.read_registers = function (dataToWrite, bytesToRead, next)
{

  this.i2c.transfer(dataToWrite, bytesToRead, function (err, data) {
    next(err, data);
  });
}

// Write a single byte to the register.
RFID.prototype.write_register  = function (dataToWrite)
{
  return this.i2c.send(dataToWrite);
}

// Write a single byte to the register.
RFID.prototype.write_one_register = function (dataToWrite)
{
  return this.i2c.send([dataToWrite]);
}

RFID.prototype.setListening = function () {
  var self = this;
  self.listening = true;
  // Loop until nothing is listening
  self.listeningLoop = setInterval (function () {
    if (self.numListeners) {
      self.readPassiveTargetID(PN532_MIFARE_ISO14443A, function(uid){
        led2.high();
        self.emit('data', uid);
        led2.low();
      });
    } else {
      clearInterval(listeningLoop);
    }
  }, self.pollFrequency);
}

exports.RFID = RFID;
exports.connect = function (hardware, portBank) {
  return new RFID(hardware, portBank);
}<commit_msg>working on replacing sleeps with setIntervals, taking a break to look for why it reads so fast<commit_after>// datasheet: http://www.nxp.com/documents/short_data_sheet/PN532_C1_SDS.pdf
// user manual: http://www.nxp.com/documents/user_manual/141520.pdf

var tm = process.binding('tm');
var tessel = require('tessel');
var events = require('events');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var PN532_COMMAND_INLISTPASSIVETARGET = 0x4A;
var PN532_COMMAND_GETFIRMWAREVERSION = 0x02;
var PN532_COMMAND_SAMCONFIGURATION = 0x14;
var PN532_I2C_READY = 0x01;
var PN532_PREAMBLE = 0x00;
var PN532_STARTCODE1 = 0x00;
var PN532_STARTCODE2 = 0xFF;
var PN532_POSTAMBLE = 0x00;
var PN532_I2C_ADDRESS = 0x48 >> 1;
var PN532_I2C_READBIT = 0x01;
var PN532_I2C_BUSY = 0x00;
var PN532_I2C_READY = 0x01;
var PN532_I2C_READYTIMEOUT = 20;
var PN532_HOSTTOPN532 = 0xD4;
var PN532_MIFARE_ISO14443A = 0x00;
var WAKE_UP_TIME = 100;

var led1 = tessel.led(1).output().low();
var led2 = tessel.led(2).output().low();

var packetBuffer = [];

function RFID (hardware, next) {
  var self = this;

  self.hardware = hardware;
  self.irq = hardware.gpio(3);
  self.nRST = hardware.gpio(2);
  self.numListeners = 0;
  self.listening = false;

  self.nRST.output();
  self.nRST.low(); // toggle reset every time we initialize

  self.i2c = new hardware.I2C(PN532_I2C_ADDRESS);
  self.i2c.initialize();

  self.irq.input();
  setTimeout(function () {
    self.nRST.high();
    self.getFirmwareVersion(function (version) {
      if (!version) {
        throw "Cannot connect to pn532.";
      } else {
        self.emit('connected', version);
      }
    });
  }, WAKE_UP_TIME);

  // If we get a new listener
  self.on('newListener', function(event) {
    if (event == "data") {
      // Add to the number of things listening
      self.numListeners += 1;
      // If we're not already listening
      if (!self.listening) {
        // Start listening
        self.setListening();
      }
    }
  });

  // If we remove a listener
  self.on('removeListener', function(event) {
    if (event == "data") {
      // Remove from the number of things listening
      self.numListeners -= 1;
      // Because we listen in a while loop, if this.listening goes to 0, we'll stop listening automatically
      if (self.numListeners < 1) {
        self.listening = false;
      }
    }
  });

  self.on('removeAllListeners', function(event) {
    self.numListeners = 0;
    self.listening = false;
  });
}

util.inherits(RFID, events.EventEmitter);

RFID.prototype.initialize = function (hardware, next) {
  this.getFirmwareVersion(function(firmware){
    next(firmware);
  });
  // TODO: Do something with the bank to determine the IRQ and RESET lines
  // Once Reset actually works...
}

/**************************************************************************/
/*!
    @brief  Checks the firmware version of the PN5xx chip

    @returns  The chip's firmware version and ID
*/
/**************************************************************************/
RFID.prototype.getFirmwareVersion = function (next) {
  var self = this;
  var response;

  // console.log("Starting firmware check...");

  var commandBuffer = [PN532_COMMAND_GETFIRMWAREVERSION];

  self.sendCommandCheckAck(commandBuffer, 1, function(ack){
    if (!ack){
      return next(0);
    }

    self.wirereaddata(12, function (firmware){
      // console.log("FIRMWARE: ", firmware);
      // console.log("cleaned firmware: ", response);
      self.SAMConfig(next);
    });
  });

  // read data packet

  // check some basic stuff
 //  if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6)) {
 //    #ifdef PN532DEBUG
 //    Serial.println("Firmware doesn't match!");
  // #endif
 //    return 0;
 //  }

  // response = firmware[7];
  // response <<= 8;
  // response |= firmware[8];
  // response <<= 8;
  // response |= firmware[9];
  // response <<= 8;
  // response |= firmware[10];

  // console.log("cleaned firmware: ", response);
  // return response;
}

/**************************************************************************/
/*!
    Waits for an ISO14443A target to enter the field

    @param  cardBaudRate  Baud rate of the card
    @param  uid           Pointer to the array that will be populated
                          with the card's UID (up to 7 bytes)
    @param  uidLength     Pointer to the variable that will hold the
                          length of the card's UID.

    @returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
RFID.prototype.readPassiveTargetID = function (cardbaudrate, next) {
  var self = this
  var commandBuffer = [
    PN532_COMMAND_INLISTPASSIVETARGET,
    1,
    cardbaudrate
  ];

  self.sendCommandCheckAck(commandBuffer, 3, function(ack){
    if (!ack) {
      return next(0x0);
    }
     // Wait for a card to enter the field
    var status = PN532_I2C_BUSY;
    var waitLoop = setInterval(function(){
      if (self.wirereadstatus() == PN532_I2C_READY){
        clearInterval(waitLoop);

        // check some basic stuff
        /* ISO14443A card response should be in the following format:

          byte            Description
          -------------   ------------------------------------------
          b0..6           Frame header and preamble
          b7              Tags Found
          b8              Tag Number (only one used in this example)
          b9..10          SENS_RES
          b11             SEL_RES
          b12             NFCID Length
          b13..NFCIDLen   NFCID                                      */

        // read data packet
        self.wirereaddata(20, function(response){
          // console.log("got response", response);
          // if (response[7] != 1){
            // return next(0x0);
          // }

          var uid = [];
          for (var i=0; i < response[12]; i++)
          {
            uid[i] = response[13+i];
          }
          next(uid);
        });
      }
    },10);
  });
}

/**************************************************************************/
/*!
    @brief  Configures the SAM (Secure Access Module)
*/
/**************************************************************************/
RFID.prototype.SAMConfig = function (next) {
  var self = this;
  var commandBuffer = [
    PN532_COMMAND_SAMCONFIGURATION,
    0x01,
    0x14,
    0x01
  ];

  self.sendCommandCheckAck(commandBuffer, 4, function(ack){
    if (!ack){
      return next(false);
    }
    // read data packet
    self.wirereaddata(8, function(response){
      next(response);
      led1.high();
    });
  });
}

/**************************************************************************/
/*!
    @brief  Sends a command and waits a specified period for the ACK

    @param  cmd       Pointer to the command buffer
    @param  cmdlen    The size of the command in bytes
    @param  timeout   timeout before giving up

    @returns  1 if everything is OK, 0 if timeout occured before an
              ACK was recieved
*/
/**************************************************************************/
// default timeout of one second
RFID.prototype.sendCommandCheckAck = function (cmd, cmdlen, next) {
  var timer = 0;
  var timeout = 500;
  var self = this;
  // write the command
  self.wiresendcommand(cmd, cmdlen);

  // // Wait for chip to say it's ready!
  // var waitLoop = setInterval(function(){
  //   if (self.wirereadstatus() == PN532_I2C_READY) {
  //     // Success- ready
  //     clearInterval(waitLoop);
  //     // read acknowledgement
  //     self.readackframe(function(ackbuff){
  //       if (!ackbuff){
  //         next(false);
  //       }
  //       next(true);
  //     });
  //   } else if (timer > timeout) {
  //     // Failure- timed out
  //     clearInterval(waitLoop);
  //     return false;
  //   } else {
  //     // Increase timeout timer
  //     timer +=10;
  //   }
  // }, 10);

  // Wait for chip to say it's ready!
  while (self.wirereadstatus() != PN532_I2C_READY) {
    if (timeout) {
      // console.log('timeout')
      timer+=10;
      if (timer > timeout) {
        // console.log("about to return false")
        return false;
      }
    }
    // console.log("sleeping");
    tessel.sleep(10);
  }

  // read acknowledgement
  self.readackframe(function(ackbuff){
    if (!ackbuff){
      next(false);
    }
    next(true);
  });
}

/**************************************************************************/
/*!
    @brief  Writes a command to the PN532, automatically inserting the
            preamble and required frame details (checksum, len, etc.)

    @param  cmd       Pointer to the command buffer
*/
/**************************************************************************/
RFID.prototype.wiresendcommand = function (cmd, cmdlen) {
  var checksum;

  cmdlen++;
  tessel.sleep(2);     // or whatever the delay is for waking up the board

  // I2C START
  // checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; // 0 + 0 + FF
  checksum = -1;

  var sendCommand = [PN532_PREAMBLE,
    PN532_PREAMBLE,
    PN532_STARTCODE2,
    cmdlen,
    (255 - cmdlen) + 1,
    PN532_HOSTTOPN532];

  checksum += PN532_HOSTTOPN532;

  for (var i=0; i<cmdlen-1; i++) {
    sendCommand.push(cmd[i]);
    checksum += cmd[i];
  }
  checksum = checksum % 256;
  sendCommand.push((255 - checksum));
  sendCommand.push(PN532_POSTAMBLE);
  this.write_register(sendCommand);
}

/**************************************************************************/
/*!
    @brief  Tries to read the PN532 ACK frame (not to be confused with
          the I2C ACK signal)
*/
/**************************************************************************/
RFID.prototype.readackframe = function (next) {

   this.wirereaddata(6, function(ackbuff){
    next(ackbuff);
   });
}

RFID.prototype.wirereadstatus = function () {
  var x = this.irq.read();

  // console.log("IRQ", x);

  if (x == 1)
    return PN532_I2C_BUSY;
  else
    return PN532_I2C_READY;
}

/**************************************************************************/
/*!
    @brief  Reads n bytes of data from the PN532 via I2C

    @param  buff      Pointer to the buffer where data will be written
    @param  n         Number of bytes to be read
*/
/**************************************************************************/
RFID.prototype.wirereaddata = function (numBytes, next) {

  tessel.sleep(2);

  this.read_registers([], numBytes+2, function(err, response){
    next(response);
  });
}

/**************************************************************************/
/*!
    @brief  I2C Helper Functions Below
*/
/**************************************************************************/
RFID.prototype.read_registers = function (dataToWrite, bytesToRead, next)
{

  this.i2c.transfer(dataToWrite, bytesToRead, function (err, data) {
    next(err, data);
  });
}

// Write a single byte to the register.
RFID.prototype.write_register  = function (dataToWrite)
{
  return this.i2c.send(dataToWrite);
}

// Write a single byte to the register.
RFID.prototype.write_one_register = function (dataToWrite)
{
  return this.i2c.send([dataToWrite]);
}

RFID.prototype.setListening = function () {
  var self = this;
  self.listening = true;
  // Loop until nothing is listening
  self.listeningLoop = setInterval (function () {
    if (self.numListeners) {
      self.readPassiveTargetID(PN532_MIFARE_ISO14443A, function(uid){
        led2.high();
        self.emit('data', uid);
        led2.low();
      });
    } else {
      clearInterval(listeningLoop);
    }
  }, self.pollFrequency);
}

exports.RFID = RFID;
exports.connect = function (hardware, portBank) {
  return new RFID(hardware, portBank);
}<|endoftext|>