<commit_before>var bpiscreen = require('./lib/bpiscreen')
var config = require('./lib/globals-config')
var internalIp = require('internal-ip')
var publicIp = require('public-ip')
var os = require('os')
var numeral = require('numeral')
var exec = require('child_process').exec
var isOnline = require('is-online')
var Bleacon = require('bleacon')
var PeaconDB = require('./lib/peacon-db')

var events = require("events"),
	displayEvents = new events.EventEmitter()

var actualScreenX = 0, actualScreenY = 0
var screenIntervalId

var beaconHistory = []
var beaconHistoryCount = 0

// ----------------------------------------------------------------
// GET SCREEN TEXT
// ----------------------------------------------------------------
// this array will return the text from each of screen position
var updateScreen = [
	[
		// first screen, show simple message
		function() {
			updateDisplayMsg("Aguardando\nbeacons...")
		}
	],
	[
		// this screen will show the last seen beacons
		function() {
			// TODO list last beacons
			if(beaconHistoryCount == 0)
				updateDisplayMsg("Nenhum beacon\nencontrado")
			else if(beaconHistoryCount == 1)
				updateDisplayMsg("1 beacon\nencontrado")
			else
				updateDisplayMsg(beaconHistoryCount + " beacons\nencontrados")
		}
	],
	[
		// this screen will display the RPi statistics, such as load average,
		// CPU temp, public and internal IP address
		function() {
			// TODO Improve to rewrite only the second line
			updateLoadAverage()
			screenIntervalId = setInterval(updateLoadAverage, 1000)
		},
		function() {
			// TODO Improve to rewrite only the second line
			updateSysTemp()
			screenIntervalId = setInterval(updateSysTemp, 1000)
		},
		function() {
			//displayEvents.emit('updated', "IP Privado\n" + internalIp())
			updateDisplayMsg("IP Privado\n" + internalIp())
		},
		function() {
			updateDisplayMsg("IP Publico\nCarregando...")
			publicIp(function (err, ip) {
				if(!ip)
					updateDisplayMsg("IP Publico\nnao encontrado")
				else
					updateDisplayMsg("IP Publico\n" + ip)
			})
		}
	]
]

var updateLoadAverage = function() {
	updateDisplayMsg("Load average\n" +
		numeral(os.loadavg()[0]).format('0.00') + " " +
		numeral(os.loadavg()[1]).format('0.00') + " " +
		numeral(os.loadavg()[2]).format('0.00'))
}

var updateSysTemp = function() {
	exec("cat /sys/class/thermal/thermal_zone0/temp", function (error, stdout, stderr) {
		if (error !== null) {
			console.log('exec error: ' + error)
		} else {
			// gets cpu temp and sends to callback function
			var temp = parseFloat(stdout) / 1000
			updateDisplayMsg("CPU Temp\n" + temp)
		}
	})
}

var updateDisplayMsg = function(message) {
	bpiscreen.write.lcd(message)
}
// ----------------------------------------------------------------
// END GET SCREEN TEXT
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// CHANGE DISPLAY SCREEN
// ----------------------------------------------------------------
var changeScreen = function(opts) {
	opts = opts || {}
	clearInterval(screenIntervalId)

	var x = opts.screenX || false
	var y = opts.screenY || false
	var next = opts.next || false

	if(x) {
		if(next)
			actualScreenX++
		else
			actualScreenX--
	} else if(y) {
		if(next)
			actualScreenY++
		else
			actualScreenX--
	}

	if(actualScreenX < 0)
	{
		actualScreenX = updateScreen.length - 1
	}
	else if(actualScreenX >= updateScreen.length)
	{
		actualScreenX = 0
	}
	if(actualScreenY < 0)
	{
		actualScreenY = updateScreen[actualScreenX].length - 1
	}
	else if(actualScreenY >= updateScreen[actualScreenX].length)
	{
		actualScreenY = 0
	}

	bpiscreen.write.led(config.INTERFACELED1, Number(actualScreenX == 0))
	bpiscreen.write.led(config.INTERFACELED2, Number(actualScreenX == 1))
	bpiscreen.write.led(config.INTERFACELED3, Number(actualScreenX == 2))

	updateScreen[actualScreenX][actualScreenY]()
	//displayEvents.emit('screenUpdated' + actualScreenX)
}
// ----------------------------------------------------------------
// END CHANGE DISPLAY SCREEN
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// BUTTON CLICK CALLBACK
// ----------------------------------------------------------------
var leftBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenX:true, next:false })
}
var middleBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenY:true, next:true })
}
var rightBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenX:true, next:true })
}
// ----------------------------------------------------------------
// END BUTTON CLICK CALLBACK
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// CHECK INTERNET CONNECTIVITY (YELLOW LED)
// ----------------------------------------------------------------
var checkInternet = function(){
	isOnline(function(err, online) {
		bpiscreen.write.led(config.INTERNETLED, Number(online == true))
	})
}
// ----------------------------------------------------------------
// END CHECK INTERNET CONNECTIVITY (YELLOW LED)
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// BEACON IDENTIFICATION
// ----------------------------------------------------------------

// save all beacons on range for a limited time
var beaconsOnRange = [ ]

// time between beacon range in and out - in ms
var beaconTime = 3000

// find a beacon at the original array
var findBeaconLocally = function(uuid, major, minor) {
	var i = 0, len = beaconsOnRange.length
	for (; i < len; ++i) {
		if ( beaconsOnRange[i].uuid == uuid &&
			beaconsOnRange[i].major == major &&
			beaconsOnRange[i].minor == minor )
			return beaconsOnRange[i]
	}
	return null
}

// creates a new beacon item to insert on the range array
var newBeacon = function(){
	var newB = {
		"uuid": "",
		"major": "",
		"minor": "",
		"name": "",
		"initialDate": Date.now(),
		"finalDate": "",
		"funcTimeout": ""
	}
	return newB
}

// timeout callback to remove a beacon from the range array
var beaconTimeoutCallback = function(beacon) {
	beacon.finalDate = Date.now()

	var index = beaconsOnRange.indexOf(beacon)
	if (index > -1) {
		beaconsOnRange.splice(index, 1)
	}

	var beaconToSaveDB = {
		"uuid": beacon.uuid,
		"major": beacon.major,
		"minor": beacon.minor,
		"total": ( (beacon.finalDate - beacon.initialDate - beaconTime) / 1000 )
	}

	PeaconDB.saveBeaconFound(beaconToSaveDB)

	/*var beaconToSaveHistory = {
		"uuid": beacon.uuid,
		"major": beacon.major,
		"minor": beacon.minor,
		"name": beacon.name
	}

	beaconHistory.push(beaconToSaveHistory)*/

	beaconHistoryCount++

	var currentBeacon = beaconHistoryCount

	updateScreen[1].push(function(){
		if(!beacon.name)
			updateDisplayMsg(currentBeacon + " de " + beaconHistoryCount + "\nDesconhecido")
		else
			updateDisplayMsg(currentBeacon + " de " + beaconHistoryCount + "\n" + beacon.name)
	})

	// TODO - SHOW ON SCREEN

	bpiscreen.write.led(config.BEACONLED, Number(beaconsOnRange.length > 0))
}

// callback when a beacon is discovered
Bleacon.on('discover', function(bleacon) {

	console.log("Bleacon Discover")

	var findB = findBeaconLocally(bleacon.uuid, bleacon.major, bleacon.minor)

	if (!findB) {
		findB = newBeacon()
		findB.uuid = bleacon.uuid
		findB.major = bleacon.major
		findB.minor = bleacon.minor
		PeaconDB.searchSavedBeacon(bleacon, function(err, beaconFound){
			if(!beaconFound.name)
				findB.name = null
			else
				findB.name = beaconFound.name
		})
		beaconsOnRange.push(findB)
	}

	// stops the older timeout
	clearTimeout(findB.funcTimeout)

	findB.funcTimeout = setTimeout(function() {
		console.log("beaconTimeoutCallback")
		beaconTimeoutCallback(findB)
	}, beaconTime)

    /*console.log("UUID: " + bleacon.uuid + " " +
		"Major: " + bleacon.major + " " +
		"Minor: " + bleacon.minor + " " +
		"RSSI: " + bleacon.rssi + " " +
		"Power: " + bleacon.measuredPower)*/

	bpiscreen.write.led(config.BEACONLED, Number(beaconsOnRange.length > 0))
})
// ----------------------------------------------------------------
// END BEACON IDENTIFICATION
// ----------------------------------------------------------------

// run shell command
// got from http://stackoverflow.com/questions/14458508/node-js-shell-command-execution
var run_cmd = function (cmd, args, callBack) {
    var spawn = require('child_process').spawn
    var child = spawn(cmd, args)
    var resp = ""

    child.stdout.on('data', function (buffer) { resp += buffer.toString() })
    child.stdout.on('end', function() { callBack (resp) })
}

// ----------------------------------------------------------------
// STARTING SCRIPTS
// ----------------------------------------------------------------
var start = function() {
	bpiscreen.start()

	bpiscreen.write.led(config.POWERLED, 1)
	bpiscreen.write.led(config.INTERNETLED, 0)
	bpiscreen.write.led(config.BEACONLED, 0)

	bpiscreen.write.led(config.INTERFACELED1, 0)
	bpiscreen.write.led(config.INTERFACELED2, 0)
	bpiscreen.write.led(config.INTERFACELED3, 0)

	bpiscreen.watch.button(config.LEFTBTN, leftBtnClick)
	bpiscreen.watch.button(config.MIDDLEBTN, middleBtnClick)
	bpiscreen.watch.button(config.RIGHTBTN, rightBtnClick)

	changeScreen()
	//displayEvents.emit('changed')

	// restarting hci0
	// this is a bug from my cheap ORICO BTA adapter
	run_cmd( "sudo hciconfig hci0 down", [], function(text) {
		run_cmd( "sudo hciconfig hci0 up", [], function(text) {

		})
	})

	// check internet connectivity every minute
	checkInternet()
	setInterval(checkInternet, 60000)

	Bleacon.startScanning() // scan for any bleacons

	PeaconDB.startDB() // start all databases
}

start()
// ----------------------------------------------------------------
// END STARTING SCRIPTS
// ----------------------------------------------------------------
<commit_msg>Changing first screen message<commit_after>var bpiscreen = require('./lib/bpiscreen')
var config = require('./lib/globals-config')
var internalIp = require('internal-ip')
var publicIp = require('public-ip')
var os = require('os')
var numeral = require('numeral')
var exec = require('child_process').exec
var isOnline = require('is-online')
var Bleacon = require('bleacon')
var PeaconDB = require('./lib/peacon-db')

var events = require("events"),
	displayEvents = new events.EventEmitter()

var actualScreenX = 0, actualScreenY = 0
var screenIntervalId

var beaconHistory = []
var beaconHistoryCount = 0

