<commit_before>const Discord = require('discord.js'),
		cutie = new Discord.Client(),
		token = require('../config')
let	queue = [],
		vc = null,
		pf = 'q!',
		singing = false

cutie.on('ready', () => {
	console.log(`${cutie.user.username} is ready...`)
	vc = cutie.channels.get('275364590857093120')
	if(vc) console.log(`Managing ${vc.name}...`)
})

cutie.on('message', (message) => {
	let rest = message.content
	//if message starts with prefix and sent through a guild server
	if(rest.startsWith(pf) && message.channel.type === 'text') {
		rest = rest.substring(pf.length).trim()
		//help command
		if(rest.startsWith('help')) {
			let cmds = `**sing** - To queue up for singing\n\
				**queue** - To see the queue list\n\
				**help** - What are you even doing...\n`
			//if managing role
			if(cRoles(message))
				cmds += `**skip [index]** - To skip the specified position\n`
					//**start** - To let the singer start\n\
					//**done** - After the singer is done to unmute all\n`
			else
				cmds += `**skip** - To skip your turn if queued`
			message.channel.sendMessage({embed: {
				title: `Available commands - prefix is __${pf}__`,
				description: cmds,
				color: 0x00ff00
			}})
		//sing command
		} else if(rest.startsWith('sing')) {
			//if member in voice channel, voice channel is kaoke and managing vc
			if(message.member.voiceChannel && message.member.voiceChannel.id === vc.id && vc != null) {
				//if alreaady queued, NO
				if(queue.includes(message.member)) return
				queue.push(message.member)
				message.reply(`you are in position #\`${queue.length}\``)
			}
		//queue command
		} else if(rest.startsWith('queue')) {
			//if there's a queue
			if(queue.length > 0) {
				let msg = (singing ? `Singing now is ` : `Next singer is `) + `\`${queue[0].displayName}\`\n`
				for(let i = 1; i < queue.length; i++)
					msg += `${i}. \`${queue[i].displayName}\`\n`
				message.channel.send(msg)
			} else
				message.reply('there\'s no queue right now, sorry :cry:')
		//start command
		/*} else if(rest.startsWith('start'))
			//if has managing perms
			if(cRoles(message))
				sQueue(message)		//call start function
			else return
		//done command
		else if(rest.startsWith('done'))
			//if has managing perms
			if(cRoles(message))
				nQueue(message)		//call done function
			else return
		//manage command
		else if(rest.startsWith('manage'))
			//if has managing perms
			if(cRoles(message)) {
				vc = message.member.voiceChannel
				message.reply(`started managing \`${vc.name}\``)
			} else return*/
		//skip command
		} else if(rest.startsWith('skip'))
			//if has managing perms
			if(cRoles) {
				let pams = rest.substring(4)
				uQueue(message, pams)		//call skip function
			} else return
	}
})

//voice state update, if user leaves or joins vc
/*cutie.on('voiceStateUpdate', (o, n) => {
	//if singing and member is not singer
	if(singing && n.id != queue[0].id)
		//if joining voice channel and voice channel is kaoke
		if(n.voiceChannel && n.voiceChannel.id === vc.id)
				n.setMute(true)
		//else if left chann is kaoke
		else if(o.voiceChannel && o.voiceChannel.id === vc.id)
			//
			if(n.voiceChannel ? n.voiceChannel.id != vc.id : true)
				//if(n.roles.exists('name', 'Member Perms'))
				n.setMute(false)
})*/

/*
 * ** Functions **
 */

//singer is done, unmute everyone
function nQueue(m) {
	//if managing vc, there's a queue and singing
		if(vc != null && queue.length > 0 && singing) {
			//vc.overwritePermissions('193643658556211200', {'SPEAK': true})
			//unmute all members in the vc
			for(let i of vc.members)
				//if member is level 2 and over... ?
				//if(i[1].roles.exists('name', 'Member Perms'))
				i[1].setMute(false)
			m.channel.sendMessage(`\`${queue[0].displayName}\` is done... unmuting everyone...\nOk :blush:`)
			queue.shift()
			singing = false
			//if there's queue, next singer in a voice channel then check if different vc, else send warning
			if(queue.length > 0 && (queue[0].voiceChannel ? queue[0].voiceChannel.id != vc.id : true))
				queue[0].sendMessage('You are up next! Please join back to the channel or skip it')
		} else
			m.reply('there\'s currently no one singing right now...')
		return
}

//next person in queue is starting... start muting
function sQueue(m) {
	//if there's a queue and managing a vc
	if(queue.length > 0 && vc != null) {
		//vc.overwritePermissions('193643658556211200', {'SPEAK': false})
		//mute members in the vc
		for(let i of vc.members)
			//if not a bot or the singer, MUTE
			if(i[0] != queue[0].id && !i[1].user.bot)
				i[1].setMute(true)
		//unmute singer
		queue[0].setMute(false)
		m.channel.sendMessage(`Muting members Xd ...\n*Singing now is* ${queue[0].toString()} :microphone:`)
		singing = true
	} else
		m.channel.sendMessage('There\'re no more members in the queue :sweat:')
	return
}

//skip person in queue by self or mod can take out
function uQueue(m, pams) {
	//normal user, skip self
	if(pams.length <1)
		//if singing and singer tries to skip self, NO
		if(singing ? m.author.id != queue[0].id : true)
			//if user is in queue, else NO
			if(queue.includes(m.member)) {
				queue.splice(queue.indexOf(m.member), 1)
				m.reply('you have been unqueued :blush:')
			} else return
		else return
	//managing user, skip position
	else if(cRoles(m)) {
		let x = parseInt(pams, 10)
		//if x is not a number, NO
		if(isNaN(x))
			return
		//x is withing range, if singing and x is 0, NO
		if(x < queue.length && (singing ? x != 0 : true)) {
			let name = queue[x].displayName
			queue.splice(x, 1)
			m.channel.sendMessage(`\`${name}\` has been unqueued from position #\`${x}\` :blush:`)
		}
	}
}

//checks for managing roles
function cRoles(m) {
	return m.member.roles.some(x => x.name === 'Moderator' || x.hasPermission('ADMINISTRATOR') || x.id === '297591992957927424')
}

/*	V1.2.1
 *	work on role restriction											check
 *	work on unqueue, passing turn									check
 *	* work on queue up use bot...									check
 *	fix if queue empty														check
 *	Pending requests...
 *	Check for user in vc													check
 *	Check if queued user is still in vc						check
 */

cutie.login(token)
<commit_msg>Uncomment Managing command<commit_after>const Discord = require('discord.js'),
		cutie = new Discord.Client(),
		token = require('../config')
let	queue = [],
		vc = null,
		pf = 'y!',
		singing = false

cutie.on('ready', () => {
	console.log(`${cutie.user.username} is ready...`)
	vc = cutie.channels.get('275364590857093120')
	if(vc) console.log(`Managing ${vc.name}...`)
})

cutie.on('message', (message) => {
	let rest = message.content
	//if message starts with prefix and sent through a guild server
	if(rest.startsWith(pf) && message.channel.type === 'text') {
		rest = rest.substring(pf.length).trim()
		//help command
		if(rest.startsWith('help')) {
			let cmds = `**sing** - To queue up for singing\n\
				**queue** - To see the queue list\n\
				**help** - What are you even doing...\n`
			//if managing role
			if(cRoles(message))
				cmds += `**skip [index]** - To skip the specified position\n`
					//**start** - To let the singer start\n\
					//**done** - After the singer is done to unmute all\n`
			else
				cmds += `**skip** - To skip your turn if queued`
			message.channel.sendMessage({embed: {
				title: `Available commands - prefix is __${pf}__`,
				description: cmds,
				color: 0x00ff00
			}})
		//sing command
		} else if(rest.startsWith('sing')) {
			//if member in voice channel, voice channel is kaoke and managing vc
			if(message.member.voiceChannel && message.member.voiceChannel.id === vc.id && vc != null) {
				//if alreaady queued, NO
				if(queue.includes(message.member)) return
				queue.push(message.member)
				message.reply(`you are in position #\`${queue.length}\``)
			}
		//queue command
		} else if(rest.startsWith('queue')) {
			//if there's a queue
			if(queue.length > 0) {
				let msg = (singing ? `Singing now is ` : `Next singer is `) + `\`${queue[0].displayName}\`\n`
				for(let i = 1; i < queue.length; i++)
					msg += `${i}. \`${queue[i].displayName}\`\n`
				message.channel.send(msg)
			} else
				message.reply('there\'s no queue right now, sorry :cry:')
		//start command
		/*} else if(rest.startsWith('start'))
			//if has managing perms
			if(cRoles(message))
				sQueue(message)		//call start function
			else return
		//done command
		else if(rest.startsWith('done'))
			//if has managing perms
			if(cRoles(message))
				nQueue(message)		//call done function
			else return
		//manage command*/
		} else if(rest.startsWith('manage'))
			//if has managing perms
			if(cRoles(message)) {
				vc = message.member.voiceChannel
				message.reply(`started managing \`${vc.name}\``)
			} else return
		//skip command
		else if(rest.startsWith('skip'))
			//if has managing perms
			if(cRoles) {
				let pams = rest.substring(4)
				uQueue(message, pams)		//call skip function
			} else return
	}
})

//voice state update, if user leaves or joins vc
/*cutie.on('voiceStateUpdate', (o, n) => {
	//if singing and member is not singer
	if(singing && n.id != queue[0].id)
		//if joining voice channel and voice channel is kaoke
		if(n.voiceChannel && n.voiceChannel.id === vc.id)
				n.setMute(true)
		//else if left chann is kaoke
		else if(o.voiceChannel && o.voiceChannel.id === vc.id)
			//
			if(n.voiceChannel ? n.voiceChannel.id != vc.id : true)
				//if(n.roles.exists('name', 'Member Perms'))
				n.setMute(false)
})*/

/*
 * ** Functions **
 */

//singer is done, unmute everyone
function nQueue(m) {
	//if managing vc, there's a queue and singing
		if(vc != null && queue.length > 0 && singing) {
			//vc.overwritePermissions('193643658556211200', {'SPEAK': true})
			//unmute all members in the vc
			for(let i of vc.members)
				//if member is level 2 and over... ?
				//if(i[1].roles.exists('name', 'Member Perms'))
				i[1].setMute(false)
			m.channel.sendMessage(`\`${queue[0].displayName}\` is done... unmuting everyone...\nOk :blush:`)
			queue.shift()
			singing = false
			//if there's queue, next singer in a voice channel then check if different vc, else send warning
			if(queue.length > 0 && (queue[0].voiceChannel ? queue[0].voiceChannel.id != vc.id : true))
				queue[0].sendMessage('You are up next! Please join back to the channel or skip it')
		} else
			m.reply('there\'s currently no one singing right now...')
		return
}

//next person in queue is starting... start muting
function sQueue(m) {
	//if there's a queue and managing a vc
	if(queue.length > 0 && vc != null) {
		//vc.overwritePermissions('193643658556211200', {'SPEAK': false})
		//mute members in the vc
		for(let i of vc.members)
			//if not a bot or the singer, MUTE
			if(i[0] != queue[0].id && !i[1].user.bot)
				i[1].setMute(true)
		//unmute singer
		queue[0].setMute(false)
		m.channel.sendMessage(`Muting members Xd ...\n*Singing now is* ${queue[0].toString()} :microphone:`)
		singing = true
	} else
		m.channel.sendMessage('There\'re no more members in the queue :sweat:')
	return
}