// ----------------------------------------------------------------
// GET SCREEN TEXT
// ----------------------------------------------------------------
// this array will return the text from each of screen position
var updateScreen = [
	[
		// first screen, show simple message
		function() {
			updateDisplayMsg("Aguardando\nbeacons...")
		}
	],
	[
		// this screen will show the last seen beacons
		function() {
			// TODO list last beacons
			if(beaconHistoryCount == 0)
				updateDisplayMsg("Nenhum beacon\nencontrado")
			else if(beaconHistoryCount == 1)
				updateDisplayMsg("1 beacon\nencontrado")
			else
				updateDisplayMsg(beaconHistoryCount + " beacons\nencontrados")
		}
	],
	[
		// this screen will display the RPi statistics, such as load average,
		// CPU temp, public and internal IP address
		function() {
			// TODO Improve to rewrite only the second line
			updateLoadAverage()
			screenIntervalId = setInterval(updateLoadAverage, 1000)
		},
		function() {
			// TODO Improve to rewrite only the second line
			updateSysTemp()
			screenIntervalId = setInterval(updateSysTemp, 1000)
		},
		function() {
			//displayEvents.emit('updated', "IP Privado\n" + internalIp())
			updateDisplayMsg("IP Privado\n" + internalIp())
		},
		function() {
			updateDisplayMsg("IP Publico\nCarregando...")
			publicIp(function (err, ip) {
				if(!ip)
					updateDisplayMsg("IP Publico\nnao encontrado")
				else
					updateDisplayMsg("IP Publico\n" + ip)
			})
		}
	]
]

var updateLoadAverage = function() {
	updateDisplayMsg("Load average\n" +
		numeral(os.loadavg()[0]).format('0.00') + " " +
		numeral(os.loadavg()[1]).format('0.00') + " " +
		numeral(os.loadavg()[2]).format('0.00'))
}

var updateSysTemp = function() {
	exec("cat /sys/class/thermal/thermal_zone0/temp", function (error, stdout, stderr) {
		if (error !== null) {
			console.log('exec error: ' + error)
		} else {
			// gets cpu temp and sends to callback function
			var temp = parseFloat(stdout) / 1000
			updateDisplayMsg("CPU Temp\n" + temp)
		}
	})
}

displayEvents.on("beacon-range-change", function(){

	if( (actualScreenX ==  0) && (actualScreenY == 0) ) {
		if(beaconsOnRange.length == 0)
			updateDisplayMsg("Aguardando\nbeacons...")
		else if(beaconsOnRange.length == 1)
			updateDisplayMsg("1 beacon\nencontrado...")
		else
			updateDisplayMsg(beaconsOnRange.length + " beacons\nencontrados...")
	}

})

var updateDisplayMsg = function(message) {
	bpiscreen.write.lcd(message)
}
// ----------------------------------------------------------------
// END GET SCREEN TEXT
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// CHANGE DISPLAY SCREEN
// ----------------------------------------------------------------
var changeScreen = function(opts) {
	opts = opts || {}
	clearInterval(screenIntervalId)

	var x = opts.screenX || false
	var y = opts.screenY || false
	var next = opts.next || false

	if(x) {
		if(next)
			actualScreenX++
		else
			actualScreenX--
	} else if(y) {
		if(next)
			actualScreenY++
		else
			actualScreenX--
	}

	if(actualScreenX < 0)
	{
		actualScreenX = updateScreen.length - 1
	}
	else if(actualScreenX >= updateScreen.length)
	{
		actualScreenX = 0
	}
	if(actualScreenY < 0)
	{
		actualScreenY = updateScreen[actualScreenX].length - 1
	}
	else if(actualScreenY >= updateScreen[actualScreenX].length)
	{
		actualScreenY = 0
	}

	bpiscreen.write.led(config.INTERFACELED1, Number(actualScreenX == 0))
	bpiscreen.write.led(config.INTERFACELED2, Number(actualScreenX == 1))
	bpiscreen.write.led(config.INTERFACELED3, Number(actualScreenX == 2))

	updateScreen[actualScreenX][actualScreenY]()
	//displayEvents.emit('screenUpdated' + actualScreenX)
}
// ----------------------------------------------------------------
// END CHANGE DISPLAY SCREEN
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// BUTTON CLICK CALLBACK
// ----------------------------------------------------------------
var leftBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenX:true, next:false })
}
var middleBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenY:true, next:true })
}
var rightBtnClick = function(){
	//displayEvents.emit('changed')
	changeScreen({ screenX:true, next:true })
}
// ----------------------------------------------------------------
// END BUTTON CLICK CALLBACK
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// CHECK INTERNET CONNECTIVITY (YELLOW LED)
// ----------------------------------------------------------------
var checkInternet = function(){
	isOnline(function(err, online) {
		bpiscreen.write.led(config.INTERNETLED, Number(online == true))
	})
}
// ----------------------------------------------------------------
// END CHECK INTERNET CONNECTIVITY (YELLOW LED)
// ----------------------------------------------------------------

// ----------------------------------------------------------------
// BEACON IDENTIFICATION
// ----------------------------------------------------------------

// save all beacons on range for a limited time
var beaconsOnRange = [ ]

// time between beacon range in and out - in ms
var beaconTime = 3000

// find a beacon at the original array
var findBeaconLocally = function(uuid, major, minor) {
	var i = 0, len = beaconsOnRange.length
	for (; i < len; ++i) {
		if ( beaconsOnRange[i].uuid == uuid &&
			beaconsOnRange[i].major == major &&
			beaconsOnRange[i].minor == minor )
			return beaconsOnRange[i]
	}
	return null
}

// creates a new beacon item to insert on the range array
var newBeacon = function(){
	var newB = {
		"uuid": "",
		"major": "",
		"minor": "",
		"name": "",
		"initialDate": Date.now(),
		"finalDate": "",
		"funcTimeout": ""
	}
	return newB
}

// timeout callback to remove a beacon from the range array
var beaconTimeoutCallback = function(beacon) {
	beacon.finalDate = Date.now()

	var index = beaconsOnRange.indexOf(beacon)
	if (index > -1) {
		beaconsOnRange.splice(index, 1)
	}

	displayEvents.emit("beacon-range-change")

	var beaconToSaveDB = {
		"uuid": beacon.uuid,
		"major": beacon.major,
		"minor": beacon.minor,
		"total": ( (beacon.finalDate - beacon.initialDate - beaconTime) / 1000 )
	}

	PeaconDB.saveBeaconFound(beaconToSaveDB)

	/*var beaconToSaveHistory = {
		"uuid": beacon.uuid,
		"major": beacon.major,
		"minor": beacon.minor,
		"name": beacon.name
	}

	beaconHistory.push(beaconToSaveHistory)*/

	beaconHistoryCount++

	var currentBeacon = beaconHistoryCount

	updateScreen[1].push(function(){
		if(!beacon.name)
			updateDisplayMsg(currentBeacon + " de " + beaconHistoryCount + "\nDesconhecido")
		else
			updateDisplayMsg(currentBeacon + " de " + beaconHistoryCount + "\n" + beacon.name)
	})

	// TODO - SHOW ON SCREEN

	bpiscreen.write.led(config.BEACONLED, Number(beaconsOnRange.length > 0))
}

// callback when a beacon is discovered
Bleacon.on('discover', function(bleacon) {

	console.log("Bleacon Discover")

	var findB = findBeaconLocally(bleacon.uuid, bleacon.major, bleacon.minor)

	if (!findB) {
		findB = newBeacon()
		findB.uuid = bleacon.uuid
		findB.major = bleacon.major
		findB.minor = bleacon.minor
		PeaconDB.searchSavedBeacon(bleacon, function(err, beaconFound){
			if(!beaconFound.name)
				findB.name = null
			else
				findB.name = beaconFound.name
		})
		beaconsOnRange.push(findB)
		displayEvents.emit("beacon-range-change")
	}

	// stops the older timeout
	clearTimeout(findB.funcTimeout)

	findB.funcTimeout = setTimeout(function() {
		console.log("beaconTimeoutCallback")
		beaconTimeoutCallback(findB)
	}, beaconTime)

    /*console.log("UUID: " + bleacon.uuid + " " +
		"Major: " + bleacon.major + " " +
		"Minor: " + bleacon.minor + " " +
		"RSSI: " + bleacon.rssi + " " +
		"Power: " + bleacon.measuredPower)*/

	bpiscreen.write.led(config.BEACONLED, Number(beaconsOnRange.length > 0))
})
// ----------------------------------------------------------------
// END BEACON IDENTIFICATION
// ----------------------------------------------------------------

// run shell command
// got from http://stackoverflow.com/questions/14458508/node-js-shell-command-execution
var run_cmd = function (cmd, args, callBack) {
    var spawn = require('child_process').spawn
    var child = spawn(cmd, args)
    var resp = ""

    child.stdout.on('data', function (buffer) { resp += buffer.toString() })
    child.stdout.on('end', function() { callBack (resp) })
}

// ----------------------------------------------------------------
// STARTING SCRIPTS
// ----------------------------------------------------------------
var start = function() {
	bpiscreen.start()

	bpiscreen.write.led(config.POWERLED, 1)
	bpiscreen.write.led(config.INTERNETLED, 0)
	bpiscreen.write.led(config.BEACONLED, 0)

	bpiscreen.write.led(config.INTERFACELED1, 0)
	bpiscreen.write.led(config.INTERFACELED2, 0)
	bpiscreen.write.led(config.INTERFACELED3, 0)

	bpiscreen.watch.button(config.LEFTBTN, leftBtnClick)
	bpiscreen.watch.button(config.MIDDLEBTN, middleBtnClick)
	bpiscreen.watch.button(config.RIGHTBTN, rightBtnClick)

	changeScreen()
	//displayEvents.emit('changed')

	// restarting hci0
	// this is a bug from my cheap ORICO BTA adapter
	run_cmd( "sudo hciconfig hci0 down", [], function(text) {
		run_cmd( "sudo hciconfig hci0 up", [], function(text) {

		})
	})

	// check internet connectivity every minute
	checkInternet()
	setInterval(checkInternet, 60000)

	Bleacon.startScanning() // scan for any bleacons

	PeaconDB.startDB() // start all databases
}

start()
// ----------------------------------------------------------------
// END STARTING SCRIPTS
// ----------------------------------------------------------------
<|endoftext|>


<commit_before>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter.stop = function () {
            emitter._stopped = true;
            emitter.emit('stop');
        };
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (emitter._stopped) return;
        if (err) return finish();
        emitter._seen[stat.ino || dir] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (emitter._stopped) return;
                if (err) return finish();
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
        emitter._seen = null;
    }

    function onreaddir (err, files) {
        if (emitter._stopped) return;
        emitter._pending --;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (emitter._stopped) return;
                if (err) check()
                else onstat(file, stat)
            });
        });
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino || file]) return check();
        emitter._seen[stat.ino || file] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (emitter._stopped) return;
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (emitter._stopped) return;
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<commit_msg>fix problem with walk for nested empty directories<commit_after>var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var path = require('path');

module.exports = function walk (dir, opts, emitter, dstat) {
    if (!opts) opts = {};
    var fdir = opts._original || dir;
    opts._original = undefined;

    if (!emitter) {
        emitter = new EventEmitter;
        emitter.stop = function () {
            emitter._stopped = true;
            emitter.emit('stop');
        };
        emitter._pending = 0;
        emitter._seen = {};
    }
    emitter._pending ++;

    if (dstat) {
        var stopped = false;
        emitter.emit('directory', fdir, dstat, function stop () {
            stopped = true;
        });
        emitter.emit('path', fdir, dstat);
        if (!stopped) fs.readdir(dir, onreaddir);
        else check()
    }
    else fs.lstat(dir, function onstat (err, stat) {
        if (emitter._stopped) return;
        if (err) return finish();
        emitter._seen[stat.ino || dir] = true;

        if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', fdir, stat);
            fs.readlink(dir, function (err, rfile) {
                if (emitter._stopped) return;
                if (err) return finish();
                var file_ = path.resolve(dir, rfile);
                emitter.emit('readlink', fdir, file_);
                fs.lstat(file_, onstat);
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
        else if (stat.isDirectory()) {
            var stopped = false;
            emitter.emit('directory', fdir, stat, function stop () {
                stopped = true;
            });
            emitter.emit('path', fdir, stat);
            if (!stopped) fs.readdir(dir, onreaddir);
            else check()
        }
        else {
            emitter.emit('file', fdir, stat);
            emitter.emit('path', fdir, stat);
            finish();
        }
    });

    return emitter;

    function check () {
        if (-- emitter._pending === 0) finish();
    }

    function finish () {
        emitter.emit('end');
        emitter._seen = null;
    }

    function onreaddir (err, files) {
        if (emitter._stopped) return;
        if (err) return check();

        files.forEach(function (rfile) {
            emitter._pending ++;
            var file = path.join(fdir, rfile);

            fs.lstat(file, function (err, stat) {
                if (emitter._stopped) return;
                if (err) check()
                else onstat(file, stat)
            });
        });
       check();
    }

    function onstat (file, stat, original) {
        if (emitter._seen[stat.ino || file]) return check();
        emitter._seen[stat.ino || file] = true;

        if (stat.isDirectory()) {
            if (original) opts._original = original;
            walk(file, opts, emitter, stat);
            check();
        }
        else if (stat.isSymbolicLink() && opts.followSymlinks) {
            emitter.emit('link', file, stat);

            fs.readlink(file, function (err, rfile) {
                if (emitter._stopped) return;
                if (err) return check();
                var file_ = path.resolve(path.dirname(file), rfile);

                emitter.emit('readlink', file, file_);
                fs.lstat(file_, function (err, stat_) {
                    if (emitter._stopped) return;
                    if (err) return check();

                    emitter._pending ++;
                    onstat(file_, stat_, file);
                    check();
                });
            });
        }
        else if (stat.isSymbolicLink()) {
            emitter.emit('link', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
        else {
            emitter.emit('file', file, stat);
            emitter.emit('path', file, stat);
            check();
        }
    }
};
<|endoftext|>


<commit_before>/**
 * index.js
 *
 * @author: Harish Anchu <harishanchu@gmail.com>
 * @copyright 2015, Harish Anchu. All rights reserved.
 * @license Licensed under MIT
 */

var SessionManager = require('./lib/SessionManager');
var onHeaders = require('on-headers');
var _ = require('lodash');
var signature = require('cookie-signature');
var cookie = require('cookie');
var util = require('./lib/util');

/**
 * Create a new NodeSession instance
 *
 * @param {Object} config - session configuration object
 * @param {Object | void} encrypter
 * @constructor
 */
function NodeSession(config, encrypter) {
    var defaults = {
        'driver': 'file',
        'lifetime': 300000, // five minutes
        'expireOnClose': false,
        'files': process.cwd()+'/sessions',
        'connection': false,
        'table': 'sessions',
        'lottery': [2, 100],
        'cookie': 'node_session',
        'path': '/',
        'domain': null,
        'secure': false,
        'httpOnly': true,
        'encrypt': false
    };

    /**
     * The Session configuration
     *
     * @type {Object}
     * @private
     */
    this.__config = _.merge(defaults, config);

    if(this.__config.trustProxy && !this.__config.trustProxyFn) {
        this.__config.trustProxyFn = util.compileTrust(this.__config.trustProxy)
    }

    /**
     * The session manager instance
     * @type {SessionManager}
     * @private
     */
    this.__manager = new SessionManager(this.__config, encrypter);

    if (!this.__config.secret) {
        throw new Error('secret option required for sessions');
    }
}

/**
 * Start session for a given http request - response
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @param {function} callback
 */
NodeSession.prototype.startSession = function (request, response, callback) {
    var self = this;
    var end = response.end;
    var ended = false;

    // Set cookie to response headers before headers are sent
    onHeaders(response, function () {
        self.__addCookieToResponse(request, response);
    });

    // Proxy response.end to close session before request end
    response.end = function () {
        var endArguments = arguments;

        if (ended) {
            return false;
        }

        ended = true;

        self.__closeSession(request.session, function (err) {
            if(err) {
                throw err;
            }
            end.apply(response, endArguments);
        });

    };

    // start the session for the request
    this.__startSession(request, callback);
};

/**
 * Start the session for the given request.
 *
 * @param {Object} request - http request object
 * @param {function} callback
 * @private
 */
NodeSession.prototype.__startSession = function (request, callback) {
    this.getSession(request, function(session) {
        request.session = session;

        session.start(callback);
    });
};

/**
 * Get the session implementation from the manager.
 *
 * @param {Object} request - http request object
 * @param {function} callback - callback to return session object
 */
NodeSession.prototype.getSession = function (request, callback) {
    var self = this;
    this.__manager.driver(null, function(session){
        session.setId(self.__getCookie(request, session.getName()));

        callback(session);
    });
};

/**
 * Add the session cookie to the application response.
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @private
 */
NodeSession.prototype.__addCookieToResponse = function (request, response) {
    var config = this.__config;
    var session = request.session;
    var maxAge = this.__getCookieLifetime();
    var data = {
        signed: true,
        path: config.path,
        domain: config.domain,
        secure: config.secure,
        httpOnly: config.httpOnly
    };

    // maxAge = 0 => cookie expire on browser close.
    // so no need to set maxAge.
    if (maxAge !== 0) {
        data.maxAge = maxAge;
    }

    this.__setCookie(
        request,
        response,
        session.getName(),
        session.getId(),
        data
    );
};

/**
 * Get the cookie lifetime in seconds.
 *
 * @return {Number}
 * @private
 */
NodeSession.prototype.__getCookieLifetime = function () {
    var config = this.__config;

    return config.expireOnClose ? 0 : config.lifetime;
};

/**
 * Closes the given session.
 *
 * @param {Object} session - the session object
 * @param {function} callback
 * @private
 */
NodeSession.prototype.__closeSession = function (session, callback) {
    session.save(callback);
    //@todo: note callback is executed after save, not waiting for garbage collection to complete
    this.__collectGarbage(session);
};

/**
 * Remove the garbage from the session if necessary.
 *
 * @param {Object} session - the session object
 * @private
 */
NodeSession.prototype.__collectGarbage = function (session) {
    // Here we will see if this request hits the garbage collection lottery by hitting
    // the odds needed to perform garbage collection on any given request. If we do
    // hit it, we'll call this handler to let it delete all the expired sessions.
    if (this.__configHitsLottery()) {
        session.getHandler().gc(this.__config.lifetime);
    }
};

/**
 * Determine if the configuration odds hit the lottery.
 *
 * @return {Boolean}
 * @private
 */
NodeSession.prototype.__configHitsLottery = function () {
    return (_.random(1, this.__config['lottery'][1]) <= this.__config['lottery'][0]);
};

/**
 * Add session cookie to response
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @param {String} name - cookie name
 * @param {*} val - cookie value
 * @param {*} options
 * @private
 */
NodeSession.prototype.__setCookie = function (request, response, name, val, options) {
    options = _.merge({}, options);

    // only send secure cookies via https
    if (!(options.secure && !this.__isSecure(request))) {
        var secret = this.__config.secret;
        var signed = options.signed;

        if (signed && !secret) {
            throw new Error('An encryption key is required for signed cookies');
        }

        if ('number' == typeof val) {
            val = val.toString();
        }

        if ('object' == typeof val) {
            val = 'j:' + JSON.stringify(val);
        }

        if (signed) {
            val = 's:' + signature.sign(val, secret);
        }

        if ('maxAge' in options) {
            options.expires = new Date(Date.now() + options.maxAge);
            options.maxAge /= 1000;
        }

        if (null == options.path) {
            options.path = '/';
        }

        var headerVal = cookie.serialize(name, String(val), options);

        // supports multiple 'setCookie' calls by getting previous value
        var prev = response.getHeader('set-cookie') || [];
        var header = Array.isArray(prev) ? prev.concat(headerVal)
            : Array.isArray(headerVal) ? [prev].concat(headerVal)
            : [prev, headerVal];

        response.setHeader('set-cookie', header);
    }
};

/**
 * Check whether request is secure
 *
 * @param {Object} request - http request object
 * @return {boolean}
 * @private
 */
NodeSession.prototype.__isSecure = function (request) {
    var proto;

    // socket is https server
    if (request.connection && request.connection.encrypted) {
        proto = 'https'
    } else {
        proto = 'http';
    }

    if (this.__config.trustProxy &&
        this.__config.trustProxyFn &&
        this.__config.trustProxyFn(request.connection.remoteAddress, 0)) {
        // Note: X-Forwarded-Proto is normally only ever a
        //       single value, but this is to be safe.
        // read the proto from x-forwarded-proto header
        var header = request.headers['x-forwarded-proto'] || '';
        var index = header.indexOf(',');
        proto = (index !== -1
            ? header.substr(0, index).toLowerCase().trim()
            : header.toLowerCase().trim()) || proto;
    }

    return proto === 'https';
};

/**
 * Get the session ID cookie from request.
 *
 * @return {string} session id
 * @private
 */
NodeSession.prototype.__getCookie = function (request, name) {
    // if signed cookie is already present in request(means cookie
    // parsing is already done), we will use it straight.
    if (request.signedCookies) {
        return request.signedCookies[name];
    }

    var header = request.headers.cookie;
    var raw;
    var val;

    // read from cookie header
    if (header) {
        var cookies = cookie.parse(header);

        raw = cookies[name];

        if (raw) {
            if (raw.substr(0, 2) === 's:') {
                val = this.__unsignCookie(raw.slice(2));

                if (val === false) {
                    //console.error('cookie signature invalid');
                    val = undefined;
                }
            }
        }
    }

    return val;
};

/**
 * Unsign a cookie value
 *
 * @param {String} val
 * @returns {String|Boolean}
 * @private
 */
NodeSession.prototype.__unsignCookie = function (val) {
    return signature.unsign(val, this.__config.secret);
};

module.exports = NodeSession;<commit_msg>Call gc only if handler supports gc method<commit_after>/**
 * index.js
 *
 * @author: Harish Anchu <harishanchu@gmail.com>
 * @copyright 2015, Harish Anchu. All rights reserved.
 * @license Licensed under MIT
 */

var SessionManager = require('./lib/SessionManager');
var onHeaders = require('on-headers');
var _ = require('lodash');
var signature = require('cookie-signature');
var cookie = require('cookie');
var util = require('./lib/util');

/**
 * Create a new NodeSession instance
 *
 * @param {Object} config - session configuration object
 * @param {Object | void} encrypter
 * @constructor
 */
function NodeSession(config, encrypter) {
    var defaults = {
        'driver': 'file',
        'lifetime': 300000, // five minutes
        'expireOnClose': false,
        'files': process.cwd()+'/sessions',
        'connection': false,
        'table': 'sessions',
        'lottery': [2, 100],
        'cookie': 'node_session',
        'path': '/',
        'domain': null,
        'secure': false,
        'httpOnly': true,
        'encrypt': false
    };

    /**
     * The Session configuration
     *
     * @type {Object}
     * @private
     */
    this.__config = _.merge(defaults, config);

    if(this.__config.trustProxy && !this.__config.trustProxyFn) {
        this.__config.trustProxyFn = util.compileTrust(this.__config.trustProxy)
    }

    /**
     * The session manager instance
     * @type {SessionManager}
     * @private
     */
    this.__manager = new SessionManager(this.__config, encrypter);

    if (!this.__config.secret) {
        throw new Error('secret option required for sessions');
    }
}

/**
 * Start session for a given http request - response
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @param {function} callback
 */
NodeSession.prototype.startSession = function (request, response, callback) {
    var self = this;
    var end = response.end;
    var ended = false;

    // Set cookie to response headers before headers are sent
    onHeaders(response, function () {
        self.__addCookieToResponse(request, response);
    });

    // Proxy response.end to close session before request end
    response.end = function () {
        var endArguments = arguments;

        if (ended) {
            return false;
        }

        ended = true;

        self.__closeSession(request.session, function (err) {
            if(err) {
                throw err;
            }
            end.apply(response, endArguments);
        });

    };

    // start the session for the request
    this.__startSession(request, callback);
};

/**
 * Start the session for the given request.
 *
 * @param {Object} request - http request object
 * @param {function} callback
 * @private
 */
NodeSession.prototype.__startSession = function (request, callback) {
    this.getSession(request, function(session) {
        request.session = session;

        session.start(callback);
    });
};

/**
 * Get the session implementation from the manager.
 *
 * @param {Object} request - http request object
 * @param {function} callback - callback to return session object
 */
NodeSession.prototype.getSession = function (request, callback) {
    var self = this;
    this.__manager.driver(null, function(session){
        session.setId(self.__getCookie(request, session.getName()));

        callback(session);
    });
};

/**
 * Add the session cookie to the application response.
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @private
 */
NodeSession.prototype.__addCookieToResponse = function (request, response) {
    var config = this.__config;
    var session = request.session;
    var maxAge = this.__getCookieLifetime();
    var data = {
        signed: true,
        path: config.path,
        domain: config.domain,
        secure: config.secure,
        httpOnly: config.httpOnly
    };

    // maxAge = 0 => cookie expire on browser close.
    // so no need to set maxAge.
    if (maxAge !== 0) {
        data.maxAge = maxAge;
    }

    this.__setCookie(
        request,
        response,
        session.getName(),
        session.getId(),
        data
    );
};

/**
 * Get the cookie lifetime in seconds.
 *
 * @return {Number}
 * @private
 */
NodeSession.prototype.__getCookieLifetime = function () {
    var config = this.__config;

    return config.expireOnClose ? 0 : config.lifetime;
};

/**
 * Closes the given session.
 *
 * @param {Object} session - the session object
 * @param {function} callback
 * @private
 */
NodeSession.prototype.__closeSession = function (session, callback) {
    session.save(callback);
    //@todo: note callback is executed after save, not waiting for garbage collection to complete
    this.__collectGarbage(session);
};

/**
 * Remove the garbage from the session if necessary.
 *
 * @param {Object} session - the session object
 * @private
 */
NodeSession.prototype.__collectGarbage = function (session) {
    // Here we will see if this request hits the garbage collection lottery by hitting
    // the odds needed to perform garbage collection on any given request. If we do
    // hit it, we'll call this handler to let it delete all the expired sessions.
    if (this.__configHitsLottery()) {
        session.getHandler().gc && session.getHandler().gc(this.__config.lifetime);
    }
};

/**
 * Determine if the configuration odds hit the lottery.
 *
 * @return {Boolean}
 * @private
 */
NodeSession.prototype.__configHitsLottery = function () {
    return (_.random(1, this.__config['lottery'][1]) <= this.__config['lottery'][0]);
};

/**
 * Add session cookie to response
 *
 * @param {Object} request - http request object
 * @param {Object} response - http response object
 * @param {String} name - cookie name
 * @param {*} val - cookie value
 * @param {*} options
 * @private
 */
NodeSession.prototype.__setCookie = function (request, response, name, val, options) {
    options = _.merge({}, options);

    // only send secure cookies via https
    if (!(options.secure && !this.__isSecure(request))) {
        var secret = this.__config.secret;
        var signed = options.signed;

        if (signed && !secret) {
            throw new Error('An encryption key is required for signed cookies');
        }

        if ('number' == typeof val) {
            val = val.toString();
        }

        if ('object' == typeof val) {
            val = 'j:' + JSON.stringify(val);
        }

        if (signed) {
            val = 's:' + signature.sign(val, secret);
        }

        if ('maxAge' in options) {
            options.expires = new Date(Date.now() + options.maxAge);
            options.maxAge /= 1000;
        }

        if (null == options.path) {
            options.path = '/';
        }

        var headerVal = cookie.serialize(name, String(val), options);

        // supports multiple 'setCookie' calls by getting previous value
        var prev = response.getHeader('set-cookie') || [];
        var header = Array.isArray(prev) ? prev.concat(headerVal)
            : Array.isArray(headerVal) ? [prev].concat(headerVal)
            : [prev, headerVal];

        response.setHeader('set-cookie', header);
    }
};

/**
 * Check whether request is secure
 *
 * @param {Object} request - http request object
 * @return {boolean}
 * @private
 */
NodeSession.prototype.__isSecure = function (request) {
    var proto;

    // socket is https server
    if (request.connection && request.connection.encrypted) {
        proto = 'https'
    } else {
        proto = 'http';
    }

    if (this.__config.trustProxy &&
        this.__config.trustProxyFn &&
        this.__config.trustProxyFn(request.connection.remoteAddress, 0)) {
        // Note: X-Forwarded-Proto is normally only ever a
        //       single value, but this is to be safe.
        // read the proto from x-forwarded-proto header
        var header = request.headers['x-forwarded-proto'] || '';
        var index = header.indexOf(',');
        proto = (index !== -1
            ? header.substr(0, index).toLowerCase().trim()
            : header.toLowerCase().trim()) || proto;
    }

    return proto === 'https';
};

/**
 * Get the session ID cookie from request.
 *
 * @return {string} session id
 * @private
 */
NodeSession.prototype.__getCookie = function (request, name) {
    // if signed cookie is already present in request(means cookie
    // parsing is already done), we will use it straight.
    if (request.signedCookies) {
        return request.signedCookies[name];
    }

    var header = request.headers.cookie;
    var raw;
    var val;

    // read from cookie header
    if (header) {
        var cookies = cookie.parse(header);

        raw = cookies[name];

        if (raw) {
            if (raw.substr(0, 2) === 's:') {
                val = this.__unsignCookie(raw.slice(2));

                if (val === false) {
                    //console.error('cookie signature invalid');
                    val = undefined;
                }
            }
        }
    }

    return val;
};

/**
 * Unsign a cookie value
 *
 * @param {String} val
 * @returns {String|Boolean}
 * @private
 */
NodeSession.prototype.__unsignCookie = function (val) {
    return signature.unsign(val, this.__config.secret);
};

module.exports = NodeSession;<|endoftext|>


<commit_before>/**
 * Module dependencies
 */
var apac = require('apac')
  , path = require('JSONPath').eval
  , transforms = require('./transforms')
  , _ = require('underscore');

var price = module.exports = function (itemId, opts) {
  return new Price(itemId, opts);
};

var Price = function Price (itemId, opts) {
  this.mode = 'lookup';

  if ('object' === typeof itemId) {
    if (itemId.id) this.itemId = itemId.id;
    if (itemId.keywords) this.keywords = itemId.keywords, this.mode = 'search';
  } else {
    this.itemId = itemId;
  }

  this.opts = opts || {};
  this.extractions = defaultExtractions;
};

Price.prototype.creds = function (creds) {
  _.extend(this.opts, {
    amazonId: creds.id,
    amazonSecret: creds.secret,
    associateId: creds.associateId
  });

  return this;
};

Price.prototype.id = function (id) {
  this.opts.amazonId = id;
  return this;
};

Price.prototype.secret = function (secret) {
  this.opts.amazonSecret = secret;
  return this;
};

Price.prototype.associate = function (associateId) {
  this.opts.associateId = associateId;
  return this;
};

Price.prototype.country = function (country) {
  if (!country) return this;

  // Find matching endpoints
  var match = endpointMap.filter(function (e) {
    return e.code === country.toUpperCase() || e.name === country;
  });

  // Set country
  this.country = country;

  // Set the first matching endpoint
  if (match.length > 0) this.opts.endpoint = match[0].endpoint;
  return this;
};

Price.prototype.price = function (price) {
  if (_.isString(price)) {
    price = price.split('..');
  } else if (!_.isArray(price)) {
    return this;
  }

  if (price[0]) this.opts.minimumPrice = price[0] * 100;
  if (price[1]) this.opts.maximumPrice = price[1] * 100;

  return this;
};

Price.prototype.done = function (cb) {
  var that = this;

  var helper = new apac.OperationHelper({
    awsId: this.opts.amazonId,
    awsSecret: this.opts.amazonSecret,
    assocId: this.opts.associateId,
    endPoint: this.opts.endpoint
  });

  // Make sure we only execute the callback once
  cb = _.once(cb);

  // Convert op name
  var op = this.mode === 'search' ? 'ItemSearch' : 'ItemLookup';

  // Populate request object
  var req = {
    'ResponseGroup': 'Offers,ItemAttributes',
  };

  if (this.opts.minimumPrice) req['MinimumPrice'] = this.opts.minimumPrice;
  if (this.opts.maximumPrice) req['MaximumPrice'] = this.opts.maximumPrice;

  if (this.mode === 'search') {
    _.extend(req, { 'SearchIndex': 'All', 'Keywords': this.keywords });
  } else if (this.mode === 'lookup') {
    _.extend(req, { 'ItemId': this.itemId });
  }

  // Run the request
  helper.execute(op, req, success(cb), error(cb));

  function success (cb) {
    return function (res) {
      var error = extractError(res);

      // Process errors
      if (error) return cb(new Error(error));

      // Extract interesting stuff
      var result = extract.call(that, res, that.extractions);

      return cb(null, result);
    }
  }

  function error (cb) {
    return function (error) {
      return cb(error);
    }
  }

  return this;
};

var first = function (obj, query) {
  var matches = path(obj, query);
  return matches.length ? matches[0] : null;
};

var extractError = function (obj) {
  return first(obj, '$..Error..Message[0]');
};

var endpointMap = [
  { name: 'canada', code: 'CA', endpoint: 'webservices.amazon.ca' },
  { name: 'china', code: 'CN', endpoint: 'webservices.amazon.cn' },
  { name: 'germany', code: 'DE', endpoint: 'webservices.amazon.de' },
  { name: 'spain', code: 'ES', endpoint: 'webservices.amazon.es' },
  { name: 'france', code: 'FR', endpoint: 'webservices.amazon.fr' },
  { name: 'italy', code: 'IT', endpoint: 'webservices.amazon.it' },
  { name: 'japan', code: 'JP', endpoint: 'webservices.amazon.co.jp' },
  { name: 'uk', code: 'GB', endpoint: 'webservices.amazon.co.uk' },
  { name: 'us', code: 'US', endpoint: 'webservices.amazon.com' },
  { name: 'india', code: 'IN', endpoint: 'webservices.amazon.in' }
];

var extract = function (text, extractions) {
  var that = this;

  var res = _
    .chain(extractions)
    .map(function (x) {
      var key = x.name
        , val = first(text, x.query);

      // Transform value if we have a transform available
      if (x.transform) val = x.transform.call(that, val);

      return [key, val];
    })
    .filter(function (x) {
      return x[1] !== null;
    })
    .object()
    .value();

  return _.keys(res).length ? res : null;
};

var defaultExtractions = [
  { name: 'id', query: '$..ASIN[0]' },
  { name: 'listPrice',
    query: '$..ListPrice..Price[0]',
    transform: transforms.formatPrice
  },
  { name: 'name', query: '$..Title[0]' },
  { name: 'offerPrice',
    query: '$..Offer..Price[0]',
    transform: transforms.formatPrice
  },
  { name: 'lowestPrice',
    query: '$..LowestNewPrice[0]',
    transform: transforms.formatPrice
  },
  { name: 'url', query: '$..DetailPageURL[0]' },
  { name: 'remaining', query: '$..TotalNew[0]' }
];
<commit_msg>Add limit and page controlling methods<commit_after>/**
 * Module dependencies
 */
var apac = require('apac')
  , path = require('JSONPath').eval
  , transforms = require('./transforms')
  , _ = require('underscore');

var price = module.exports = function (itemId, opts) {
  return new Price(itemId, opts);
};

var Price = function Price (itemId, opts) {
  this.mode = 'lookup';

  if ('object' === typeof itemId) {
    if (itemId.id) this.itemId = itemId.id;
    if (itemId.keywords) this.keywords = itemId.keywords, this.mode = 'search';
  } else {
    this.itemId = itemId;
  }

  this.opts = opts || {};
  this.extractions = defaultExtractions;
};

Price.prototype.creds = function (creds) {
  _.extend(this.opts, {
    amazonId: creds.id,
    amazonSecret: creds.secret,
    associateId: creds.associateId
  });

  return this;
};

Price.prototype.id = function (id) {
  this.opts.amazonId = id;
  return this;
};

Price.prototype.secret = function (secret) {
  this.opts.amazonSecret = secret;
  return this;
};

Price.prototype.associate = function (associateId) {
  this.opts.associateId = associateId;
  return this;
};

Price.prototype.country = function (country) {
  if (!country) return this;

  // Find matching endpoints
  var match = endpointMap.filter(function (e) {
    return e.code === country.toUpperCase() || e.name === country;
  });

  // Set country
  this.country = country;

  // Set the first matching endpoint
  if (match.length > 0) this.opts.endpoint = match[0].endpoint;
  return this;
};

Price.prototype.price = function (price) {
  if (_.isString(price)) {
    price = price.split('..');
  } else if (!_.isArray(price)) {
    return this;
  }

  if (price[0]) this.opts.minimumPrice = price[0] * 100;
  if (price[1]) this.opts.maximumPrice = price[1] * 100;

  return this;
};

Price.prototype.limit = function (limit) {
  return this._limit = limit, this;
};

Price.prototype.page = function (page) {
  return this._page = page, this;
};

Price.prototype.one = function (one) {
  return this._one = 'undefined' === typeof one ? true : !!one, this;
};

Price.prototype.done = function (cb) {
  var that = this;

  var helper = new apac.OperationHelper({
    awsId: this.opts.amazonId,
    awsSecret: this.opts.amazonSecret,
    assocId: this.opts.associateId,
    endPoint: this.opts.endpoint
  });

  // Make sure we only execute the callback once
  cb = _.once(cb);

  // Convert op name
  var op = this.mode === 'search' ? 'ItemSearch' : 'ItemLookup';

  // Populate request object
  var req = {
    'ResponseGroup': 'Offers,ItemAttributes',
  };

  if (this.opts.minimumPrice) req['MinimumPrice'] = this.opts.minimumPrice;
  if (this.opts.maximumPrice) req['MaximumPrice'] = this.opts.maximumPrice;

  if (this.mode === 'search') {
    _.extend(req, { 'SearchIndex': 'All', 'Keywords': this.keywords });
  } else if (this.mode === 'lookup') {
    _.extend(req, { 'ItemId': this.itemId });
  }

  // Run the request
  helper.execute(op, req, success(cb), error(cb));

  function success (cb) {
    return function (res) {
      var error = extractError(res);

      // Process errors
      if (error) return cb(new Error(error));

      // Extract interesting stuff
      var result = extract.call(that, res, that.extractions);

      return cb(null, result);
    }
  }

  function error (cb) {
    return function (error) {
      return cb(error);
    }
  }

  return this;
};

var first = function (obj, query) {
  var matches = path(obj, query);
  return matches.length ? matches[0] : null;
};

var extractError = function (obj) {
  return first(obj, '$..Error..Message[0]');
};

var endpointMap = [
  { name: 'canada', code: 'CA', endpoint: 'webservices.amazon.ca' },
  { name: 'china', code: 'CN', endpoint: 'webservices.amazon.cn' },
  { name: 'germany', code: 'DE', endpoint: 'webservices.amazon.de' },
  { name: 'spain', code: 'ES', endpoint: 'webservices.amazon.es' },
  { name: 'france', code: 'FR', endpoint: 'webservices.amazon.fr' },
  { name: 'italy', code: 'IT', endpoint: 'webservices.amazon.it' },
  { name: 'japan', code: 'JP', endpoint: 'webservices.amazon.co.jp' },
  { name: 'uk', code: 'GB', endpoint: 'webservices.amazon.co.uk' },
  { name: 'us', code: 'US', endpoint: 'webservices.amazon.com' },
  { name: 'india', code: 'IN', endpoint: 'webservices.amazon.in' }
];

var extract = function (text, extractions) {
  var that = this;

  var res = _
    .chain(extractions)
    .map(function (x) {
      var key = x.name
        , val = first(text, x.query);

      // Transform value if we have a transform available
      if (x.transform) val = x.transform.call(that, val);

      return [key, val];
    })
    .filter(function (x) {
      return x[1] !== null;
    })
    .object()
    .value();

  return _.keys(res).length ? res : null;
};

var defaultExtractions = [
  { name: 'id', query: '$..ASIN[0]' },
  { name: 'listPrice',
    query: '$..ListPrice..Price[0]',
    transform: transforms.formatPrice
  },
  { name: 'name', query: '$..Title[0]' },
  { name: 'offerPrice',
    query: '$..Offer..Price[0]',
    transform: transforms.formatPrice
  },
  { name: 'lowestPrice',
    query: '$..LowestNewPrice[0]',
    transform: transforms.formatPrice
  },
  { name: 'url', query: '$..DetailPageURL[0]' },
  { name: 'remaining', query: '$..TotalNew[0]' }
];
<|endoftext|>


<commit_before>/**
 * Build and run BDD flows with before/after hooks, describe, it
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

module.exports = {
  Bddflow: Bddflow,
  Describe: Describe,
  It: It,
  HookContext: HookContext,
  HookSet: HookSet,
  create: create,
  require: require // Allow tests to use component-land require.
};

var Batch = require('batch');
var bind = require('bind');
var clone = require('clone');
var configurable = require('configurable.js');
var extend = require('extend');

// Match properties that should not be 'inherited' between hook/describe/it.
var defOmitContextRegex = /^__|^(it|describe|before|beforeEach|after|afterEach|settings|set|get)$/;

// TODO make this a property, not a global
var initOmitContextRegex = {
  all: [defOmitContextRegex],
  it: [],
  hook: []
};
var omitContextRegex;

function create() {
  return new Bddflow();
}

function Bddflow() {
  this.settings = {
    done: noOp, // Batch#end callback that fires after flow completes.

    // Propagate to each new Describe instance:
    itWrap: null
  };
  this.rootDescribes = [];
  this.batch = new Batch();
  this.seedProps = {}; // Will me merged into initial hook/describe/it context.

  omitContextRegex = clone(initOmitContextRegex); // TODO refactor
}
Bddflow.describeConfigKeys = ['itWrap'];

configurable(Bddflow.prototype);

/**
 * Add a "root" describe().
 *
 * @param {string} name
 * @param {function} cb
 */
Bddflow.prototype.addRootDescribe = function(name, cb, context) {
  var self = this;
  var desc = new Describe(name);

  var bddFlowConfig = {}; // Propagate selected settings.
  Bddflow.describeConfigKeys.forEach(function(key) {
    bddFlowConfig[key] = self.get(key);
  });
  desc.set('bddFlowConfig', bddFlowConfig);

  desc.describe(name, cb);
  this.rootDescribes.push(desc);
  return this;
};

/**
 * Run the batched steps in each root describe().
 */
Bddflow.prototype.run = function() {
  var self = this;
  var batch = new Batch();
  batch.concurrency = 1;
  this.rootDescribes.forEach(function(desc) {
    batch.push(function(taskDone) {
      extend(desc, self.seedProps);
      runArrayOfFn(desc.__steps, taskDone, 1);
    });
  });
  batch.end(this.get('done'));
};

/**
 * Add custom property to the initial hook/describe/it context.
 *
 * @param {string} key
 * @param {mixed} val
 * @return {object} this
 */
Bddflow.prototype.addContextProp = function(key, val) {
  this.seedProps[key] = val;
  return this;
};

Bddflow.prototype.omitContextByRegex = function(type, regex) {
  omitContextRegex[type].push(regex);
  return this;
};

/**
 * Filter 'this' into an object with properties that can be 'inherited'
 * between hooks/describe/it.
 *
 * Static used in other classes via call(). Exposed for test access.
 *
 * @param {string} type 'describe', 'it', 'hook'
 * @return {object}
 */
Bddflow.getInheritableContext = function(type) {
  var self = this;
  var regex = omitContextRegex.all.concat(type ? omitContextRegex[type] : []);

  return Object.keys(this).reduce(function(memo, key) {
    var omit = false;
    regex.forEach(function(re) {
      omit = omit || re.test(key);
    });
    if (omit) {
      return memo;
    }
    memo[key] = self[key];
    return memo;
  }, {});
};

/**
 * Augment 'this' with a new non-enumerable/configrable property intended
 * for internal-use only. Help avoid conflicts with properties 'inherited'
 * via getInheritableContext.
 *
 * Static used in other classes via call(). Exposed for test access.
 *
 * @param {string} key
 * @param {mixed} value
 */
Bddflow.addInternalProp = function(key, value) {
  Object.defineProperty(
    this, '__' + key,
    {value: value, enumerable: false, configurable: false, writable: true}
  );
};

/**
 * Construct before(), beforeEach(), etc.
 *
 * @param {string} name Of enclosing describe().
 */
function HookContext(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
}
HookContext.prototype.getInheritableContext = Bddflow.getInheritableContext;

// Auto-terminating callback for use with Batch#push.
Bddflow.defaultHookImpl = function(done) { done(); };

/**
 * Construct a container for a before(), beforeEach(), etc. method set.
 */
function HookSet() {
  this.before = Bddflow.defaultHookImpl;
  this.beforeEach = Bddflow.defaultHookImpl;
  this.after = Bddflow.defaultHookImpl;
  this.afterEach = Bddflow.defaultHookImpl;
}

/**
 * Construct an it() context.
 *
 * @param {string} name // Ex. 'shoul do X'
 */
function It(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
}

/**
 * Construct a describe() context.
 *
 * @param {string} name Subject expected to exhibit some behavior.
 */
function Describe(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
  Bddflow.addInternalProp.call(this, 'steps', []);
  Bddflow.addInternalProp.call(this, 'hooks', new HookSet());
  this.settings = {
    bddFlowConfig: {}
  };
}
configurable(Describe.prototype);
Describe.prototype.getInheritableContext = Bddflow.getInheritableContext;

/**
 * Add an it() step.
 *
 * @param {string} name
 * @param {function} cb Batch#push compat.
 */
Describe.prototype.it = function(name, cb) {
  cb.type = 'it';
  this.__steps.push(cb);
};

/**
 * Add a describe() step.
 *
 * @param {string} name
 * @param {function} cb Batch#push compat.
 */
Describe.prototype.describe = function(name, cb) {
  var self = this;
  var step = function(done) {
    var desc = new Describe(name); // Collect nested steps.
    desc.set('bddFlowConfig', self.get('bddFlowConfig'));
    extend(desc, self.getInheritableContext());
    cb.call(desc);

    var hc = new HookContext(name);
    var batch = new Batch();

    batch.push(function(done) {
      extend(hc, desc.getInheritableContext('hook'));
      desc.__hooks.before.call(hc, function() {
        extend(desc, hc.getInheritableContext('hook'));
        done();
      });
    });

    batch.push(function(done) { // Wrap hooks around each internal describe()/it()
      desc.__steps = desc.__steps.map(function(fn) {
        if ('describe' === fn.type) {
          extend(desc, hc.getInheritableContext());
          return bind(desc, fn);
        }
        return function(done) { // type = 'it'
          var batch = new Batch();
          batch.push(function(done) {
            extend(hc, desc.getInheritableContext('hook'));
            desc.__hooks.beforeEach.call(hc, done);
          });
          batch.push(function(done) {
            var it = new It(name);

            // Start with context inherited from outer describe().
            // Then merge in changes/additions from the hooks.
            // If only the hook context is used, hook-targeted omission
            // strip some desired props from the describe().
            extend(it, desc.getInheritableContext('it'));
            extend(it, hc.getInheritableContext('it'));

            var itWrap = self.get('bddFlowConfig').itWrap || defItWrap;
            itWrap(name, function() {
              var wrapContext = this;
              var mergedContext = extend(it, wrapContext);
              fn.call(mergedContext, done);
            });
          });
          batch.push(function(done) {
            desc.__hooks.afterEach.call(hc, function() {
              extend(desc, hc.getInheritableContext('hook'));
              done();
            });
          });
          batch.concurrency = 1;
          batch.end(done);
        };
      });

      runArrayOfFn(desc.__steps, done);
    });

    batch.push(function(done) {
      extend(hc, desc.getInheritableContext('hook'));
      desc.__hooks.after.call(hc, done);
    });

    batch.concurrency = 1;
    batch.end(done);
  };
  step.type = 'describe';
  this.__steps.push(step);
};

/**
 * Override the default no-op before() hook.
 *
 * @param {function} cb
 */
Describe.prototype.before = function(cb) { this.__hooks.before = cb; };

/**
 * Override the default no-op beforeEach() hook.
 *
 * @param {function} cb
 */
Describe.prototype.beforeEach = function(cb) { this.__hooks.beforeEach = cb; };

/**
 * Override the default no-op after() hook.
 *
 * @param {function} cb
 */
Describe.prototype.after = function(cb) { this.__hooks.after = cb; };

/**
 * Override the default no-op afterEach() hook.
 *
 * @param {function} cb
 */
Describe.prototype.afterEach = function(cb) { this.__hooks.afterEach = cb; };

/**
 * Execute an array of functions w/ Batch.
 *
 * @param {array} list
 * @param {function} cb Called at completion.
 * @param {number} [concurrency=1]
 */
function runArrayOfFn(list, cb, concurrency) {
  var batch = new Batch();
  batch.concurrency = typeof concurrency === 'undefined' ? 1 : concurrency;
  list.forEach(function(fn) { batch.push(fn); });
  batch.end(cb);
}

function noOp() {}
function defItWrap(name, cb) { cb(); }
<commit_msg>Refactor context property omitting<commit_after>/**
 * Build and run BDD flows with before/after hooks, describe, it
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

module.exports = {
  Bddflow: Bddflow,
  Describe: Describe,
  It: It,
  HookContext: HookContext,
  HookSet: HookSet,
  create: create,
  require: require // Allow tests to use component-land require.
};

var Batch = require('batch');
var bind = require('bind');
var clone = require('clone');
var configurable = require('configurable.js');
var extend = require('extend');

// Match properties that should not be 'inherited' by it(), hooks, or all.
var defOmitContextRegex = {
  all: [/^__|^(it|describe|before|beforeEach|after|afterEach|settings|set|get)$/],
  it: [],
  hook: []
};

function create() {
  return new Bddflow();
}

function Bddflow() {
  this.settings = {
    done: noOp, // Batch#end callback that fires after flow completes.

    // Propagate to each new Describe instance:
    itWrap: null,
    omitContextRegex: clone(defOmitContextRegex)
  };
  this.rootDescribes = [];
  this.batch = new Batch();
  this.seedProps = {}; // Will me merged into initial hook/describe/it context.
}
Bddflow.sharedConfigKeys = ['itWrap', 'omitContextRegex'];

configurable(Bddflow.prototype);

/**
 * Add a "root" describe().
 *
 * @param {string} name
 * @param {function} cb
 */
Bddflow.prototype.addRootDescribe = function(name, cb, context) {
  var self = this;
  var desc = new Describe(name);

  var bddFlowConfig = {}; // Propagate selected settings.
  Bddflow.sharedConfigKeys.forEach(function(key) {
    bddFlowConfig[key] = self.get(key);
  });
  desc.set('bddFlowConfig', bddFlowConfig);

  desc.describe(name, cb);
  this.rootDescribes.push(desc);
  return this;
};

/**
 * Run the batched steps in each root describe().
 */
Bddflow.prototype.run = function() {
  var self = this;
  var batch = new Batch();
  batch.concurrency = 1;
  this.rootDescribes.forEach(function(desc) {
    batch.push(function(taskDone) {
      extend(desc, self.seedProps);
      runArrayOfFn(desc.__steps, taskDone, 1);
    });
  });
  batch.end(this.get('done'));
};

/**
 * Add custom property to the initial hook/describe/it context.
 *
 * @param {string} key
 * @param {mixed} val
 * @return {object} this
 */
Bddflow.prototype.addContextProp = function(key, val) {
  this.seedProps[key] = val;
  return this;
};

/**
 * Prevent a type of flow function from 'inheriting' specific context properties
 * from enclosing/subsequently-executed flow functions.
 *
 * @param {string} 'it', 'hook'
 * @param {object} RegExp instance.
 * @return {object} this
 */
Bddflow.prototype.omitContextByRegex = function(type, regex) {
  this.get('omitContextRegex')[type].push(regex);
  return this;
};

/**
 * Filter 'this' into an object with properties that can be 'inherited'
 * between hooks/describe/it.
 *
 * Static used in other classes via call(). Exposed for test access.
 *
 * @param {string} type 'describe', 'it', 'hook'
 * @return {object}
 */
Bddflow.getInheritableContext = function(type) {
  var self = this;
  var omitContextRegex = this.get('bddFlowConfig').omitContextRegex;
  var regex = omitContextRegex.all.concat(type ? omitContextRegex[type] : []);

  return Object.keys(this).reduce(function(memo, key) {
    var omit = false;
    regex.forEach(function(re) {
      omit = omit || re.test(key);
    });
    if (omit) {
      return memo;
    }
    memo[key] = self[key];
    return memo;
  }, {});
};

/**
 * Augment 'this' with a new non-enumerable/configrable property intended
 * for internal-use only. Help avoid conflicts with properties 'inherited'
 * via getInheritableContext.
 *
 * Static used in other classes via call(). Exposed for test access.
 *
 * @param {string} key
 * @param {mixed} value
 */
Bddflow.addInternalProp = function(key, value) {
  Object.defineProperty(
    this, '__' + key,
    {value: value, enumerable: false, configurable: false, writable: true}
  );
};

/**
 * Construct before(), beforeEach(), etc.
 *
 * @param {string} name Of enclosing describe().
 */
function HookContext(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
}
configurable(HookContext.prototype);
HookContext.prototype.getInheritableContext = Bddflow.getInheritableContext;

// Auto-terminating callback for use with Batch#push.
Bddflow.defaultHookImpl = function(done) { done(); };

/**
 * Construct a container for a before(), beforeEach(), etc. method set.
 */
function HookSet() {
  this.before = Bddflow.defaultHookImpl;
  this.beforeEach = Bddflow.defaultHookImpl;
  this.after = Bddflow.defaultHookImpl;
  this.afterEach = Bddflow.defaultHookImpl;
}

/**
 * Construct an it() context.
 *
 * @param {string} name // Ex. 'shoul do X'
 */
function It(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
}

/**
 * Construct a describe() context.
 *
 * @param {string} name Subject expected to exhibit some behavior.
 */
function Describe(name) {
  Bddflow.addInternalProp.call(this, 'name', name);
  Bddflow.addInternalProp.call(this, 'steps', []);
  Bddflow.addInternalProp.call(this, 'hooks', new HookSet());
  this.settings = {
    bddFlowConfig: {}
  };
}
configurable(Describe.prototype);
Describe.prototype.getInheritableContext = Bddflow.getInheritableContext;

/**
 * Add an it() step.
 *
 * @param {string} name
 * @param {function} cb Batch#push compat.
 */
Describe.prototype.it = function(name, cb) {
  cb.type = 'it';
  this.__steps.push(cb);
};

/**
 * Add a describe() step.
 *
 * @param {string} name
 * @param {function} cb Batch#push compat.
 */
Describe.prototype.describe = function(name, cb) {
  var self = this;
  var step = function(done) {
    var desc = new Describe(name); // Collect nested steps.
    desc.set('bddFlowConfig', self.get('bddFlowConfig'));
    extend(desc, self.getInheritableContext());
    cb.call(desc);

    var hc = new HookContext(name);
    hc.set('bddFlowConfig', self.get('bddFlowConfig'));

    var batch = new Batch();

    batch.push(function(done) {
      extend(hc, desc.getInheritableContext('hook'));
      desc.__hooks.before.call(hc, function() {
        extend(desc, hc.getInheritableContext('hook'));
        done();
      });
    });

    batch.push(function(done) { // Wrap hooks around each internal describe()/it()
      desc.__steps = desc.__steps.map(function(fn) {
        if ('describe' === fn.type) {
          extend(desc, hc.getInheritableContext());
          return bind(desc, fn);
        }
        return function(done) { // type = 'it'
          var batch = new Batch();
          batch.push(function(done) {
            extend(hc, desc.getInheritableContext('hook'));
            desc.__hooks.beforeEach.call(hc, done);
          });
          batch.push(function(done) {
            var it = new It(name);

            // Start with context inherited from outer describe().
            // Then merge in changes/additions from the hooks.
            // If only the hook context is used, hook-targeted omission
            // strip some desired props from the describe().
            extend(it, desc.getInheritableContext('it'));
            extend(it, hc.getInheritableContext('it'));

            var itWrap = self.get('bddFlowConfig').itWrap || defItWrap;
            itWrap(name, function() {
              var wrapContext = this;
              var mergedContext = extend(it, wrapContext);
              fn.call(mergedContext, done);
            });
          });
          batch.push(function(done) {
            desc.__hooks.afterEach.call(hc, function() {
              extend(desc, hc.getInheritableContext('hook'));
              done();
            });
          });
          batch.concurrency = 1;
          batch.end(done);
        };
      });

      runArrayOfFn(desc.__steps, done);
    });

    batch.push(function(done) {
      extend(hc, desc.getInheritableContext('hook'));
      desc.__hooks.after.call(hc, done);
    });

    batch.concurrency = 1;
    batch.end(done);
  };
  step.type = 'describe';
  this.__steps.push(step);
};

/**
 * Override the default no-op before() hook.
 *
 * @param {function} cb
 */
Describe.prototype.before = function(cb) { this.__hooks.before = cb; };

/**
 * Override the default no-op beforeEach() hook.
 *
 * @param {function} cb
 */
Describe.prototype.beforeEach = function(cb) { this.__hooks.beforeEach = cb; };

/**
 * Override the default no-op after() hook.
 *
 * @param {function} cb
 */
Describe.prototype.after = function(cb) { this.__hooks.after = cb; };

/**
 * Override the default no-op afterEach() hook.
 *
 * @param {function} cb
 */
Describe.prototype.afterEach = function(cb) { this.__hooks.afterEach = cb; };

/**
 * Execute an array of functions w/ Batch.
 *
 * @param {array} list
 * @param {function} cb Called at completion.
 * @param {number} [concurrency=1]
 */
function runArrayOfFn(list, cb, concurrency) {
  var batch = new Batch();
  batch.concurrency = typeof concurrency === 'undefined' ? 1 : concurrency;
  list.forEach(function(fn) { batch.push(fn); });
  batch.end(cb);
}

function noOp() {}
function defItWrap(name, cb) { cb(); }
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var express = require('express');

var app = express();
var bodyParser = require('body-parser');
var frequency = require(__dirname + '/lib/frequency');
var sentimentChecker = require(__dirname + '/lib/sentiment_checker.js');
var mapSentimentToArticle = require(__dirname + '/lib/map_sentiment.js');
var listRouter = require(__dirname + '/routes/list_routes.js');
var listEntryRouter = require(__dirname + '/routes/listentry_routes.js');
var articleRouter = require(__dirname + '/routes/article_routes.js');
var Article = require(__dirname + '/models/article').Article;

mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/nlp_database');

app.use('/api', listRouter);
app.use('/api', articleRouter);
app.use('/api', listEntryRouter);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/public/index.html');
});

app.post('/process', bodyParser.urlencoded({extended: true}), function(req, res){
  var recievedText = (req.body.text);
  var returnJSON = (sentimentChecker(recievedText));
  res.json(returnJSON);
});

app.listen(3000, function(){
  console.log('server up!');
});
<commit_msg>added routes to about us page<commit_after>var mongoose = require('mongoose');
var express = require('express');

var app = express();
var bodyParser = require('body-parser');
var frequency = require(__dirname + '/lib/frequency');
var sentimentChecker = require(__dirname + '/lib/sentiment_checker.js');
var mapSentimentToArticle = require(__dirname + '/lib/map_sentiment.js');
var listRouter = require(__dirname + '/routes/list_routes.js');
var listEntryRouter = require(__dirname + '/routes/listentry_routes.js');
var articleRouter = require(__dirname + '/routes/article_routes.js');
var Article = require(__dirname + '/models/article').Article;

mongoose.connect(process.env.MONGOLAB_URI || 'mongodb://localhost/nlp_database');

app.use('/api', listRouter);
app.use('/api', articleRouter);
app.use('/api', listEntryRouter);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/public/index.html');
});