//skip person in queue by self or mod can take out
function uQueue(m, pams) {
	//normal user, skip self
	if(pams.length <1)
		//if singing and singer tries to skip self, NO
		if(singing ? m.author.id != queue[0].id : true)
			//if user is in queue, else NO
			if(queue.includes(m.member)) {
				queue.splice(queue.indexOf(m.member), 1)
				m.reply('you have been unqueued :blush:')
			} else return
		else return
	//managing user, skip position
	else if(cRoles(m)) {
		let x = parseInt(pams, 10)
		//if x is not a number, NO
		if(isNaN(x))
			return
		//x is withing range, if singing and x is 0, NO
		if(x < queue.length && (singing ? x != 0 : true)) {
			let name = queue[x].displayName
			queue.splice(x, 1)
			m.channel.sendMessage(`\`${name}\` has been unqueued from position #\`${x}\` :blush:`)
		}
	}
}

//checks for managing roles
function cRoles(m) {
	return m.member.roles.some(x => x.name === 'Moderator' || x.hasPermission('ADMINISTRATOR') || x.id === '297591992957927424')
}

/*	V1.2.1
 *	work on role restriction											check
 *	work on unqueue, passing turn									check
 *	* work on queue up use bot...									check
 *	fix if queue empty														check
 *	Pending requests...
 *	Check for user in vc													check
 *	Check if queued user is still in vc						check
 */

cutie.login(token)
<|endoftext|>


<commit_before>// CartoDB SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - OAuth. Must have proper OAuth 1.1 headers. For OAuth 1.1 spec see Google
//
// eg. /api/v1/?sql=SELECT 1 as one (with a load of OAuth headers or URL arguments)
//
// for public (read only) queries:
// - sql only, provided the subdomain exists in CartoDB and the table's sharing options are public
//
// eg. vizzuality.cartodb.com/api/v1/?sql=SELECT * from my_table
//

var express = require('express');
var bodyParser = require('body-parser');
var os = require('os');
var Profiler = require('./stats/profiler-proxy');
var StatsD = require('node-statsd').StatsD;
var _ = require('underscore');
var LRU = require('lru-cache');

var RedisPool = require('redis-mpool');
var UserDatabaseService = require('./services/user_database_service');
var JobPublisher = require('../batch/job_publisher');
var JobQueue = require('../batch/job_queue');
var JobBackend = require('../batch/job_backend');
var JobCanceller = require('../batch/job_canceller');
var JobService = require('../batch/job_service');

var UserDatabaseMetadataService = require('../batch/user_database_metadata_service');

var cors = require('./middlewares/cors');

var GenericController = require('./controllers/generic_controller');
var QueryController = require('./controllers/query_controller');
var JobController = require('./controllers/job_controller');
var CacheStatusController = require('./controllers/cache_status_controller');
var HealthCheckController = require('./controllers/health_check_controller');
var VersionController = require('./controllers/version_controller');

var batchFactory = require('../batch');

process.env.PGAPPNAME = process.env.PGAPPNAME || 'cartodb_sqlapi';

// override Date.toJSON
require('./utils/date_to_json');

// jshint maxcomplexity:12
function App() {

    var app = express();

    var redisConfig = {
        host: global.settings.redis_host,
        port: global.settings.redis_port,
        max: global.settings.redisPool,
        idleTimeoutMillis: global.settings.redisIdleTimeoutMillis,
        reapIntervalMillis: global.settings.redisReapIntervalMillis
    };
    var metadataBackend = require('cartodb-redis')(redisConfig);

    // Set default configuration
    global.settings.db_pubuser = global.settings.db_pubuser || "publicuser";
    global.settings.bufferedRows = global.settings.bufferedRows || 1000;

    var tableCache = LRU({
      // store no more than these many items in the cache
      max: global.settings.tableCacheMax || 8192,
      // consider entries expired after these many milliseconds (10 minutes by default)
      maxAge: global.settings.tableCacheMaxAge || 1000*60*10
    });

    // Size based on https://github.com/CartoDB/cartodb.js/blob/3.15.2/src/geo/layer_definition.js#L72
    var SQL_QUERY_BODY_LOG_MAX_LENGTH = 2000;
    app.getSqlQueryFromRequestBody = function(req) {
        var sqlQuery = req.body && req.body.q;
        if (!sqlQuery) {
            return '';
        }

        if (sqlQuery.length > SQL_QUERY_BODY_LOG_MAX_LENGTH) {
            sqlQuery = sqlQuery.substring(0, SQL_QUERY_BODY_LOG_MAX_LENGTH) + ' [...]';
        }
        return JSON.stringify({q: sqlQuery});
    };

    if ( global.log4js ) {
        var loggerOpts = {
            buffer: true,
            // log4js provides a tokens solution as expess but in does not provide the request/response in the callback.
            // Thus it is not possible to extract relevant information from them.
            // This is a workaround to be able to access request/response.
            format: function(req, res, format) {
                var logFormat = global.settings.log_format ||
                    ':remote-addr :method :req[Host]:url :status :response-time ms -> :res[Content-Type]';

                logFormat = logFormat.replace(/:sql/, app.getSqlQueryFromRequestBody(req));
                return format(logFormat);
            }
        };
        app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level:'info'})));
    }

    // Initialize statsD client if requested
    var statsd_client;
    if ( global.settings.statsd ) {

      // Perform keyword substitution in statsd
      if ( global.settings.statsd.prefix ) {
        var host_token = os.hostname().split('.').reverse().join('.');
        global.settings.statsd.prefix = global.settings.statsd.prefix.replace(/:host/, host_token);
      }

      statsd_client = new StatsD(global.settings.statsd);
      statsd_client.last_error = { msg:'', count:0 };
      statsd_client.socket.on('error', function(err) {
        var last_err = statsd_client.last_error;
        var last_msg = last_err.msg;
        var this_msg = ''+err;
        if ( this_msg !== last_msg ) {
          console.error("statsd client socket error: " + err);
          statsd_client.last_error.count = 1;
          statsd_client.last_error.msg = this_msg;
        } else {
            ++last_err.count;
            if ( ! last_err.interval ) {
              //console.log("Installing interval");
              statsd_client.last_error.interval = setInterval(function() {
                var count = statsd_client.last_error.count;
                if ( count > 1 ) {
                  console.error("last statsd client socket error repeated " + count + " times");
                  statsd_client.last_error.count = 1;
                  //console.log("Clearing interval");
                  clearInterval(statsd_client.last_error.interval);
                  statsd_client.last_error.interval = null;
                }
              }, 1000);
            }
        }
      });
    }

    app.use(cors());

    // Use step-profiler
    app.use(function(req, res, next) {
        var profile = global.settings.useProfiler;
        req.profiler = new Profiler({
            profile: profile,
            statsd_client: statsd_client
        });
        next();
    });

    // Set connection timeout
    if ( global.settings.hasOwnProperty('node_socket_timeout') ) {
      var timeout = parseInt(global.settings.node_socket_timeout);
      app.use(function(req, res, next) {
        req.connection.setTimeout(timeout);
        next();
      });
    }

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.enable('jsonp callback');
    app.set("trust proxy", true);
    app.disable('x-powered-by');
    app.disable('etag');

    // basic routing

    var userDatabaseService = new UserDatabaseService(metadataBackend);

    var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'job-publisher'}));
    var jobPublisher = new JobPublisher(redisPoolPublisher);
    var jobQueue = new JobQueue(metadataBackend, jobPublisher);
    var jobBackend = new JobBackend(metadataBackend, jobQueue);
    var userDatabaseMetadataService = new UserDatabaseMetadataService(metadataBackend);
    var jobCanceller = new JobCanceller(userDatabaseMetadataService);
    var jobService = new JobService(jobBackend, jobCanceller);

    var genericController = new GenericController();
    genericController.route(app);

    var queryController = new QueryController(userDatabaseService, tableCache, statsd_client);
    queryController.route(app);

    var jobController = new JobController(userDatabaseService, jobService, statsd_client);
    jobController.route(app);

    var cacheStatusController = new CacheStatusController(tableCache);
    cacheStatusController.route(app);

    var healthCheckController = new HealthCheckController();
    healthCheckController.route(app);

    var versionController = new VersionController();
    versionController.route(app);

    var isBatchProcess = process.argv.indexOf('--no-batch') === -1;

    if (global.settings.environment !== 'test' && isBatchProcess) {
        app.batch = batchFactory(metadataBackend, redisConfig, statsd_client, global.settings.batch_log_filename);
        app.batch.start();
    }

    return app;
}

module.exports = App;
<commit_msg>Add context object in all requests<commit_after>// CartoDB SQL API
//
// all requests expect the following URL args:
// - `sql` {String} SQL to execute
//
// for private (read/write) queries:
// - OAuth. Must have proper OAuth 1.1 headers. For OAuth 1.1 spec see Google
//
// eg. /api/v1/?sql=SELECT 1 as one (with a load of OAuth headers or URL arguments)
//
// for public (read only) queries:
// - sql only, provided the subdomain exists in CartoDB and the table's sharing options are public
//
// eg. vizzuality.cartodb.com/api/v1/?sql=SELECT * from my_table
//

var express = require('express');
var bodyParser = require('body-parser');
var os = require('os');
var Profiler = require('./stats/profiler-proxy');
var StatsD = require('node-statsd').StatsD;
var _ = require('underscore');
var LRU = require('lru-cache');

var RedisPool = require('redis-mpool');
var UserDatabaseService = require('./services/user_database_service');
var JobPublisher = require('../batch/job_publisher');
var JobQueue = require('../batch/job_queue');
var JobBackend = require('../batch/job_backend');
var JobCanceller = require('../batch/job_canceller');
var JobService = require('../batch/job_service');

var UserDatabaseMetadataService = require('../batch/user_database_metadata_service');

var cors = require('./middlewares/cors');

var GenericController = require('./controllers/generic_controller');
var QueryController = require('./controllers/query_controller');
var JobController = require('./controllers/job_controller');
var CacheStatusController = require('./controllers/cache_status_controller');
var HealthCheckController = require('./controllers/health_check_controller');
var VersionController = require('./controllers/version_controller');

var batchFactory = require('../batch');

process.env.PGAPPNAME = process.env.PGAPPNAME || 'cartodb_sqlapi';

// override Date.toJSON
require('./utils/date_to_json');