app.get('/about-us', function(req, res){
  res.sendFile(__dirname + '/public/about-us.html');
});

app.post('/process', bodyParser.urlencoded({extended: true}), function(req, res){
  var recievedText = (req.body.text);
  var returnJSON = (sentimentChecker(recievedText));
  res.json(returnJSON);
});

app.listen(3000, function(){
  console.log('server up!');
});
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-g-map',

  included: function(app, parentAddon) {
    var target = (parentAddon || app);
    target.import('vendor/addons.css');
  },

  contentFor: function(type, config) {
    var content = '';

    if (type === 'head') {
      var src = "https://maps.googleapis.com/maps/api/js";
      var gMapConfig = config['g-map'] || {};
      var params = [];

      var key = gMapConfig.key;
      if (key) {
        params.push('key=' + encodeURIComponent(key));
      }

      var libraries = gMapConfig.libraries;
      if (libraries && libraries.length) {
        params.push('libraries=' + encodeURIComponent(libraries.join(',')));
      }

      var protocol = gMapConfig.protocol;
      if (protocol) {
        src = protocol + ":" + src;
      }

      src += '?' + params.join('&');
      content = '<script type="text/javascript" src="' + src + '"></script>';
    }

    return content;
  }
};
<commit_msg>Revert "removing protocol relative url"<commit_after>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-g-map',

  included: function(app, parentAddon) {
    var target = (parentAddon || app);
    target.import('vendor/addons.css');
  },

  contentFor: function(type, config) {
    var content = '';

    if (type === 'head') {
      var src = "//maps.googleapis.com/maps/api/js";
      var gMapConfig = config['g-map'] || {};
      var params = [];

      var key = gMapConfig.key;
      if (key) {
        params.push('key=' + encodeURIComponent(key));
      }

      var libraries = gMapConfig.libraries;
      if (libraries && libraries.length) {
        params.push('libraries=' + encodeURIComponent(libraries.join(',')));
      }

      var protocol = gMapConfig.protocol;
      if (protocol) {
        src = protocol + ":" + src;
      }

      src += '?' + params.join('&');
      content = '<script type="text/javascript" src="' + src + '"></script>';
    }

    return content;
  }
};
<|endoftext|>


<commit_before>'use strict';

var ts         = require('typescript');
var Filter     = require('broccoli-persistent-filter');
var stringify  = require('json-stable-stringify');
var crypto     = require('crypto');

var getCallerFile = require('get-caller-file');

var loadTSConfig = require('./lib/load-ts-config');
var findTSConfig = require('./lib/find-ts-config');

module.exports = TypeScript;
function TypeScript(inputTree, _options) {
  var options = _options || {};

  if (!(this instanceof TypeScript)) {
    return new TypeScript(inputTree, options);
  }

  Filter.call(this, inputTree, {
    persist: true,
    extensions: ['ts','d.ts'],
    targetExtension: 'js',
    name: 'broccoli-typescript-compiler',
    annotation: options.annotation
  });

  this.options = loadTSConfig(options.tsConfig || findTSConfig(getCallerFile()));
}

TypeScript.prototype = Object.create(Filter.prototype);
TypeScript.prototype.constructor = TypeScript;

TypeScript.prototype.baseDir = function() {
  return __dirname;
};

/*
 * @private
 *
 * @method optionsString
 * @returns a stringifeid version of the input options
 */
TypeScript.prototype.optionsHash  = function() {
  if (!this._optionsHash) {
    this._optionsHash = crypto.createHash('md5').update(stringify(this.options), 'utf8').digest('hex');
  }
  return this._optionsHash;
};