// jshint maxcomplexity:12
function App() {

    var app = express();

    var redisConfig = {
        host: global.settings.redis_host,
        port: global.settings.redis_port,
        max: global.settings.redisPool,
        idleTimeoutMillis: global.settings.redisIdleTimeoutMillis,
        reapIntervalMillis: global.settings.redisReapIntervalMillis
    };
    var metadataBackend = require('cartodb-redis')(redisConfig);

    // Set default configuration
    global.settings.db_pubuser = global.settings.db_pubuser || "publicuser";
    global.settings.bufferedRows = global.settings.bufferedRows || 1000;

    var tableCache = LRU({
      // store no more than these many items in the cache
      max: global.settings.tableCacheMax || 8192,
      // consider entries expired after these many milliseconds (10 minutes by default)
      maxAge: global.settings.tableCacheMaxAge || 1000*60*10
    });

    // Size based on https://github.com/CartoDB/cartodb.js/blob/3.15.2/src/geo/layer_definition.js#L72
    var SQL_QUERY_BODY_LOG_MAX_LENGTH = 2000;
    app.getSqlQueryFromRequestBody = function(req) {
        var sqlQuery = req.body && req.body.q;
        if (!sqlQuery) {
            return '';
        }

        if (sqlQuery.length > SQL_QUERY_BODY_LOG_MAX_LENGTH) {
            sqlQuery = sqlQuery.substring(0, SQL_QUERY_BODY_LOG_MAX_LENGTH) + ' [...]';
        }
        return JSON.stringify({q: sqlQuery});
    };

    if ( global.log4js ) {
        var loggerOpts = {
            buffer: true,
            // log4js provides a tokens solution as expess but in does not provide the request/response in the callback.
            // Thus it is not possible to extract relevant information from them.
            // This is a workaround to be able to access request/response.
            format: function(req, res, format) {
                var logFormat = global.settings.log_format ||
                    ':remote-addr :method :req[Host]:url :status :response-time ms -> :res[Content-Type]';

                logFormat = logFormat.replace(/:sql/, app.getSqlQueryFromRequestBody(req));
                return format(logFormat);
            }
        };
        app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level:'info'})));
    }

    // Initialize statsD client if requested
    var statsd_client;
    if ( global.settings.statsd ) {

      // Perform keyword substitution in statsd
      if ( global.settings.statsd.prefix ) {
        var host_token = os.hostname().split('.').reverse().join('.');
        global.settings.statsd.prefix = global.settings.statsd.prefix.replace(/:host/, host_token);
      }

      statsd_client = new StatsD(global.settings.statsd);
      statsd_client.last_error = { msg:'', count:0 };
      statsd_client.socket.on('error', function(err) {
        var last_err = statsd_client.last_error;
        var last_msg = last_err.msg;
        var this_msg = ''+err;
        if ( this_msg !== last_msg ) {
          console.error("statsd client socket error: " + err);
          statsd_client.last_error.count = 1;
          statsd_client.last_error.msg = this_msg;
        } else {
            ++last_err.count;
            if ( ! last_err.interval ) {
              //console.log("Installing interval");
              statsd_client.last_error.interval = setInterval(function() {
                var count = statsd_client.last_error.count;
                if ( count > 1 ) {
                  console.error("last statsd client socket error repeated " + count + " times");
                  statsd_client.last_error.count = 1;
                  //console.log("Clearing interval");
                  clearInterval(statsd_client.last_error.interval);
                  statsd_client.last_error.interval = null;
                }
              }, 1000);
            }
        }
      });
    }

    app.use(cors());

    // Use step-profiler
    app.use(function bootstrap$prepareRequestResponse(req, res, next) {
        req.context = req.context || {};

        var profile = global.settings.useProfiler;
        req.profiler = new Profiler({
            profile: profile,
            statsd_client: statsd_client
        });
        next();
    });

    // Set connection timeout
    if ( global.settings.hasOwnProperty('node_socket_timeout') ) {
      var timeout = parseInt(global.settings.node_socket_timeout);
      app.use(function(req, res, next) {
        req.connection.setTimeout(timeout);
        next();
      });
    }

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.enable('jsonp callback');
    app.set("trust proxy", true);
    app.disable('x-powered-by');
    app.disable('etag');

    // basic routing

    var userDatabaseService = new UserDatabaseService(metadataBackend);

    var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'job-publisher'}));
    var jobPublisher = new JobPublisher(redisPoolPublisher);
    var jobQueue = new JobQueue(metadataBackend, jobPublisher);
    var jobBackend = new JobBackend(metadataBackend, jobQueue);
    var userDatabaseMetadataService = new UserDatabaseMetadataService(metadataBackend);
    var jobCanceller = new JobCanceller(userDatabaseMetadataService);
    var jobService = new JobService(jobBackend, jobCanceller);

    var genericController = new GenericController();
    genericController.route(app);

    var queryController = new QueryController(userDatabaseService, tableCache, statsd_client);
    queryController.route(app);

    var jobController = new JobController(userDatabaseService, jobService, statsd_client);
    jobController.route(app);

    var cacheStatusController = new CacheStatusController(tableCache);
    cacheStatusController.route(app);

    var healthCheckController = new HealthCheckController();
    healthCheckController.route(app);

    var versionController = new VersionController();
    versionController.route(app);

    var isBatchProcess = process.argv.indexOf('--no-batch') === -1;

    if (global.settings.environment !== 'test' && isBatchProcess) {
        app.batch = batchFactory(metadataBackend, redisConfig, statsd_client, global.settings.batch_log_filename);
        app.batch.start();
    }

    return app;
}

module.exports = App;
<|endoftext|>


<commit_before>var fs = require('fs');
var http = require('http');
var formidable = require('formidable');
var xlsx = require('node-xlsx');
var shopifyAPI = require('shopify-node-api');

var request = require('request').defaults({ encoding: null });

var trim = require('trim');
var slug = require('slug');

var Shopify = new shopifyAPI({
  shop: process.env.SHOP, // MYSHOP.myshopify.com  // process.env.shop
  apiKey: process.env.API_KEY, // Your API key
  access_token: process.env.PASSWORD, // Your API password
  verbose: false
});

function callback(err, data, headers) {
  var api_limit = headers['http_x_shopify_shop_api_call_limit'];
  console.log( api_limit ); // "1/40"
}

// var query_data = '';

// Shopify.get('/admin/products.json', query_data, function(err, data, headers){
//   console.log(data); // Data contains product json information
//   console.log(headers); // Headers returned from request
// });

console.log(process.env.SHOP);
console.log(process.env.API_KEY);
console.log(process.env.PASSWORD);
console.log(process.env.ACCESS_TOKEN);

// console.log(Shopify.hostname());