TypeScript.prototype.cacheKeyProcessString = function(string, relativePath) {
  return this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath);
};

TypeScript.prototype.processString = function (string, relativePath) {
  return ts.transpileModule(string, {compilerOptions: this.options, fileName: relativePath}).outputText;
};
<commit_msg>fix-typo, ensure tsconfig is loaded from options<commit_after>'use strict';

var ts         = require('typescript');
var Filter     = require('broccoli-persistent-filter');
var stringify  = require('json-stable-stringify');
var crypto     = require('crypto');

var getCallerFile = require('get-caller-file');

var loadTSConfig = require('./lib/load-ts-config');
var findTSConfig = require('./lib/find-ts-config');

module.exports = TypeScript;
function TypeScript(inputTree, _options) {
  var options = _options || {};

  if (!(this instanceof TypeScript)) {
    return new TypeScript(inputTree, options);
  }

  Filter.call(this, inputTree, {
    persist: true,
    extensions: ['ts','d.ts'],
    targetExtension: 'js',
    name: 'broccoli-typescript-compiler',
    annotation: options.annotation
  });

  this.options = loadTSConfig(options.tsconfig || findTSConfig(getCallerFile()));
}

TypeScript.prototype = Object.create(Filter.prototype);
TypeScript.prototype.constructor = TypeScript;

TypeScript.prototype.baseDir = function() {
  return __dirname;
};

/*
 * @private
 *
 * @method optionsString
 * @returns a stringifeid version of the input options
 */
TypeScript.prototype.optionsHash  = function() {
  if (!this._optionsHash) {
    this._optionsHash = crypto.createHash('md5').update(stringify(this.options), 'utf8').digest('hex');
  }
  return this._optionsHash;
};

TypeScript.prototype.cacheKeyProcessString = function(string, relativePath) {
  return this.optionsHash() + Filter.prototype.cacheKeyProcessString.call(this, string, relativePath);
};

TypeScript.prototype.processString = function (string, relativePath) {
  return ts.transpileModule(string, {compilerOptions: this.options, fileName: relativePath}).outputText;
};
<|endoftext|>


<commit_before>'use strict';

var mongoose          = require('mongoose'),
      _               = require('lodash'),
      inflection      = require('inflection'),
      slugs           = require('slugs');

function slugify(model, options){
    var slugParts = _.values(_.pick(model, options.source));
    return slugs(slugParts.join(' '));
}

function getModel(document, options){
    var modelName = options.modelName || inflection.singularize(inflection.camelize(document.collection.name));
    return document.collection.conn.model(modelName);
}

function incrementAndSave(document, options, cb){
    var Model = getModel(document, options);
    var params = {};
    var slugbaseKey = options.slugBase;
    var itKey = options.slugIt;
    params[slugbaseKey] = document[slugbaseKey];

    Model.findOne(params).sort('-'+itKey).exec(function(e, doc){
        if(e) return cb(e);

        var it = (doc[itKey] || 0) + Math.ceil(Math.random()*10);

        document[itKey] = it;
        document[options.slugName] = document[slugbaseKey]+'-'+it;

        return document.save(cb);
    });
}

function Slugin(schema, options){
    options = _.defaults(options || {}, Slugin.defaultOptions);
    if(_.isString(options.source))
        options.source = [options.source];
    options.slugIt = options.slugName + '_it';
    options.slugBase = options.slugName + '_base';
    var fields = {};
    fields[options.slugName] = {
        type : String,
        unique: true
    };

    fields[options.slugBase] = {
        type: String,
        index:true
    };

    fields[options.slugIt] = {
        type: Number
    };

    schema.add(fields);

    schema.pre('save', function(next){
        var slugBase = slugify(this,options);
        if(this[options.slugBase] !== slugBase){  // TODO: handle changes to the source
            this[options.slugName] = slugBase;
            this[options.slugBase] = slugBase;
            delete this[options.slugIt];
        }
        next();
    });

    schema.methods.save = function(cb){
        var self = this;
        mongoose.Model.prototype.save.call(self, function(e, model, num){
            if(e && (e.code === 11000  || e.code === 11001) && !!~e.err.indexOf(self[options.slugName])){
                incrementAndSave(self, options, cb);
            }else{
                cb(e,model,num);
            }
        });
    };
}

Slugin.defaultOptions = {
    slugName : 'slug',
    source : 'title',
    modelName : null
};

module.exports = Slugin;<commit_msg>marking all source fields modified now<commit_after>'use strict';

var mongoose          = require('mongoose'),
      _               = require('lodash'),
      chalk = require('chalk'),
      inflection      = require('inflection'),
      slugs           = require('slugs');

function slugify(model, options){
    var slugParts = _.values(_.pick(model, options.source));
    return slugs(slugParts.join(' '));
}

function getModel(document, options){
    var modelName = options.modelName || inflection.singularize(inflection.camelize(document.collection.name));
    return document.collection.conn.model(modelName);
}

function incrementAndSave(document, options, cb){
    var Model = getModel(document, options);
    var params = {};
    var slugbaseKey = options.slugBase;
    var itKey = options.slugIt;
    params[slugbaseKey] = document[slugbaseKey];

    Model.findOne(params).sort('-'+itKey).exec(function(e, doc){
        if(e) return cb(e);

        var it = (doc[itKey] || 0) + Math.ceil(Math.random()*10);

        document[itKey] = it;
        document[options.slugName] = document[slugbaseKey]+'-'+it;
        document.markModified(slugbaseKey);

        _.forEach(options.source, function(item){
            document.markModified(item);
        });

        return document.save(cb);
    });
}