http.createServer(function (req, res) {
  if (req.url == '/fileupload') {
  	res.writeHead(200, {'Content-Type': 'text/html'});
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
      var oldpath = files.filetoupload.path;
      // var newpath = 'C:/Users/Your Name/' + files.filetoupload.name;
      // fs.rename(oldpath, newpath, function (err) {
      //   if (err) throw err;
      //   res.write('File uploaded and moved!');
      //   res.end();
      // });

   	  //   fs.createReadStream(files.filetoupload.path)
	  // .pipe(csv())
	  // .on('data', function (data) {
	  //   console.log(data);
	  // })

     const workSheetsFromFile = xlsx.parse(files.filetoupload.path);

     // console.log(workSheetsFromFile[0].data[1]);

     var artist = workSheetsFromFile[0].data[1];

     workSheetsFromFile[0].data.shift();

     // var test = [];

     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());

    // console.log(test);
		workSheetsFromFile[0].data.forEach(function(currentValue, currentIndex, listObj){
		// test.forEach(function(currentValue, currentIndex, listObj){

		// console.log(slug(listObj[currentIndex][3]).toLowerCase());
		// res.write( '
' + slug(listObj[currentIndex][3].toLowerCase()) + '
');

		var handle = '';

		if( listObj[currentIndex][3] ){
			handle = slug(listObj[currentIndex][3].toLowerCase());
		}

		var title = '';
		if( listObj[currentIndex][3] ){
			title = trim(listObj[currentIndex][3]);
		}

		var instagramURL = '';
		var facebookURL = '';
		var websiteURL = '';

		if( listObj[currentIndex][6] && trim(listObj[currentIndex][6]) != '' ){
			// console.log(instagram(listObj[currentIndex][6]));
			// res.write( '
' + instagram(listObj[currentIndex][6]) + '
');
			instagramURL = instagram(listObj[currentIndex][6]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		if( listObj[currentIndex][5] && trim(listObj[currentIndex][5]) != '' ){
			// console.log(facebook(listObj[currentIndex][5]));
			// res.write( '
' + facebook(listObj[currentIndex][5]) + '
');
			facebookURL = facebook(listObj[currentIndex][5]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		if( listObj[currentIndex][4] && trim(listObj[currentIndex][4]) != '' ){
			// console.log(website(listObj[currentIndex][4]));
			// res.write( '
' + facebook(listObj[currentIndex][5]) + '
');
			websiteURL = website(listObj[currentIndex][4]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		var body_html = '';
		body_html = (listObj[currentIndex][8])? '
'+listObj[currentIndex][8].replace('\r\n','

').replace('\r\n','

').replace('\r\n','

').replace('\r\n','

').replace('\r\n','

')+'
':'' ;
		body_html = body_html + '
';
		body_html = body_html + ((body_html)? ' ':'' ) + ((websiteURL != '')?''+createURL(websiteURL, 'WEBSITE'):'' );

		body_html = body_html + ((websiteURL != '' && ( facebookURL != '' || instagramURL != '' ) )? ' // ':'');

		body_html = body_html + ((facebookURL != '')?''+createURL(facebookURL, 'FACEBOOK'):'' );

		body_html = body_html + ((facebookURL != '' && instagramURL != '' )? ' // ':'');

		body_html = body_html + ((instagramURL != '')?''+createURL(instagramURL, 'INSTAGRAM'):'' );
		body_html = body_html + '
';

		body_html = trim(body_html);

		// console.log(body_html);

		// console.log(facebookURL);
		var tags = [];

		if( listObj[currentIndex][7] ){
			tags = tags.concat( listObj[currentIndex][7].split(/\r?\n/) );
		}

		if( listObj[currentIndex][0].includes("BOTH") ){
			tags.push('Missoula Holiday MADE fair');
			tags.push('Helena Holiday MADE fair');
		}else if( listObj[currentIndex][0].includes("Missoula") ){
			tags.push('Missoula Holiday MADE fair');
		}else if( listObj[currentIndex][0].includes("Helena") ){
			tags.push('Helena Holiday MADE fair');
		}

		tags = tags.join(',');

		// wait(500);
		// console.log('waiting...');

		request.get(listObj[currentIndex][9], function (error, response, body) {
	    if (!error && response.statusCode == 200) {
	        attachment = "" + new Buffer(body).toString('base64');
	        // console.log(attachment);

	         var post_data = {
			  "product": {
			  	"handle": handle,
			    "title": title,
			    "body_html": body_html,
			    "vendor": "",
			    "product_type": "artist",
			    "published_scope": "global",
			    "images": [
			      {
			        "attachment": attachment
			      }
			    ],
			    "tags": tags,
			    "variants": [
			    ]
			  }
			}

			// console.log(post_data);

			Shopify.post('/admin/products.json', post_data, function(err, data, headers){
			  console.log(err);
			  console.log(data);
			  console.log(headers);
			  if(data){
			  	res.write(JSON.stringify(data));
			  }else if(err){
			  	res.write(JSON.stringify(err));
			  }

			});

	    }else{
	    	console.log(listObj[currentIndex][9]);
	    	console.log('Request error: '+error);
	    }

	});

	});

 });
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
    res.write('<input type="file" name="filetoupload">
');
    res.write('<input type="submit">');
    res.write('</form>');
    return res.end();
  }
}).listen(8080);

function instagram(url){
	var baseUrl = 'https://www.instagram.com/';

	username = url.toLowerCase().split("?")[0];
	username = username.replace('www.instagram.com','');
	username = username.replace('instagram.com','');
	username = username.replace('https://www.','');
	username = username.replace('http://www.','');
	username = username.replace('https:','');
	username = username.replace('http:','');
	username = username.replace('/','').replace('/','').replace('/','').replace('/','').replace('/','');
	username = username.replace('@','');
	username = username.replace("'",'').replace("'",'');
	username = username.replace(' ','').replace(' ','');

	username = trim(username);

	return baseUrl+username;
}

function facebook(url){
	var baseUrl = 'https://www.facebook.com/';

	username = url.toLowerCase().split("?")[0];
	username = username.replace('www.facebook.com','');
	username = username.replace('facebook.com','');
	username = username.replace('https://www.','');
	username = username.replace('http://www.','');
	username = username.replace('https:','');
	username = username.replace('http:','');
	username = username.replace('/','').replace('/','').replace('/','').replace('/','').replace('/','');
	username = username.replace('@','');
	username = username.replace("'",'').replace("'",'');
	username = username.replace(' ','').replace(' ','');

	username = trim(username);

	return baseUrl+username;
}

function website(url){
	var baseUrl = '';

	url = trim(url);

	url = url.replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','');

	if (!/^(f|ht)tps?:\/\//i.test(url)) {
      url = "http://" + url;
    }

	return url;
}

function createURL(url, string){
	return ''+string+'';
}

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}<commit_msg>Changed from http to express<commit_after>var fs = require('fs');
// var http = require('http');
var formidable = require('formidable');
var xlsx = require('node-xlsx');
var shopifyAPI = require('shopify-node-api');

var express = require('express');
var app = express();

var request = require('request').defaults({ encoding: null });

var trim = require('trim');
var slug = require('slug');

var Shopify = new shopifyAPI({
  shop: process.env.SHOP, // MYSHOP.myshopify.com  // process.env.shop
  apiKey: process.env.API_KEY, // Your API key
  access_token: process.env.PASSWORD, // Your API password
  verbose: false
});

function callback(err, data, headers) {
  var api_limit = headers['http_x_shopify_shop_api_call_limit'];
  console.log( api_limit ); // "1/40"
}

// var query_data = '';

// Shopify.get('/admin/products.json', query_data, function(err, data, headers){
//   console.log(data); // Data contains product json information
//   console.log(headers); // Headers returned from request
// });

console.log(process.env.SHOP);
console.log(process.env.API_KEY);
console.log(process.env.PASSWORD);
console.log(process.env.ACCESS_TOKEN);

// console.log(Shopify.hostname());

/**
*
* Http Server
*
*/

app.set('port', (process.env.PORT || 5000));

// // views is directory for all template files
// // app.set('views', __dirname + '/views');
// // app.set('view engine', 'ejs');

app.get('/', function(req, res) {
  if (req.url == '/fileupload') {
  	res.writeHead(200, {'Content-Type': 'text/html'});
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
      var oldpath = files.filetoupload.path;
      // var newpath = 'C:/Users/Your Name/' + files.filetoupload.name;
      // fs.rename(oldpath, newpath, function (err) {
      //   if (err) throw err;
      //   res.write('File uploaded and moved!');
      //   res.end();
      // });

   	  //   fs.createReadStream(files.filetoupload.path)
	  // .pipe(csv())
	  // .on('data', function (data) {
	  //   console.log(data);
	  // })

     const workSheetsFromFile = xlsx.parse(files.filetoupload.path);

     // console.log(workSheetsFromFile[0].data[1]);

     var artist = workSheetsFromFile[0].data[1];

     workSheetsFromFile[0].data.shift();

     // var test = [];

     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());
     // test.push(workSheetsFromFile[0].data.pop());

    // console.log(test);
		workSheetsFromFile[0].data.forEach(function(currentValue, currentIndex, listObj){
		// test.forEach(function(currentValue, currentIndex, listObj){

		// console.log(slug(listObj[currentIndex][3]).toLowerCase());
		// res.write( '
' + slug(listObj[currentIndex][3].toLowerCase()) + '
');

		var handle = '';

		if( listObj[currentIndex][3] ){
			handle = slug(listObj[currentIndex][3].toLowerCase());
		}

		var title = '';
		if( listObj[currentIndex][3] ){
			title = trim(listObj[currentIndex][3]);
		}

		var instagramURL = '';
		var facebookURL = '';
		var websiteURL = '';

		if( listObj[currentIndex][6] && trim(listObj[currentIndex][6]) != '' ){
			// console.log(instagram(listObj[currentIndex][6]));
			// res.write( '
' + instagram(listObj[currentIndex][6]) + '
');
			instagramURL = instagram(listObj[currentIndex][6]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		if( listObj[currentIndex][5] && trim(listObj[currentIndex][5]) != '' ){
			// console.log(facebook(listObj[currentIndex][5]));
			// res.write( '
' + facebook(listObj[currentIndex][5]) + '
');
			facebookURL = facebook(listObj[currentIndex][5]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		if( listObj[currentIndex][4] && trim(listObj[currentIndex][4]) != '' ){
			// console.log(website(listObj[currentIndex][4]));
			// res.write( '
' + facebook(listObj[currentIndex][5]) + '
');
			websiteURL = website(listObj[currentIndex][4]);
		}else{
			// console.log('N/A');
			// res.write('
N/A
');
		}

		var body_html = '';
		body_html = (listObj[currentIndex][8])? '
'+listObj[currentIndex][8].replace('\r\n','

').replace('\r\n','

').replace('\r\n','

').replace('\r\n','

').replace('\r\n','

')+'
':'' ;
		body_html = body_html + '
';
		body_html = body_html + ((body_html)? ' ':'' ) + ((websiteURL != '')?''+createURL(websiteURL, 'WEBSITE'):'' );

		body_html = body_html + ((websiteURL != '' && ( facebookURL != '' || instagramURL != '' ) )? ' // ':'');

		body_html = body_html + ((facebookURL != '')?''+createURL(facebookURL, 'FACEBOOK'):'' );

		body_html = body_html + ((facebookURL != '' && instagramURL != '' )? ' // ':'');

		body_html = body_html + ((instagramURL != '')?''+createURL(instagramURL, 'INSTAGRAM'):'' );
		body_html = body_html + '
';

		body_html = trim(body_html);

		// console.log(body_html);

		// console.log(facebookURL);
		var tags = [];

		if( listObj[currentIndex][7] ){
			tags = tags.concat( listObj[currentIndex][7].split(/\r?\n/) );
		}

		if( listObj[currentIndex][0].includes("BOTH") ){
			tags.push('Missoula Holiday MADE fair');
			tags.push('Helena Holiday MADE fair');
		}else if( listObj[currentIndex][0].includes("Missoula") ){
			tags.push('Missoula Holiday MADE fair');
		}else if( listObj[currentIndex][0].includes("Helena") ){
			tags.push('Helena Holiday MADE fair');
		}

		tags = tags.join(',');

		// wait(500);
		// console.log('waiting...');

		request.get(listObj[currentIndex][9], function (error, response, body) {
	    if (!error && response.statusCode == 200) {
	        attachment = "" + new Buffer(body).toString('base64');
	        // console.log(attachment);

	         var post_data = {
			  "product": {
			  	"handle": handle,
			    "title": title,
			    "body_html": body_html,
			    "vendor": "",
			    "product_type": "artist",
			    "published_scope": "global",
			    "images": [
			      {
			        "attachment": attachment
			      }
			    ],
			    "tags": tags,
			    "variants": [
			    ]
			  }
			}

			// console.log(post_data);

			Shopify.post('/admin/products.json', post_data, function(err, data, headers){
			  console.log(err);
			  console.log(data);
			  console.log(headers);
			  if(data){
			  	res.write(JSON.stringify(data));
			  }else if(err){
			  	res.write(JSON.stringify(err));
			  }

			});

	    }else{
	    	console.log(listObj[currentIndex][9]);
	    	console.log('Request error: '+error);
	    }

	});

	});

 });
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
    res.write('<input type="file" name="filetoupload">
');
    res.write('<input type="submit">');
    res.write('</form>');
    return res.end();
  }
}).listen(8080);

function instagram(url){
	var baseUrl = 'https://www.instagram.com/';

	username = url.toLowerCase().split("?")[0];
	username = username.replace('www.instagram.com','');
	username = username.replace('instagram.com','');
	username = username.replace('https://www.','');
	username = username.replace('http://www.','');
	username = username.replace('https:','');
	username = username.replace('http:','');
	username = username.replace('/','').replace('/','').replace('/','').replace('/','').replace('/','');
	username = username.replace('@','');
	username = username.replace("'",'').replace("'",'');
	username = username.replace(' ','').replace(' ','');

	username = trim(username);

	return baseUrl+username;
}

function facebook(url){
	var baseUrl = 'https://www.facebook.com/';

	username = url.toLowerCase().split("?")[0];
	username = username.replace('www.facebook.com','');
	username = username.replace('facebook.com','');
	username = username.replace('https://www.','');
	username = username.replace('http://www.','');
	username = username.replace('https:','');
	username = username.replace('http:','');
	username = username.replace('/','').replace('/','').replace('/','').replace('/','').replace('/','');
	username = username.replace('@','');
	username = username.replace("'",'').replace("'",'');
	username = username.replace(' ','').replace(' ','');

	username = trim(username);

	return baseUrl+username;
}

function website(url){
	var baseUrl = '';

	url = trim(url);

	url = url.replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','').replace(' ','');

	if (!/^(f|ht)tps?:\/\//i.test(url)) {
      url = "http://" + url;
    }

	return url;
}

function createURL(url, string){
	return ''+string+'';
}

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}<|endoftext|>


<commit_before>var fs = require('fs'),
    detectIndent = require('detect-indent'),
    os = require('os')

var readSync = function (file) {
    var str = fs.readFileSync(file, 'utf8');
    return process(str);
}

var writeSync = function (file, data, options) {
    var str = post(data, options);
    fs.writeFileSync(file, str, 'utf8');
    return str;
}

var sync = function (file, data) {
    var options = readSync(file)
    return writeSync(file, data, options);
}

var process = function (str) {
    var indent = detectIndent(str) || '  ',
        spaces = indent.length,
        cf = false,
        ending

    str = str.split('\n')
    str.forEach(function (line) {
        if (line.indexOf(',') > -1) {
            if (!line.match(/,$/)) {
                cf = true
            }
        }
    })
    ending = (str[str.length - 1] === '') ? '\n' : ''
    return {
        indent: indent,
        spaces: spaces,
        cf: cf,
        ending: ending
    };
}

var read = function (file, cb) {
    fs.readFile(file, 'utf8', function (err, str) {
        if (err) return cb(err)
        cb(null, process(str));
    })
}

var post = function (data, options) {
    var str = JSON.stringify(data, null, options.spaces);
    if (options.cf) {
        str = str.split(/(,\n\s+)/)
            .map(function (e, i) {
                return i % 2 ? '\n' + e.substring(4) + ', ' : e
            })
            .join('')
    }
    str += options.ending
    return str;
}

var write = function (file, data, options, callback) {
    var str = post(data, options);
    fs.writeFile(file, str, 'utf8', function (err) {
        /* istanbul ignore next */
        if (err) return callback(err)
        callback(null, str)
    });
}

var format = function (file, data, callback) {
    read(file, function (err, options) {
        /* istanbul ignore next */
        if (err) return callback(err)
        write(file, data, options, callback)
    });
}

format.read = read
format.write = write

format.readSync = readSync
format.writeSync = writeSync
format.sync = sync

module.exports = format

<commit_msg>Making sure default options are picked up<commit_after>var fs = require('fs'),
    detectIndent = require('detect-indent'),
    os = require('os')

var readSync = function (file) {
    var str = fs.readFileSync(file, 'utf8');
    return process(str);
}

var writeSync = function (file, data, options) {
    var str = post(data, options);
    fs.writeFileSync(file, str, 'utf8');
    return str;
}

var sync = function (file, data) {
    var options = readSync(file)
    return writeSync(file, data, options);
}

var process = function (str) {
    var indent = detectIndent(str) || '  ',
        spaces = indent.length,
        cf = false,
        ending

    str = str.split('\n')
    str.forEach(function (line) {
        if (line.indexOf(',') > -1) {
            if (!line.match(/,$/)) {
                cf = true
            }
        }
    })
    ending = (str[str.length - 1] === '') ? '\n' : ''
    return {
        indent: indent,
        spaces: spaces,
        cf: cf,
        ending: ending
    };
}

var read = function (file, cb) {
    fs.readFile(file, 'utf8', function (err, str) {
        if (err) return cb(err)
        cb(null, process(str));
    })
}

var post = function (data, options) {
    options.spaces = options.spaces || 2
    var str = JSON.stringify(data, null, options.spaces),
        ending = (options.ending === undefined) ? '\n' : options.ending;
    if (options.cf) {
        str = str.split(/(,\n\s+)/)
            .map(function (e, i) {
                return i % 2 ? '\n' + e.substring(4) + ', ' : e
            })
            .join('')
    }
    str += ending
    return str;
}

var write = function (file, data, options, callback) {
    var str = post(data, options);
    fs.writeFile(file, str, 'utf8', function (err) {
        /* istanbul ignore next */
        if (err) return callback(err)
        callback(null, str)
    });
}

var format = function (file, data, callback) {
    read(file, function (err, options) {
        /* istanbul ignore next */
        if (err) return callback(err)
        write(file, data, options, callback)
    });
}

format.read = read
format.write = write

format.readSync = readSync
format.writeSync = writeSync
format.sync = sync

module.exports = format

<|endoftext|>


<commit_before>'use strict';

var fs = require("fs")
var path = require('path')
var loaderUtils = require('loader-utils');
var elmCompiler = require('node-elm-compiler');
var yargs = require('yargs');

var cachedDependencies = [];
var cachedDirDependencies = [];

var defaultOptions = {
  cache: false,
  yes: true
};

var getInput = function() {
  return this.resourcePath;
};

var getOptions = function() {
  var globalOptions = this.options.elm || {};
  var loaderOptions = loaderUtils.parseQuery(this.query);
  return Object.assign({
    emitWarning: this.emitWarning
  }, defaultOptions, globalOptions, loaderOptions);
};

var addDependencies = function(dependencies) {
  cachedDependencies = cachedDependencies.concat(dependencies);
  dependencies.forEach(this.addDependency.bind(this));
};

var addDirDependency = function(dirs){
  cachedDirDependencies = cachedDirDependencies.concat(dirs);
  dirs.forEach(this.addContextDependency.bind(this));
};

var isInWatchMode = function(){
  var argv = yargs(process.argv)
      .alias('w', 'watch')
      .argv;

  return typeof argv.watch !== "undefined" && argv.watch;
};

/* Takes a working dir, tries to read elm-package.json, then grabs all the modules from in there
*/
var filesToWatch = function(cwd){
  var readFile = fs.readFileSync(path.join(cwd, "elm-package.json"), 'utf8');
  var elmPackage = JSON.parse(readFile);

  var elmPackage = JSON.parse(readFile);

  var paths = elmPackage["source-directories"].map(function(dir){
    return path.join(cwd, dir);
  });

  return paths;
};

module.exports = function() {
  this.cacheable && this.cacheable();

  var callback = this.async();

  if (!callback) {
    throw 'elm-webpack-loader currently only supports async mode.';
  }

  var input = getInput.call(this);
  var options = getOptions.call(this);

  var compilation = elmCompiler.compileToString(input, options)
    .then(function(v) { return { kind: 'success', result: v }; })
    .catch(function(v) { return { kind: 'error', error: v }; });

  var promises = [compilation];

  // we only need to track deps if we are in watch mode
  // otherwise, we trust elm to do it's job
  if (isInWatchMode()){
    // we can do a glob to track deps we care about if cwd is set
    if (typeof options.cwd !== "undefined" && options.cwd !== null){
      // watch elm-package.json
      addDependencies.bind(this)([path.join(options.cwd, "elm-package.json")]);
      var dirs = filesToWatch(options.cwd);
      // watch all the dirs in elm-package.json
      addDirDependency.bind(this)(dirs);
    } else {
      var dependencies = Promise.resolve()
        .then(function() {
          if (!options.cache || cachedDependencies.length === 0) {
            return elmCompiler.findAllDependencies(input).then(addDependencies.bind(this));
          }
        }.bind(this))
        .then(function(v) { return { kind: 'success', result: v }; })
        .catch(function(v) { return { kind: 'error', error: v }; });

      promises.push(dependencies);
    }
  }

  Promise.all(promises)
    .then(function(results) {
      var output = results[0]; // compilation output
      if (output.kind == 'success') {
        callback(null, output.result);
      } else {
        output.error.message = 'Compiler process exited with error ' + output.error.message;
        callback(output.error);
      }
    });
}
<commit_msg>Pick up file changes when using Webpack Dev Server<commit_after>'use strict';

var fs = require("fs")
var path = require('path')
var loaderUtils = require('loader-utils');
var elmCompiler = require('node-elm-compiler');
var yargs = require('yargs');

var cachedDependencies = [];
var cachedDirDependencies = [];

var defaultOptions = {
  cache: false,
  yes: true
};

var getInput = function() {
  return this.resourcePath;
};

var getOptions = function() {
  var globalOptions = this.options.elm || {};
  var loaderOptions = loaderUtils.parseQuery(this.query);
  return Object.assign({
    emitWarning: this.emitWarning
  }, defaultOptions, globalOptions, loaderOptions);
};

var addDependencies = function(dependencies) {
  cachedDependencies = cachedDependencies.concat(dependencies);
  dependencies.forEach(this.addDependency.bind(this));
};

var addDirDependency = function(dirs){
  cachedDirDependencies = cachedDirDependencies.concat(dirs);
  dirs.forEach(this.addContextDependency.bind(this));
};

var isInWatchMode = function(){
  var argv = yargs(process.argv)
      .alias('w', 'watch')
      .argv;
  var hasWebpackDevServer = Array.prototype.filter.call(process.argv, function (arg) {
    return arg.indexOf('webpack-dev-server') !== -1;
  }).length > 0;

  return hasWebpackDevServer || (typeof argv.watch !== "undefined" && argv.watch);
};

/* Takes a working dir, tries to read elm-package.json, then grabs all the modules from in there
*/
var filesToWatch = function(cwd){
  var readFile = fs.readFileSync(path.join(cwd, "elm-package.json"), 'utf8');
  var elmPackage = JSON.parse(readFile);

  var elmPackage = JSON.parse(readFile);

  var paths = elmPackage["source-directories"].map(function(dir){
    return path.join(cwd, dir);
  });

  return paths;
};

module.exports = function() {
  this.cacheable && this.cacheable();

  var callback = this.async();

  if (!callback) {
    throw 'elm-webpack-loader currently only supports async mode.';
  }

  var input = getInput.call(this);
  var options = getOptions.call(this);

  var compilation = elmCompiler.compileToString(input, options)
    .then(function(v) { return { kind: 'success', result: v }; })
    .catch(function(v) { return { kind: 'error', error: v }; });

  var promises = [compilation];

  // we only need to track deps if we are in watch mode
  // otherwise, we trust elm to do it's job
  if (isInWatchMode()){
    // we can do a glob to track deps we care about if cwd is set
    if (typeof options.cwd !== "undefined" && options.cwd !== null){
      // watch elm-package.json
      addDependencies.bind(this)([path.join(options.cwd, "elm-package.json")]);
      var dirs = filesToWatch(options.cwd);
      // watch all the dirs in elm-package.json
      addDirDependency.bind(this)(dirs);
    } else {
      var dependencies = Promise.resolve()
        .then(function() {
          if (!options.cache || cachedDependencies.length === 0) {
            return elmCompiler.findAllDependencies(input).then(addDependencies.bind(this));
          }
        }.bind(this))
        .then(function(v) { return { kind: 'success', result: v }; })
        .catch(function(v) { return { kind: 'error', error: v }; });

      promises.push(dependencies);
    }
  }

  Promise.all(promises)
    .then(function(results) {
      var output = results[0]; // compilation output
      if (output.kind == 'success') {
        callback(null, output.result);
      } else {
        output.error.message = 'Compiler process exited with error ' + output.error.message;
        callback(output.error);
      }
    });
}
<|endoftext|>


<commit_before>'use strict';

var falsey = require('falsey');
var utils = require('./utils');

/**
 * When invoked, this creates three view collections, `layouts`, `docs`
 * and `includes`, but only if they're not already on the instance.
 *
 * If a collection does already exist on the instance, its options will
 * be updated with any options defined on your application instance,
 * or options passed directly to the [invoke](#invoke) function.
 *
 * In your generator:
 *
 * ```js
 * app.extendWith(require('generate-collections'));
 * ```
 * @param {Object} `app` instance of generator, verb or assemble.
 * @api public
 */

function generator(app, base) {
  app.task('collections', { silent: true }, task(app, base.options));
  app.task('default', ['collections']);
}

/**
 * Exposes the `collections` task function directly, so you can register
 * the task with any name that makes sense for your project.
 *
 * ```js
 * var collections = require('generate-collections');
 * app.task('foo', collections.task(app));
 * ```
 * @param {Object} `app`
 * @return {Function} Returns the task callback
 * @api public
 */

function task(app, opts) {
  return function(cb) {
    invoke(app, opts);
    cb();
  };
}

/**
 * Exposes the generator on the `invoke` property, allowing you to load
 * the collections wherever and whenever it makes sense.
 *
 * ```js
 * var collections = require('generate-collections');
 *
 * // in your generator
 * collections.invoke(app, [options]);
 * ```
 * @name .invoke
 * @param {Object} `app`
 * @param {Object} `options`
 * @api public
 */

function invoke(app, options) {
  var opts = utils.extend({}, app.options, options);

  // add middleware
  middleware(app);

  // add default view collections
  app.create('docs', { viewType: 'partial' });
  app.create('badges', { viewType: 'partial' });
  app.create('includes', { viewType: 'partial' });
  app.create('layouts', { viewType: 'layout' });

  // "noop" layout
  app.layout('empty', {content: '{% body %}'});

  // create collections defined on the options
  if (utils.isObject(opts.create)) {
    for (var key in opts.create) {
      if (!app[key]) {
        app.create(key, opts.create[key]);
      } else {
        app[key].option(opts.create[key]);
      }
    }
  }
}

/**
 * Middleware for collections created by this generator
 */

function middleware(app) {
  // use an empty layout to unsure that all pre-and
  // post-layout middleware are still triggered
  app.preLayout(/\.md/, function(view, next) {
    if (falsey(view.layout) && view.isType('renderable')) {
      view.layout = 'empty';
    }
    if (view.isType('partial') || view.isType('layout') && view.layout === 'default') {
      view.layout = 'empty';
      view.options.layout = null;
    }
    next();
  });
}

/**
 * Expose collections on the `invoke` property and as a task to
 * support lazy invocation
 */

generator.invoke = invoke;
generator.task = task;

/**
 * Expose `generator`
 */

module.exports = generator;
<commit_msg>allow `docs` collection views to be rendered directly or used as includes<commit_after>'use strict';

var falsey = require('falsey');
var utils = require('./utils');

/**
 * When invoked, this creates three view collections, `layouts`, `docs`
 * and `includes`, but only if they're not already on the instance.
 *
 * If a collection does already exist on the instance, its options will
 * be updated with any options defined on your application instance,
 * or options passed directly to the [invoke](#invoke) function.
 *
 * In your generator:
 *
 * ```js
 * app.extendWith(require('generate-collections'));
 * ```
 * @param {Object} `app` instance of generator, verb or assemble.
 * @api public
 */

function generator(app, base) {
  app.task('collections', { silent: true }, task(app, base.options));
  app.task('default', ['collections']);
}

/**
 * Exposes the `collections` task function directly, so you can register
 * the task with any name that makes sense for your project.
 *
 * ```js
 * var collections = require('generate-collections');
 * app.task('foo', collections.task(app));
 * ```
 * @param {Object} `app`
 * @return {Function} Returns the task callback
 * @api public
 */

function task(app, opts) {
  return function(cb) {
    invoke(app, opts);
    cb();
  };
}

/**
 * Exposes the generator on the `invoke` property, allowing you to load
 * the collections wherever and whenever it makes sense.
 *
 * ```js
 * var collections = require('generate-collections');
 *
 * // in your generator
 * collections.invoke(app, [options]);
 * ```
 * @name .invoke
 * @param {Object} `app`
 * @param {Object} `options`
 * @api public
 */

function invoke(app, options) {
  var opts = utils.extend({}, app.options, options);

  // add middleware
  middleware(app);

  // add default view collections
  app.create('docs', { viewType: ['partial', 'renderable'] });
  app.create('badges', { viewType: 'partial' });
  app.create('includes', { viewType: 'partial' });
  app.create('layouts', { viewType: 'layout' });

  // "noop" layout
  app.layout('empty', {content: '{% body %}'});

  // create collections defined on the options
  if (utils.isObject(opts.create)) {
    for (var key in opts.create) {
      if (!app[key]) {
        app.create(key, opts.create[key]);
      } else {
        app[key].option(opts.create[key]);
      }
    }
  }
}

/**
 * Middleware for collections created by this generator
 */

function middleware(app) {
  // use an empty layout to unsure that all pre-and
  // post-layout middleware are still triggered
  app.preLayout(/\.md/, function(view, next) {
    if (falsey(view.layout) && view.isType('renderable')) {
      view.layout = 'empty';
    }
    if (view.isType('partial') || view.isType('layout') && view.layout === 'default') {
      view.layout = 'empty';
      view.options.layout = null;
    }
    next();
  });
}

/**
 * Expose collections on the `invoke` property and as a task to
 * support lazy invocation
 */

generator.invoke = invoke;
generator.task = task;

/**
 * Expose `generator`
 */

module.exports = generator;
<|endoftext|>


<commit_before>var util = require('util');
var EventEmitter = require('events').EventEmitter;
var nmea = require('nmea');
var Packetizer = require('./lib/packetizer');

var DEBUG = false;  //  Set to true for debug console logs

var GPS = function (hardware, callback) {
  /*
  Constructor

  Args
    hardware
      The Tessel port to use
    callback
      Callback function
  */
  var self = this;
  self.hardware = hardware;
  self.onOff = self.hardware.gpio(3);
  self.powerState = 'off';
  self.timeoutDuration = 10*1000;
  self.format = 'deg-min-dec';
  //  A collection of attributes and callback functions. See set/removeCallback.
  self.callbacks = {};

  //  Turn the module on
  self.initialPowerSequence(function (err) {
    if (!err) {
      //  Once we are on, emit the connected event
      self.beginDecoding(function () {

        setImmediate(function () {
          self.emit('ready');
        });
      });
    } else {
      setImmediate(function () {
        self.emit('error', err);
      });
    }
    if (callback) {
      callback();
    }
  });
};

util.inherits(GPS, EventEmitter);

GPS.prototype.initialPowerSequence = function (callback) {
  /*
  Turn on and establish contact with the A2235-H GPS module

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  //  Tell Tessel to start UART at GPS baud rate
  this.uart = this.hardware.UART({baudrate : 115200});

  var noReceiveTimeout;

  function waitForData () {
    //  Remove this listener when we hear something (anything) from the GPS
    self.uart.removeListener('data', waitForData);

    clearTimeout(noReceiveTimeout);

    //  And note that we are on
    self.powerState = 'on';

    //  Tell the A2235-H that we want it to give us NMEA strings over UART
    self._switchToNMEA9800(callback);
  }

  function noDataRecieved () {
    //  Remove the listener for any data
    self.uart.removeListener('data', waitForData);
    //  Clear the timeout
    clearTimeout(noReceiveTimeout);
    //  Call the callback
    if (callback) {
      callback(new Error('Unable to connect to module...'));
    }
  }

  /*
  Wait for a second to see if we get data. If we do, call callback;
  If we don't, toggle power and set timeout again
  If we still don't get it, something bigger is wrong
  */

  //  This event listener will wait for valid data to note that we are on
  self.uart.once('data', function (data) {
    waitForData(data);
  });

  //  Set the timeout to try to turn on if not already
  noReceiveTimeout = setTimeout(function alreadyOn() {
    //  Try to turn on
    self.powerOn(function () {
      //  If it's still not on
      if (DEBUG) {
        console.log('state after power cycle:', self.powerState);
      }
      if (self.powerState === 'off') {
        //  Set the timeout once more
        if (DEBUG) {
          console.log('Trying once more...');
        }
        noReceiveTimeout = setTimeout(function () {
          //  If we still didn't get anything, fail the connect
          noDataRecieved();
        }, 1000);
      }
    });
  }, 1000);
};

GPS.prototype.powerOn = function (callback) {
  /*
  Try to turn the power on. Note that the A2235-H responds to a pulse, not the
  state of the power pin (it toggles).

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  self.power('on', function () {
    setImmediate(function () {
      self.emit('powerOn');
    });
    if (callback) {
      callback();
    }
  });
};

GPS.prototype.powerOff = function (callback) {
  /*
  Try to turn the power off. Note that the A2235-H responds to a pulse, not the
  state of the power pin (it toggles).

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  self.power('off', function () {
    setImmediate(function () {
      self.emit('powerOff');
    });
    if (callback) {
      callback();
    }
  });
};

GPS.prototype.power = function (state, callback) {
  /*
  Toggle the power pin of the A2235-H (attached to hardware.gpio[3]). Assumes
  the module knows what power state it is in.

  Args
    state
      'on' - turn the power on
      'off' - turn the power off
    callback
      Callback function
  */
  //  We need to switch from this state to the given state
  var switchState = (state === 'on' ? 'off' : 'on');
  var self = this;

  //  Pull power high
  if (self.powerState === switchState) {
    if (DEBUG) {
      console.log('high');
    }
    self.onOff.output().high();
    setTimeout(function backLow() {
      if (DEBUG) {
        console.log('low');
      }
      self.onOff.low();
      //  Pull power low
      if (self.powerState === switchState) {
        //  Set a timeout for it to have time to turn on and start sending
        setTimeout(callback, 500);
      }
    }, 250);
  } else if (callback) {
    callback();
  }
};

GPS.prototype.beginDecoding = function (callback) {
  /*
  After making contact with the A2235-H, start decoging its NMEA messages to
  get information from the GPS satellites

  Arg
    callback
      Callback function
  */
  var self = this;
  //  Eventually replace this with stream packetizing... sorry Kolker
  //  Initializer our packetizer
  var packetizer = new Packetizer(this.uart);
  //  Tell it to start packetizing
  packetizer.packetize();
  //  When we get a packet
  packetizer.on('packet', function (packet) {
    if (DEBUG) {
      console.log('  Packet\t', packet);
    }
    //  Make sure this is a valid packet
    if (packet[0] === '$') {
      //  Parse it
      var datum = nmea.parse(packet);

      if (DEBUG) {  //  pretty print
        console.log('    Got Data:');
        Object.keys(datum).forEach(function (key) {
          console.log('     ', key, '\n       ', datum[key]);
          });
        console.log();
      }
      //  If sucessful, emit the parsed NMEA object by its type
      if (datum) {
        setImmediate(function () {
          //  Emit the packet by its type
          self.emit(datum.type, datum);
          //  Emit coordinates
          self.emitCoordinates(datum);
          //  Ditto for altitude
          self.emitAltitude(datum);
          //  Do whatever else the user maps to specific attributes
          self.executeCallbacks(datum);
        });
      }
    }
  });

  if (callback) {
    callback();
  }
};

GPS.prototype._switchToNMEA9800 = function (callback) {
  /*
  The A2235-H has been configured in hardware to use UART, but we need to send
  it this command so that it gives us NMEA messages as opposed to SiRF binary.

  Arg
    callback
      Callback function
  */
  //  Configure GPS baud rate to 9600, talk in NMEA
  var characters = new Buffer([0xA0, 0xA2, 0x00, 0x18, 0x81, 0x02, 0x01, 0x01,
    0x00, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x25, 0x80, 0x01, 0x3A, 0xB0, 0xB3]);

  //  Write the message
  this.uart.write(characters);

  //  Reset UART baud rate
  this.uart = this.hardware.UART({baudrate : 9600});

  if (callback) {
    callback();
  }
};

GPS.prototype.setCoordinateFormat = function (format) {
  /*
  Configure how the module reports latitude and longitude

  Arg
    format
      'deg-min-sec' - Degrees + minutes + seconds
      'deg-dec' - Degrees and fractions thereof, as a decimal
      'deg-min-dec' - Degrees + minutes and fractions thereof, as a decimal
      'utm' - Report coordinates in the  Universal Transverse Mercator
        coordinate system. Not currently supported.
  */
  this.format = format;
  if (format === 'utm') {
    //  if at some point we want to go through this pain: http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm
    console.warn('UTM not currently supported. Voice your outrage to @selkeymoonbeam.');
  } else if (format != 'deg-min-sec' || format != 'deg-dec' ||
    format != 'deg-min-dec') {
    this.format = null;
    console.warn('Invalid format. Must be \'dig-min-sec\', \'deg-dec\', or \'deg-min-dec\'');
  } else {
    this.format = format;
  }
};

GPS.prototype.setCallback = function (attribute, cb, callback) {
  /*
  Set a callback function to be called for NMEA messages containing valid
  forms (!== undefined) of the given attribute.

  Notes
  - There can only be one callback for any given attribute
  - All messages are already emitted by their type (see beginDecoding)
  - Not all message attributes carry the same kind of data in all message types

  Args
    attribute
      The attribute for which the callback will be called
    cb
      Callback function to call with the NMEA message; args: err, parsed (an
        object with the contents of the NMEA message)
    callback
      This function's callback function
  */
  if (this.callbacks[attribute]) {
    console.warn('Overwriting existing callback for', attribute, 'with', cb);
  }
  this.callbacks[attribute] = cb;
  if (callback) {
    callback();
  }
};

GPS.prototype.removeCallback = function (attribute, callback) {
  /*
  Remove the callback function to be called for NMEA messages containing valid
  forms of the given attribute.
  Note that there can only be one callback for any given attribute.

  Args
    attribute
      The attribute for which the callback will be called. A string.
    callback
      Callback function
  */
  if (this.callbacks[attribute]) {
    delete this.callbacks[attribute];
  } else {
    console.warn('No callback existed for', attribute);
  }
  if (callback) {
    callback();
  }
};

GPS.prototype.executeCallbacks = function (parsed) {
  /*
  Pass the parsed data to the appropriate callback functions, as defined in
  this.callbacks. Called every time we get a NMEA message (see beginDecoding).

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (DEBUG) {
    console.log('executing callbacks for', Object.keys(self.callbacks));
  }
  Object.keys(self.callbacks).forEach(function (key) {
    if (Object.keys(parsed).indexOf(key) !== -1) {  //  Is the key there?
      setImmediate(function (err) {
        self.callbacks[key](err, parsed);
      });
    }
  });
};

GPS.prototype.emitCoordinates = function (parsed) {
  /*
  Format and emit the coordinates in parsed NMEA message

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (parsed.latPole !== '' && parsed.lonPole !== '' &&
    parsed.lon !== undefined && parsed.lat !== undefined) {
    var latPole = parsed.latPole;
    var lonPole = parsed.lonPole;
    var lat = parsed.lat;
    var lon = parsed.lon;
    var dec = lat.indexOf('.');
    var latDeg = parseFloat(lat.slice(0, dec-2));
    var latMin = parseFloat(lat.slice(dec-2, lat.length));
    dec = lon.indexOf('.');
    var lonDeg = parseFloat(lon.slice(0, dec-2));
    var lonMin = parseFloat(lon.slice(dec-2, lon.length));
    var longitude;
    var latitude;
    var latSec;
    var lonSec;

    if (self.format === 'deg-min-sec') {
      latSec = parseFloat(latMin.toString().split('.')[1] * 0.6);
      latMin = parseInt(latMin.toString().split('.')[0]);

      lonSec = parseFloat(lonMin.toString().split('.')[1] * 0.6);
      lonMin = parseInt(lonMin.toString().split('.')[0]);

      latitude = [latDeg, latMin, latSec, latPole];
      longitude = [lonDeg, lonMin, lonSec, lonPole];
    } else if (self.format === 'deg-dec') {
      lat = latDeg + (latMin / 60);
      lon = lonDeg + (lonMin / 60);

      latitude = [lat, latPole];
      longitude = [lon, lonPole];
    } else {
      latitude = [latDeg, latMin, latPole];
      longitude = [lonDeg, lonMin, lonPole];
    }
    var coordinates = {lat: latitude, lon: longitude,
      timestamp: parseFloat(parsed.timestamp)};

    setImmediate(function () {
      self.emit('coordinates', coordinates);
    });
  }
};

GPS.prototype.emitAltitude = function (parsed) {
  /*
  Emit the altitude in the given parsed NMEA message. Units are always meters.

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (parsed.alt !== undefined) {

    parsed.alt = parseInt(parsed.alt);

    setImmediate(function () {
      self.emit('altitude', {alt: parsed.alt,
        timestamp: parseFloat(parsed.timestamp)});
    });
  }
};

// //  GPS.prototype.geofence = function (minCoordinates, maxCoordinates) {
// // 	//  takes in coordinates, draws a rectangle from minCoordinates to maxCoordinates
// // 	//  returns boolean 'inRange' which is true when coordinates are in the rectangle
// // 	var buffer = this.cached;
// // 	var inRange = false;
// // 	if ((minCoordinates.lat.length === 2) && (maxCoordinates.lat.length === 2)) {
// // 		if (minCoordinates.lat[1] === 'S') {
// // 			minLat = -minCoordinates.lat[0];
// // 		} else {minLat = minCoordinates.lat[0]}
// // 		if (minCoordinates.lon[1] === 'W') {
// // 			minLon = -minCoordinates.lon[0];
// // 		} else {minLon = minCoordinates.lon[0]}
// // 		if (maxCoordinates.lat[1] === 'S') {
// // 			maxLat = -maxCoordinates.lat[0];
// // 		} else {maxLat = maxCoordinates.lat[0]}
// // 		if (maxCoordinates.lon[1] === 'W') {
// // 			maxLon = -maxCoordinates.lon[0];
// // 		} else {maxLon = maxCoordinates.lon[0]}

// // 		//get current coordinates
// // 		currentCoords = this.getCoordinates(this.cached);
// // 		if (currentCoords != 'no navigation data in buffer') {
// // 			if (currentCoords.lat[1] === 'S') {
// // 				currentLat = -currentCoords.lat[0];
// // 			} else {currentLat = currentCoords.lat[0]}
// // 			if (currentCoords.lon[1] === 'W') {
// // 				currentLon = -currentCoords.lon[0];
// // 			} else {currentLon = currentCoords.lon[0]}

// // 			//compare current coordinates with geofence
// // 			if ((currentLat > minLat) && (currentLat < maxLat) && (currentLon > minLon) && (currentLon < maxLon)) {
// // 				inRange = true;
// // 			} else {inRange = false}
// // 			var timestamp = currentCoords.timestamp;
// // 			return {inRange: inRange, timestamp: timestamp}
// // 		} else {return 'no position data'}
// // 	} else {return 'please use deg-dec coordinates'}
// // }

var connect = function (hardware) {
	return new GPS(hardware);
};

module.exports.connect = connect;
module.exports.GPS = GPS;
<commit_msg>index ready for pull<commit_after>var util = require('util');
var EventEmitter = require('events').EventEmitter;
var nmea = require('nmea');
var Packetizer = require('./lib/packetizer');

var DEBUG = false;  //  Set to true for debug console logs

var GPS = function (hardware, callback) {
  /*
  Constructor

  Args
    hardware
      The Tessel port to use
    callback
      Callback function
  */
  var self = this;
  self.hardware = hardware;
  self.onOff = self.hardware.gpio(3);
  self.powerState = 'off';
  self.timeoutDuration = 10*1000;
  self.format = 'deg-min-dec';
  //  A collection of attributes and callback functions. See set/removeCallback.
  self.callbacks = {};

  //  Turn the module on
  self.initialPowerSequence(function (err) {
    if (!err) {
      //  Once we are on, emit the connected event
      self.beginDecoding(function () {

        setImmediate(function () {
          self.emit('ready');
        });
      });
    } else {
      setImmediate(function () {
        self.emit('error', err);
      });
    }
    if (callback) {
      callback();
    }
  });
};

util.inherits(GPS, EventEmitter);

GPS.prototype.initialPowerSequence = function (callback) {
  /*
  Turn on and establish contact with the A2235-H GPS module

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  //  Tell Tessel to start UART at GPS baud rate
  this.uart = this.hardware.UART({baudrate : 115200});

  var noReceiveTimeout;

  function waitForData () {
    //  Remove this listener when we hear something (anything) from the GPS
    self.uart.removeListener('data', waitForData);

    clearTimeout(noReceiveTimeout);

    //  And note that we are on
    self.powerState = 'on';

    //  Tell the A2235-H that we want it to give us NMEA strings over UART
    self._switchToNMEA9800(callback);
  }

  function noDataRecieved () {
    //  Remove the listener for any data
    self.uart.removeListener('data', waitForData);
    //  Clear the timeout
    clearTimeout(noReceiveTimeout);
    //  Call the callback
    if (callback) {
      callback(new Error('Unable to connect to module...'));
    }
  }

  /*
  Wait for a second to see if we get data. If we do, call callback;
  If we don't, toggle power and set timeout again
  If we still don't get it, something bigger is wrong
  */

  //  This event listener will wait for valid data to note that we are on
  self.uart.once('data', function (data) {
    waitForData(data);
  });

  //  Set the timeout to try to turn on if not already
  noReceiveTimeout = setTimeout(function alreadyOn() {
    //  Try to turn on
    self.powerOn(function () {
      //  If it's still not on
      if (DEBUG) {
        console.log('state after power cycle:', self.powerState);
      }
      if (self.powerState === 'off') {
        //  Set the timeout once more
        if (DEBUG) {
          console.log('Trying once more...');
        }
        noReceiveTimeout = setTimeout(function () {
          //  If we still didn't get anything, fail the connect
          noDataRecieved();
        }, 1000);
      }
    });
  }, 1000);
};

GPS.prototype.powerOn = function (callback) {
  /*
  Try to turn the power on. Note that the A2235-H responds to a pulse, not the
  state of the power pin (it toggles).

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  self.power('on', function () {
    setImmediate(function () {
      self.emit('powerOn');
    });
    if (callback) {
      callback();
    }
  });
};

GPS.prototype.powerOff = function (callback) {
  /*
  Try to turn the power off. Note that the A2235-H responds to a pulse, not the
  state of the power pin (it toggles).

  Arg
    callback
      Callback function; arg: err
  */
  var self = this;
  self.power('off', function () {
    setImmediate(function () {
      self.emit('powerOff');
    });
    if (callback) {
      callback();
    }
  });
};

GPS.prototype.power = function (state, callback) {
  /*
  Toggle the power pin of the A2235-H (attached to hardware.gpio[3]). Assumes
  the module knows what power state it is in.

  Args
    state
      'on' - turn the power on
      'off' - turn the power off
    callback
      Callback function
  */
  //  We need to switch from this state to the given state
  var switchState = (state === 'on' ? 'off' : 'on');
  var self = this;

  //  Pull power high
  if (self.powerState === switchState) {
    if (DEBUG) {
      console.log('high');
    }
    self.onOff.output().high();
    setTimeout(function backLow() {
      if (DEBUG) {
        console.log('low');
      }
      self.onOff.low();
      //  Pull power low
      if (self.powerState === switchState) {
        //  Set a timeout for it to have time to turn on and start sending
        setTimeout(callback, 500);
      }
    }, 250);
  } else if (callback) {
    callback();
  }
};

GPS.prototype.beginDecoding = function (callback) {
  /*
  After making contact with the A2235-H, start decoging its NMEA messages to
  get information from the GPS satellites

  Arg
    callback
      Callback function
  */
  var self = this;
  //  Eventually replace this with stream packetizing... sorry Kolker
  //  Initializer our packetizer
  var packetizer = new Packetizer(this.uart);
  //  Tell it to start packetizing
  packetizer.packetize();
  //  When we get a packet
  packetizer.on('packet', function (packet) {
    if (DEBUG) {
      console.log('  Packet\t', packet);
    }
    //  Make sure this is a valid packet
    if (packet[0] === '$') {
      //  Parse it
      var datum = nmea.parse(packet);

      if (DEBUG) {  //  pretty print
        console.log('    Got Data:');
        Object.keys(datum).forEach(function (key) {
          console.log('     ', key, '\n       ', datum[key]);
          });
        console.log();
      }
      //  If sucessful, emit the parsed NMEA object by its type
      if (datum) {
        setImmediate(function () {
          //  Emit the packet by its type
          self.emit(datum.type, datum);
          //  Emit coordinates
          self.emitCoordinates(datum);
          //  Ditto for altitude
          self.emitAltitude(datum);
          //  Do whatever else the user maps to specific attributes
          self.executeCallbacks(datum);
        });
      }
    }
  });

  if (callback) {
    callback();
  }
};

GPS.prototype._switchToNMEA9800 = function (callback) {
  /*
  The A2235-H has been configured in hardware to use UART, but we need to send
  it this command so that it gives us NMEA messages as opposed to SiRF binary.

  Arg
    callback
      Callback function
  */
  //  Configure GPS baud rate to 9600, talk in NMEA
  var characters = new Buffer([0xA0, 0xA2, 0x00, 0x18, 0x81, 0x02, 0x01, 0x01,
    0x00, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01,
    0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x25, 0x80, 0x01, 0x3A, 0xB0, 0xB3]);

  //  Write the message
  this.uart.write(characters);

  //  Reset UART baud rate
  this.uart = this.hardware.UART({baudrate : 9600});

  if (callback) {
    callback();
  }
};

GPS.prototype.setCoordinateFormat = function (format) {
  /*
  Configure how the module reports latitude and longitude

  Arg
    format
      'deg-min-sec' - Degrees + minutes + seconds
      'deg-dec' - Degrees and fractions thereof, as a decimal
      'deg-min-dec' - Degrees + minutes and fractions thereof, as a decimal
      'utm' - Report coordinates in the  Universal Transverse Mercator
        coordinate system. Not currently supported.
  */
  this.format = format;
  if (format === 'utm') {
    //  if at some point we want to go through this pain: http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm
    console.warn('UTM not currently supported. Voice your outrage to @selkeymoonbeam.');
  } else if (format != 'deg-min-sec' || format != 'deg-dec' ||
    format != 'deg-min-dec') {
    this.format = null;
    console.warn('Invalid format. Must be \'dig-min-sec\', \'deg-dec\', or \'deg-min-dec\'');
  } else {
    this.format = format;
  }
};

GPS.prototype.setCallback = function (attribute, cb, callback) {
  /*
  Set a callback function to be called for NMEA messages containing valid
  forms (!== undefined) of the given attribute.

  Notes
  - There can only be one callback for any given attribute
  - All messages are already emitted by their type (see beginDecoding)
  - Not all message attributes carry the same kind of data in all message types

  Args
    attribute
      The attribute for which the callback will be called
    cb
      Callback function to call with the NMEA message; args: err, parsed (an
        object with the contents of the NMEA message)
    callback
      This function's callback function
  */
  if (this.callbacks[attribute]) {
    console.warn('Overwriting existing callback for', attribute, 'with', cb);
  }
  this.callbacks[attribute] = cb;
  if (callback) {
    callback();
  }
};

GPS.prototype.removeCallback = function (attribute, callback) {
  /*
  Remove the callback function to be called for NMEA messages containing valid
  forms of the given attribute.
  Note that there can only be one callback for any given attribute.

  Args
    attribute
      The attribute for which the callback will be called. A string.
    callback
      Callback function
  */
  if (this.callbacks[attribute]) {
    delete this.callbacks[attribute];
  } else {
    console.warn('No callback existed for', attribute);
  }
  if (callback) {
    callback();
  }
};

GPS.prototype.executeCallbacks = function (parsed) {
  /*
  Pass the parsed data to the appropriate callback functions, as defined in
  this.callbacks. Called every time we get a NMEA message (see beginDecoding).

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (DEBUG) {
    console.log('executing callbacks for', Object.keys(self.callbacks));
  }
  Object.keys(self.callbacks).forEach(function (key) {
    if (Object.keys(parsed).indexOf(key) !== -1) {  //  Is the key there?
      setImmediate(function (err) {
        self.callbacks[key](err, parsed);
      });
    }
  });
};

GPS.prototype.emitCoordinates = function (parsed) {
  /*
  Format and emit the coordinates in parsed NMEA message

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (parsed.latPole !== '' && parsed.lonPole !== '' &&
    parsed.lon !== undefined && parsed.lat !== undefined) {
    var latPole = parsed.latPole;
    var lonPole = parsed.lonPole;
    var lat = parsed.lat;
    var lon = parsed.lon;
    var dec = lat.indexOf('.');
    var latDeg = parseFloat(lat.slice(0, dec-2));
    var latMin = parseFloat(lat.slice(dec-2, lat.length));
    dec = lon.indexOf('.');
    var lonDeg = parseFloat(lon.slice(0, dec-2));
    var lonMin = parseFloat(lon.slice(dec-2, lon.length));
    var longitude;
    var latitude;
    var latSec;
    var lonSec;

    if (self.format === 'deg-min-sec') {
      latSec = parseFloat(latMin.toString().split('.')[1] * 0.6);
      latMin = parseInt(latMin.toString().split('.')[0]);

      lonSec = parseFloat(lonMin.toString().split('.')[1] * 0.6);
      lonMin = parseInt(lonMin.toString().split('.')[0]);

      latitude = [latDeg, latMin, latSec, latPole];
      longitude = [lonDeg, lonMin, lonSec, lonPole];
    } else if (self.format === 'deg-dec') {
      lat = latDeg + (latMin / 60);
      lon = lonDeg + (lonMin / 60);

      latitude = [lat, latPole];
      longitude = [lon, lonPole];
    } else {
      latitude = [latDeg, latMin, latPole];
      longitude = [lonDeg, lonMin, lonPole];
    }
    var coordinates = {lat: latitude, lon: longitude,
      timestamp: parseFloat(parsed.timestamp)};

    setImmediate(function () {
      self.emit('coordinates', coordinates);
    });
  }
};

GPS.prototype.emitAltitude = function (parsed) {
  /*
  Emit the altitude in the given parsed NMEA message. Units are always meters.

  Arg
    parsed
      The output of nmea.parse(): an object containing the parsed NEMA message
  */
  var self = this;
  if (parsed.alt !== undefined) {

    parsed.alt = parseInt(parsed.alt);

    setImmediate(function () {
      self.emit('altitude', {alt: parsed.alt,
        timestamp: parseFloat(parsed.timestamp)});
    });
  }
};

var connect = function (hardware) {
	return new GPS(hardware);
};

module.exports.connect = connect;
module.exports.GPS = GPS;
<|endoftext|>


<commit_before>const assert = require('assert');
const async = require('async');
const fs = require('fs');
const path = require('path');
const Dgeni = require('dgeni');
const ejs = require('ejs');
const basepath = process.cwd();
const NgDocsBuilder = require('./lib/NgDocsBuilder');

var swankyNgdocs = function (page, meta, cb) {
  ngDocsBuilder = new NgDocsBuilder(page);

  var packages = [ngDocsBuilder.Package];

  var dgeni = new Dgeni(packages);

  dgeni.generate().then(function (docs) {
    page.processorOutput = [];

    // Render each doc here
    docs.forEach((doc, index) => {

      var partialTemplate;

      // Read template location from Swanky config
      if (page.processor.ngdocs && page.processor.ngdocs.hasOwnProperty('templates')) {
        partialTemplate = path.join(basepath, `${page.processor.ngdocs.templates}/${doc.docType}.template.ejs`);
      } else {
        partialTemplate = path.join(__dirname, `./templates/api/${doc.docType}.template.ejs`);
      }

      var str = fs.readFileSync(partialTemplate, 'utf-8');

      var options = {
        filename: partialTemplate,
        cache: true
      };

      page.processorOutput.push(ejs.compile(str, options)({
        doc: doc,
        styles: meta.cssMap
      }));

    });

    cb(null);
  });
};

module.exports = swankyNgdocs;
<commit_msg>fix(build): add template to fileDeps array<commit_after>const assert = require('assert');
const async = require('async');
const fs = require('fs');
const path = require('path');
const Dgeni = require('dgeni');
const ejs = require('ejs');
const basepath = process.cwd();
const NgDocsBuilder = require('./lib/NgDocsBuilder');

var swankyNgdocs = function (page, meta, cb) {
  ngDocsBuilder = new NgDocsBuilder(page);

  var packages = [ngDocsBuilder.Package];

  var dgeni = new Dgeni(packages);

  dgeni.generate().then(function (docs) {
    page.processorOutput = [];

    // Render each doc here
    docs.forEach((doc, index) => {

      var partialTemplate;

      // Read template location from Swanky config
      if (page.processor.ngdocs && page.processor.ngdocs.hasOwnProperty('templates')) {
        partialTemplate = path.join(basepath,
          `${page.processor.ngdocs.templates}/${doc.docType}.template.ejs`);
      } else {
        partialTemplate = path.join(__dirname, `./templates/api/${doc.docType}.template.ejs`);
      }

      var str;

      try {
        str = fs.readFileSync(partialTemplate, 'utf-8');
      } catch (err) {
        console.log(err);
        process.exit(1);
      }

      // Add file deps for live reload / webpack implementation
      page.fileDependencies.push(partialTemplate);

      var options = {
        filename: partialTemplate,
        cache: true
      };

      page.processorOutput.push(ejs.compile(str, options)({
        doc: doc,
        styles: meta.cssMap
      }));

    });

    cb(null);
  });
};

module.exports = swankyNgdocs;
<|endoftext|>


<commit_before>'use strict';

const PhantomJs = require('phantomjs-prebuilt');
const Png = require('pngjs').PNG;
const RgbQuant = require('rgbquant');
const Stream = require('stream');
const UrlValidator = require('url-validator');

const PHANTOM_ARGS = {
  url: 'http://tkm.io/',
  viewSize: {
    width: 1920,
    height: 1080,
  },
};

function parseJson(str) {
  try {
    const o = JSON.parse(str);
    if (o && typeof o === 'object') {
      return o;
    }
  } catch (e) {
    // Continue regardless
  }

  return undefined;
}

function parseMsg(complete, raw) {
  const msg = parseJson(raw);

  if (msg && msg.status && msg.body) {
    if (msg.status === 'ok') {
      return msg;
    }

    complete(`Error: "${msg.body}"`);
  }

  return undefined;
}

function final(complete, palette) {
  const response = {
    statusCode: palette ? 200 : 500,
    headers: {
      'access-control-allow-origin': '*'
    },
    body: palette ? JSON.stringify({ palette: palette }) : '',
  };

  complete(null, response);
}

function png2palette(complete, data) {
  const png = new Uint32Array(data);

  // Turn array of {R, G, B, A} into array of 32 bit pixels
  const pixels = png.reduce((acc, val, index) => {
    const pos = (index % 4);

    const pixelIndex = ((index - pos) / 4);
    const pixel = acc[pixelIndex];

    const color = png[index] & 0xff;
    const shiftBits = 8 * pos;

    const updated = pixel | (color << shiftBits);
    acc.set([updated], pixelIndex);

    return acc;
  }, new Uint32Array(data.length / 4));

  const q = new RgbQuant({ colors: 8 });
  q.sample(pixels);

  const palette = q.palette(true);

  final(complete, palette);
}

function phantomHandler(complete, raw) {
  const msg = parseMsg(complete, raw);
  if (!msg) {
    console.log('Phantom: "%s"', raw);
    return;
  }

  const screenshot = new Buffer(msg.body, 'base64');
  const pngStream = new Stream.PassThrough();

  pngStream.end(screenshot);

  pngStream.pipe(new Png({ filterType: 4 }))
    .on('error', complete)
    .on('parsed', (data) => {
      png2palette(complete, data);
    });
}

function urlFromEvent(event) {
  if (!event || !event.queryStringParameters || !event.queryStringParameters.url) {
    return false;
  }

  return UrlValidator(event.queryStringParameters.url);
}

exports.handler = function (event, context, callback) {
  const urlParam = urlFromEvent(event);
  if (!urlParam) {
    callback('Bad URL');
    return;
  }

  const phantomArgs = Object.assign({}, PHANTOM_ARGS, { url: urlParam });
  const phantom = PhantomJs.exec('phjs-main.js', JSON.stringify(phantomArgs));
  let msgBuffer = '';

  phantom.stdout.on('data', (msg) => { msgBuffer = msgBuffer.concat(String(msg)); });
  phantom.stderr.on('data', err => callback(err));
  phantom.on('exit', (code) => {
    if (code !== 0) console.log(`Phantom exited with ${code}`);
  });

  phantom.on('close', (code) => {
    if (code !== 0) console.log(`Phantom closed with ${code}`);

    phantomHandler(callback, msgBuffer);
  });
};
<commit_msg>Better Phantom message handling & linting cleanup<commit_after>'use strict';

const PhantomJs = require('phantomjs-prebuilt');
const Png = require('pngjs').PNG;
const RgbQuant = require('rgbquant');
const Stream = require('stream');
const UrlValidator = require('url-validator');

const PHANTOM_ARGS = {
  url: 'http://tkm.io/',
  viewSize: {
    width: 1920,
    height: 1080,
  },
};

function parseJson(str) {
  try {
    const o = JSON.parse(str);
    if (o && typeof o === 'object') {
      return o;
    }
  } catch (e) {
    // Continue regardless
  }

  return undefined;
}

function parseMsg(complete, raw) {
  const msg = parseJson(raw);

  if (msg && msg.status && msg.body) {
    if (msg.status === 'ok') {
      return msg;
    }

    complete(`Error: "${msg.body}"`);
  }

  return undefined;
}

function final(complete, palette) {
  const response = {
    statusCode: palette ? 200 : 500,
    headers: {
      'access-control-allow-origin': '*',
    },
    body: palette ? JSON.stringify({ palette }) : '',
  };

  complete(null, response);
}

function png2palette(complete, data) {
  const png = new Uint32Array(data);

  // Turn array of {R, G, B, A} into array of 32 bit pixels
  const pixels = png.reduce((acc, val, index) => {
    const pos = (index % 4);

    const pixelIndex = ((index - pos) / 4);
    const pixel = acc[pixelIndex];

    const color = png[index] & 0xff;
    const shiftBits = 8 * pos;

    const updated = pixel | (color << shiftBits);
    acc.set([updated], pixelIndex);

    return acc;
  }, new Uint32Array(data.length / 4));

  const q = new RgbQuant({ colors: 8 });
  q.sample(pixels);

  const palette = q.palette(true);

  final(complete, palette);
}

function phantomHandler(complete, raw) {
  const msg = parseMsg(complete, raw);
  if (!msg) {
    console.log('Phantom: "%s"', raw);
    return;
  }

  const screenshot = new Buffer(msg.body, 'base64');
  const pngStream = new Stream.PassThrough();

  pngStream.end(screenshot);

  pngStream.pipe(new Png({ filterType: 4 }))
    .on('error', complete)
    .on('parsed', (data) => {
      png2palette(complete, data);
    });
}

function urlFromEvent(event) {
  if (!event || !event.queryStringParameters || !event.queryStringParameters.url) {
    return false;
  }

  return UrlValidator(event.queryStringParameters.url);
}

exports.handler = function (event, context, callback) {
  const urlParam = urlFromEvent(event);
  if (!urlParam) {
    callback('Bad URL');
    return;
  }

  const phantomArgs = Object.assign({}, PHANTOM_ARGS, { url: urlParam });
  const phantom = PhantomJs.exec('phjs-main.js', JSON.stringify(phantomArgs));
  let msgBuffer = '';

  phantom.stdout.on('data', (msg) => {
    msgBuffer = msgBuffer.concat(String(msg));
    phantomHandler(callback, msg);
  });

  phantom.stderr.on('data', err => callback(err));
  phantom.on('exit', (code) => {
    if (code !== 0) console.log(`Phantom exited with ${code}`);
  });

  phantom.on('close', (code) => {
    if (code !== 0) console.log(`Phantom closed with ${code}`);

    phantomHandler(callback, msgBuffer);
  });
};
<|endoftext|>