function Slugin(schema, options){
    options = _.defaults(options || {}, Slugin.defaultOptions);
    if(_.isString(options.source))
        options.source = [options.source];
    options.slugIt = options.slugName + '_it';
    options.slugBase = options.slugName + '_base';
    var fields = {};
    fields[options.slugName] = {
        type : String,
        unique: true
    };

    fields[options.slugBase] = {
        type: String,
        index:true
    };

    fields[options.slugIt] = {
        type: Number
    };

    schema.add(fields);

    schema.pre('save', function(next){
        var self = this;
        var slugBase = slugify(this,options);
        console.log('Old base: %s ; New Base: %s', this[options.slugBase], slugBase);
        if(this[options.slugBase] !== slugBase){
            this[options.slugName] = slugBase;
            this[options.slugBase] = slugBase;
            delete this[options.slugIt];
        }
        next();
    });

    schema.methods.save = function(cb){
        var self = this;
        mongoose.Model.prototype.save.call(self, function(e, model, num){
            if(e && (e.code === 11000  || e.code === 11001) && !!~e.err.indexOf(self[options.slugName])){
                incrementAndSave(self, options, cb);
            }else{
                cb(e,model,num);
            }
        });
    };
}

Slugin.defaultOptions = {
    slugName : 'slug',
    source : 'title',
    modelName : null
};

module.exports = Slugin;<|endoftext|>


<commit_before>var os = require('os');
var PLATFORM = os.platform() === 'darwin' ? 'osx' : os.platform();
var ARCH = os.arch() === 'x64' ? 'x86_64' : os.arch();
var versions = require('mongodb-version-list');
var semver = require('semver');
var request = require('request');
var async = require('async');
var defaults = require('lodash.defaults');
var debug = require('debug')('mongodb-download-url');

function mci(opts, fn) {
  if (opts.platform === 'win32') {
    opts.distro = 'windows_64_2k8';
    if (opts.debug) {
      opts.distro += '_debug';
    }
  }
  var url = 'http://mci-motu.10gen.cc:9090/rest/v1/projects/mongodb-mongo-'
    + opts.branch + '/revisions/' + opts.version;
  debug('resolving version via MCI `%s`', url);
  request.get({
    url: url,
    json: true
  }, function(err, res, body) {
    if (err) {
      return fn(err);
    }

    if (res.statusCode === 404) {
      return fn(new Error(body.message));
    }
    debug('got body', body);
    var dl = 'https://s3.amazonaws.com/mciuploads/mongodb-mongo-' + opts.branch
      + '/' + opts.distro + '/' + opts.version + '/binaries';

    var s = 'mongodb_mongo_' + opts.branch + '_' + opts.distro;
    var basename = body.builds.filter(function(b) {
      return b.indexOf(s) > -1;
    })[0];

    // @todo: test across all distros as I believe this may be different for some.
    basename = 'binaries-' + basename;
    fn(null, {
      name: 'mongodb',
      version: opts.version,
      artifact: basename + opts.ext,
      url: dl + '/' + basename + opts.ext
    });
  });
}

function search(query, fn) {
  debug('searching for version', query);
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }

    var found = false;
    for (var i = 0; i < res.length; i++) {
      if (!found && semver.satisfies(res[i], query.version)) {
        found = true;
        fn(null, res[i]);
      }
    }
    if (!found) {
      fn(new Error('Could not find a MongoDB version matching `'+query+'`'));
    }
  });
}

function latest(fn) {
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }
    fn(null, res[0]);
  });
}

function stable(fn) {
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }

    fn(null, res.map(function(v) {
      return semver.parse(v);
    }).filter(function(v) {
      return v.prerelease.length === 0 && v.minor % 2 === 0;
    }).map(function(v) {
      return v.version;
    })[0]);
  });
}

module.exports = function(opts, fn) {
  if (Array.isArray(opts)) {
    var tasks = {};

    opts.map(function(opt) {
      tasks[opt.version] = module.exports.bind(null, opt);
    });

    return async.parallel(tasks, fn);
  }

  if (typeof opts === 'string') {
    opts = {
      version: opts
    };
  }
  var handler = versions;

  defaults(opts, {
    arch: ARCH,
    platform: PLATFORM,
    branch: 'master',
    bits: '64',
    debug: false
  });

  // 64bit -> 64
  opts.bits = '' + opts.bits;
  opts.bits = opts.bits.replace(/[^0-9]/g, '');

  if (opts.platform === 'darwin') {
    opts.platform = 'osx';
  }
  if (opts.platform === 'windows') {
    opts.platform = 'win32';
  }

  opts.ext = opts.platform === 'win32' ? '.zip' : '.tgz';

  if (!opts.distro) {
    if (opts.platform === 'linux') {
      opts.distro = 'linux_' + opts.bits;
    } else if (opts.platform === 'osx') {
      opts.distro = '';
    } else if (opts.enterprise) {
      opts.distro = 'windows-64';
    } else {
      opts.distro = '2008plus-ssl';
    }
    if (opts.debug) {
      opts.distro += '_debug';
    }
  }
  var extraDash;
  if (opts.platform === 'osx') {
    extraDash = '';
  } else {
    extraDash = '-';
  }

  debug('assembled options', opts);

  if (opts.version.length === 40) {
    // A commit hash
    return mci(opts, fn);
  }

  if (opts.version === 'latest' || opts.version === 'unstable') {
    handler = latest;
  } else if (opts.version === 'stable') {
    handler = stable;
  } else {
    handler = search.bind(null, opts);
  }

  handler(function(err, v) {
    if (err) {
      return fn(err);
    }
    var pkg;
    var basename;
    if (opts.enterprise) {
      basename = 'mongodb-' + opts.platform + '-x86_64-enterprise-' + opts.distro + extraDash
        + (opts.debug ? '-debugsymbols-' : '') + v;
      pkg = {
        name: 'mongodb',
        version: v,
        artifact: basename + opts.ext,
        url: 'http://downloads.mongodb.com/' + opts.platform + '/' + basename + opts.ext
      };
    } else {
      basename = 'mongodb-' + opts.platform + '-x86_64-' + opts.distro + extraDash
        + (opts.debug ? '-debugsymbols-' : '') + v;
      pkg = {
        name: 'mongodb',
        version: v,
        artifact: basename + opts.ext,
        url: 'http://fastdl.mongodb.org/' + opts.platform + '/' + basename + opts.ext
      };
    }
    debug('Url: ' + pkg.url);
    fn(null, pkg);
  });
};
<commit_msg>:zap: fix no match error msg<commit_after>var os = require('os');
var PLATFORM = os.platform() === 'darwin' ? 'osx' : os.platform();
var ARCH = os.arch() === 'x64' ? 'x86_64' : os.arch();
var versions = require('mongodb-version-list');
var semver = require('semver');
var request = require('request');
var async = require('async');
var defaults = require('lodash.defaults');
var debug = require('debug')('mongodb-download-url');

function mci(opts, fn) {
  if (opts.platform === 'win32') {
    opts.distro = 'windows_64_2k8';
    if (opts.debug) {
      opts.distro += '_debug';
    }
  }
  var url = 'http://mci-motu.10gen.cc:9090/rest/v1/projects/mongodb-mongo-'
    + opts.branch + '/revisions/' + opts.version;
  debug('resolving version via MCI `%s`', url);
  request.get({
    url: url,
    json: true
  }, function(err, res, body) {
    if (err) {
      return fn(err);
    }

    if (res.statusCode === 404) {
      return fn(new Error(body.message));
    }
    debug('got body', body);
    var dl = 'https://s3.amazonaws.com/mciuploads/mongodb-mongo-' + opts.branch
      + '/' + opts.distro + '/' + opts.version + '/binaries';

    var s = 'mongodb_mongo_' + opts.branch + '_' + opts.distro;
    var basename = body.builds.filter(function(b) {
      return b.indexOf(s) > -1;
    })[0];

    // @todo: test across all distros as I believe this may be different for some.
    basename = 'binaries-' + basename;
    fn(null, {
      name: 'mongodb',
      version: opts.version,
      artifact: basename + opts.ext,
      url: dl + '/' + basename + opts.ext
    });
  });
}

function search(query, fn) {
  debug('searching for version', query);
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }

    var found = false;
    for (var i = 0; i < res.length; i++) {
      if (!found && semver.satisfies(res[i], query.version)) {
        found = true;
        fn(null, res[i]);
      }
    }
    if (!found) {
      fn(new Error('Could not find a MongoDB version matching `'+JSON.stringify(query)+'`'));
    }
  });
}

function latest(fn) {
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }
    fn(null, res[0]);
  });
}

function stable(fn) {
  versions(function(err, res) {
    if (err) {
      return fn(err);
    }

    fn(null, res.map(function(v) {
      return semver.parse(v);
    }).filter(function(v) {
      return v.prerelease.length === 0 && v.minor % 2 === 0;
    }).map(function(v) {
      return v.version;
    })[0]);
  });
}

module.exports = function(opts, fn) {
  if (Array.isArray(opts)) {
    var tasks = {};

    opts.map(function(opt) {
      tasks[opt.version] = module.exports.bind(null, opt);
    });

    return async.parallel(tasks, fn);
  }

  if (typeof opts === 'string') {
    opts = {
      version: opts
    };
  }
  var handler = versions;

  defaults(opts, {
    arch: ARCH,
    platform: PLATFORM,
    branch: 'master',
    bits: '64',
    debug: false
  });

  // 64bit -> 64
  opts.bits = '' + opts.bits;
  opts.bits = opts.bits.replace(/[^0-9]/g, '');

  if (opts.platform === 'darwin') {
    opts.platform = 'osx';
  }
  if (opts.platform === 'windows') {
    opts.platform = 'win32';
  }

  opts.ext = opts.platform === 'win32' ? '.zip' : '.tgz';

  if (!opts.distro) {
    if (opts.platform === 'linux') {
      opts.distro = 'linux_' + opts.bits;
    } else if (opts.platform === 'osx') {
      opts.distro = '';
    } else if (opts.enterprise) {
      opts.distro = 'windows-64';
    } else {
      opts.distro = '2008plus-ssl';
    }
    if (opts.debug) {
      opts.distro += '_debug';
    }
  }
  var extraDash;
  if (opts.platform === 'osx') {
    extraDash = '';
  } else {
    extraDash = '-';
  }

  debug('assembled options', opts);

  if (opts.version.length === 40) {
    // A commit hash
    return mci(opts, fn);
  }

  if (opts.version === 'latest' || opts.version === 'unstable') {
    handler = latest;
  } else if (opts.version === 'stable') {
    handler = stable;
  } else {
    handler = search.bind(null, opts);
  }

  handler(function(err, v) {
    if (err) {
      return fn(err);
    }
    var pkg;
    var basename;
    if (opts.enterprise) {
      basename = 'mongodb-' + opts.platform + '-x86_64-enterprise-' + opts.distro + extraDash
        + (opts.debug ? '-debugsymbols-' : '') + v;
      pkg = {
        name: 'mongodb',
        version: v,
        artifact: basename + opts.ext,
        url: 'http://downloads.mongodb.com/' + opts.platform + '/' + basename + opts.ext
      };
    } else {
      basename = 'mongodb-' + opts.platform + '-x86_64-' + opts.distro + extraDash
        + (opts.debug ? '-debugsymbols-' : '') + v;
      pkg = {
        name: 'mongodb',
        version: v,
        artifact: basename + opts.ext,
        url: 'http://fastdl.mongodb.org/' + opts.platform + '/' + basename + opts.ext
      };
    }
    debug('Url: ' + pkg.url);
    fn(null, pkg);
  });
};
<|endoftext|>