<commit_before>#! /usr/bin/env node
// Native
const path = require('path')

// Packages
const args = require('args')
const chalk = require('chalk')
const ora = require('ora')

// Ours
const gest = require('../src/index')
const REPL = require('../src/REPL')
const {
  readFile,
  checkPath,
  flagsToOptions,
  colorResponse,
  colorizeGraphQL,
  readDir,
  errorMessage
} = require('../src/util')

const { getGraphQL, getPackageInfo } = require('../src/import')
const GraphQL = getGraphQL()

args
  .option(['S', 'schema'], 'Path to your GraphQL schema')
  .option(['H', 'header'], 'Set HTTP request header')
  .option(['I', 'inspect'], 'Print your GraphQL schema types')
  .option(['B', 'baseUrl'], 'Base URL for sending HTTP requests')
  .option(['A', 'all'], 'Run `gest` for all *.(gql|graphql|query) files')
  .option(['P', 'print'], 'Pretty print the GraphQL query')

const flags = args.parse(process.argv, {
  value: '[query | queryPath]',
  mainColor: ['magenta', 'bold'], // following the GraphQL brand
  usageFilter: info => info.replace('[command] ', '')
})

const getQueryString = q =>
  checkPath(path.join(process.cwd(), q))
    .then(readFile)
    .catch(() => q)

const wrapLogging = p => p.then(message => console.log(`\n${message}`)).catch(console.log)

try {
  let schema
  const options = Object.assign({ schema: 'schema.js' }, getPackageInfo(), flagsToOptions(flags))

  try {
    schema = require(path.join(process.cwd(), options.schema))
  } catch (e) {
    // schema is required unless sending over HTTP
    if (!options.baseURL) throw e
  }

  if (flags.inspect) {
    console.log('\n' + colorizeGraphQL(GraphQL.printSchema(schema)))
    process.exit()
  }

  if (flags.all) {
    readDir(process.cwd(), /.*\.(query|graphql|gql)$/i)
      .then(values => {
        if (!values.length) {
          console.log(
            `\n${chalk.yellow('Warning')}: no files matching *.(graphql|gql|query) were found`
          )
        } else {
          console.log()
        }
        return values
      })
      .then(values =>
        Promise.all(
          values.map(v => {
            const paths = v.replace(process.cwd(), '.').split('/')
            // separate file from rest of path
            const fileName = paths.pop()
            const rep = chalk.dim(paths.concat('').join('/')).concat(fileName)
            const spinner = ora({ text: rep, color: 'magenta' }).start()
            return readFile(v)
              .then(gest(schema, Object.assign(options, { verbose: false })))
              .then(value => {
                if (value.errors && value.data) spinner.warn()
                else if (value.errors) spinner.fail(`${rep}\n    -  ${value.errors}`)
                else spinner.succeed()
                return value
              })
              .catch(console.log)
          })
        )
      )
      .then(() => console.log())
      .catch(console.log)
  } else {
    if (args.sub && args.sub.length) {
      if (flags.print) {
        const q = args.sub[0] // only print first value
        wrapLogging(
          getQueryString(q)
            .then(GraphQL.parse)
            .then(GraphQL.print)
        )
      } else {
        args.sub.map(q =>
          wrapLogging(
            getQueryString(q)
              .then(gest(schema, options))
              .then(colorResponse)
              .then(message => `${message}\n`)
          )
        )
      }
    } else {
      // Open REPL
      REPL(schema, options)
    }
  }
} catch (e) {
  console.log(errorMessage(e))
}
<commit_msg>fix pretty printing<commit_after>#! /usr/bin/env node
// Native
const path = require('path')

// Packages
const args = require('args')
const chalk = require('chalk')
const ora = require('ora')

// Ours
const gest = require('../src/index')
const REPL = require('../src/REPL')
const {
  readFile,
  checkPath,
  flagsToOptions,
  colorResponse,
  colorizeGraphQL,
  readDir,
  errorMessage
} = require('../src/util')

const { getGraphQL, getPackageInfo } = require('../src/import')
const GraphQL = getGraphQL()

args
  .option(['S', 'schema'], 'Path to your GraphQL schema')
  .option(['H', 'header'], 'Set HTTP request header')
  .option(['I', 'inspect'], 'Print your GraphQL schema types')
  .option(['B', 'baseUrl'], 'Base URL for sending HTTP requests')
  .option(['A', 'all'], 'Run `gest` for all *.(gql|graphql|query) files')
  .option(['P', 'print'], 'Pretty print the GraphQL query')

const flags = args.parse(process.argv, {
  value: '[query | queryPath]',
  mainColor: ['magenta', 'bold'], // following the GraphQL brand
  usageFilter: info => info.replace('[command] ', '')
})

const getQueryString = q =>
  checkPath(path.join(process.cwd(), q))
    .then(readFile)
    .catch(() => q)

const wrapLogging = p => p.then(message => console.log(`\n${message}`)).catch(console.log)

try {
  let schema
  const options = Object.assign({ schema: 'schema.js' }, getPackageInfo(), flagsToOptions(flags))

  try {
    schema = require(path.join(process.cwd(), options.schema))
  } catch (e) {
    // schema is required unless sending over HTTP
    if (!options.baseURL) throw e
  }

  if (flags.inspect) {
    console.log('\n' + colorizeGraphQL(GraphQL.printSchema(schema)))
    process.exit()
  }

  if (flags.all) {
    readDir(process.cwd(), /.*\.(query|graphql|gql)$/i)
      .then(values => {
        if (!values.length) {
          console.log(
            `\n${chalk.yellow('Warning')}: no files matching *.(graphql|gql|query) were found`
          )
        } else {
          console.log()
        }
        return values
      })
      .then(values =>
        Promise.all(
          values.map(v => {
            const paths = v.replace(process.cwd(), '.').split('/')
            // separate file from rest of path
            const fileName = paths.pop()
            const rep = chalk.dim(paths.concat('').join('/')).concat(fileName)
            const spinner = ora({ text: rep, color: 'magenta' }).start()
            return readFile(v)
              .then(gest(schema, Object.assign(options, { verbose: false })))
              .then(value => {
                if (value.errors && value.data) spinner.warn()
                else if (value.errors) spinner.fail(`${rep}\n    -  ${value.errors}`)
                else spinner.succeed()
                return value
              })
              .catch(console.log)
          })
        )
      )
      .then(() => console.log())
      .catch(console.log)
  } else {
    if (flags.print) {
      const q = args.sub[0] || flags.print
      return wrapLogging(
        getQueryString(q)
          .then(GraphQL.parse)
          .then(GraphQL.print)
      )
    }
    if (args.sub && args.sub.length) {
      args.sub.map(q =>
        wrapLogging(
          getQueryString(q)
            .then(gest(schema, options))
            .then(colorResponse)
            .then(message => `${message}\n`)
        )
      )
    } else {
      // Open REPL
      REPL(schema, options)
    }
  }
} catch (e) {
  console.log(errorMessage(e))
}
<|endoftext|>


<commit_before>var obj_canvas,
obj_c,
cp_canvas = null;

var canvas
var video_canvas,
vid_c;

var brown_const=0;

var vid_width = 640;
var vid_height = 480;

var canvas;
var context;

var vid_width = 640;
var vid_height = 480;

var l = 80,
	n = 4,
	v = 1/4;

function setupD3() {
    canvas = d3.select("#canvasArea").append("canvas")
        .attr("width", vid_width)
        .attr("height", vid_height);

    context = canvas.node().getContext("2d");

	var w = 640,
    	h = 480,
    	m = 20,
    	radius = 50,
    	degrees = 180 / Math.PI;

	var objects = d3.range(n).map(function() {
  		var x = 40 + Math.random() * (w-40), y = 40 + Math.random() * (h-40);
  		return {
    		vx: 0,
    		vy: 0,
    		path: d3.range(m).map(function() { return [x, y]; }),
    		count: 0,
    		active: true,
    		color: "#FA6600"
  		};
	});

	var svg = d3.select("#canvasArea").append("svg:svg")
    	.attr("width", vid_width)
    	.attr("height", vid_height);

	var g = svg.selectAll("g")
    	.data(objects)
		.enter().append("svg:g");

	var box = g.append("svg:rect")
		.attr("x", -l/2)
		.attr("y", -l/2)
    	.attr("width", l)
    	.attr("height", l);

	function drawObjects(){
		for (var i = -1; ++i < n;) {
    		var object = objects[i],
        		x = object.path[0][0],
        		y = object.path[0][1];

    		// stuck at the walls.
    		if (x < 0)
    		{
    			object.path[0][0] = 0;
    		}
    		if(x > w-l)
    		{
    			object.path[0][0] = w-l;
    		}
    		if (y < 0)
    		{
    			object.path[0][1] = 0;
    		}
    		if (y > h-l)
    		{
    			object.path[0][1] = h-l;
    		}
  		}

		box.attr("stroke", function(d,i){
			return d.color;
		});

  		box.attr("transform", function(d) {
    		return "translate(" + d.path[0] + ")";
  		});
  	}

	d3.timer(function() {
  		drawObjects();
	});

	window.setInterval(getVideo, 1000/20);

	function getVideo(){
        getVidFrame("http://171.65.102.132:8080/?action=snapshot?t=" + new Date().getTime(), function(image) {
            context.clearRect(0, 0, vid_width, vid_height);
            context.drawImage(image, 0, 0, vid_width, vid_height);
        });

    	function getVidFrame(path, callback) {
            var image = new Image;
            image.onload = function() {
                callback(image);
                compareFrame(image);
            };
            image.src = path;
        }
    }

    function compareFrame(img1) {
		// just compare if there are two pictures
  		if ( img2 != null ) {
    		var res=[0,0,0,0];
    		try {
    			for (var i = -1; ++i < n;){
    				res = compare(img1, img2, objects[i].path[0][0], objects[i].path[0][1], 14, l/2+10);
    			    	if ((res[0]>400)||(res[1]>400)||(res[2]>400)||(res[3]>400)){
            				res[0]=0;res[1]=0;res[2]=0;res[3]=0;
    					}
    				objects[i].path[0][0]+=(res[0]+res[2]-res[1]-res[3])*v+(Math.random()-0.5)*20*brown_const
    				objects[i].path[0][1]+=(res[0]+res[1]-res[2]-res[3])*v+(Math.random()-0.5)*20*brown_const
					objects[i].color = ((res[0]+res[1]+res[2]+res[3])>0)?"#FDAC0D":"#FA6600";
    			}
    		}
    	catch(e) {
    			// errors
    		}
		}
		img2 = img1;
	}

}

function game(){
	switch(gamephase)
	{
		case 'pre-game':
			// draw intro
		break;
		case 'game-rest':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.fillText('New target ...',200,20);
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
		break;
		case 'game-action':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.fillText('Run! Run! Run!',200,20);
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
		break;
		case 'gameover':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.textAlign="start";
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
    		vid_c.fillStyle = "rgba(253,172,13,1)";
    		vid_c.font="40pt sans-serif";
    		vid_c.textAlign="center";
    		vid_c.fillText('GAME OVER',vid_width/2,vid_height/2-100);
    		vid_c.fillStyle = "#fff";
    		vid_c.font="20pt sans-serif";
    		vid_c.fillText(username+' scored '+score_val,vid_width/2,vid_height/2);
		break;
		default:
			vid_c.fillStyle = "#fff";
			vid_c.font="14px sans-serif";
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
	}
}

var shipX=vid_width/2,
	shipY=vid_height/2,
	shipRad,
	shipL=20,
	starX=40,
	starY=20;
var gamelevel;
var int_star=-1;
var int_engine=-1;
var engine = false;
var rest = false;
var starTimer;
var enginerTimer;
var gamephase;
var score_val = 0;
var actionTimer;
var unit=30;

function setGameAction(){
	actionTimer = window.requestAnimationFrame(actionLoop);
}

function setbackPreGame(){
    score_val = 0;
    hit = new Array();
    gamelevel=1;

	shipX = vid_width/2;
    shipY = vid_height/2;

    gamephase='pre-game';
}

function setGameOver(){
  	window.cancelAnimationFrame(actionTimer);
    actionTimer = undefined;
}

function actionLoop(){
	switch(gamephase)
	{
		case 'rest':
  			if(rest==false)
			{
				rest=true;
				int_star=gamelevel+6;
				getStarLocation(); // get new starX, starY, shipRad
				starTimer=window.setInterval(showStar,500);
			}
			drawStar(shipX,shipY,starX,starY,gamelevel-(int_star-6));
			drawShip(shipX,shipY,shipRad);
			actionTimer = window.requestAnimationFrame(gameLoop);
  		break;
		case 'engine':
			console.log(hit);
  			if(hit>0)
			{
				window.clearInterval(engineTimer);
				engine=false;
				rest=false;
				int_star=-1;
				int_engine=-1;
				gamephase='gameover';
				gamelevel=-1;
			}
			else
			{
				score_val=score_val+10;
				if(engine==false)
				{
					engine=true;
					int_engine=gamelevel+4;
					engineTimer=window.setInterval(runEngine,500);
				}
			}
			drawStar(shipX,shipY,starX,starY,gamelevel-(int_star-6));
			drawShip(shipX,shipY,shipRad);
  		break;
	}
}

function gameOver(){
    var msg = {type:'sendscore', user:username, score:score_val};
    socket.json.send(msg);
}

/*******************************************************************************
  Copyright (C) 2009 Tom Stoeveken
  This program is free software;
  you can redistribute it and/or modify it under the terms of the
  GNU General Public License, version 2.
  See the file COPYING for details.
*******************************************************************************/

var img1 = null;
var img2 = null;
var md_canvas = null;

function setupMotionDetection() {
  md_canvas = document.getElementById('mdCanvas');
  test_canvas = document.getElementById('testCanvas');
  md_canvas.width = vid_width;
  md_canvas.height = vid_height;
}

/*
  compare two images and count the differences

  input.: image1 and image2 are Image() objects
  input.: threshold specifies by how much the color value of a pixel
          must differ before they are regarded to be different

  return: number of different pixels
*/

function compare(image1, image2, ptX, ptY, threshold, ObjR) {
  var movement = new Array(0,0,0,0);
  var md_ctx = md_canvas.getContext("2d");
  var width = md_canvas.width/2, height = md_canvas.height/2;

  // copy images into canvas element
  // these steps scale the images and decodes the image data
  md_ctx.drawImage(image1, 0, 0, width, height);
  md_ctx.drawImage(image2, width, 0, width, height);

  // this makes r,g,b,alpha data of images available
  var pixels1 = md_ctx.getImageData(0, 0, width, height);
  var pixels2 = md_ctx.getImageData(width, 0, width, height);

  // substract picture1 from picture2
  // if they differ set color value to max,
  // if the difference is below threshold set difference to 0.
  for (var x = Math.round((ptX-ObjR)/2); x < Math.round((ptX+ObjR)/2); x++) {
    for (var y = Math.round((ptY-ObjR)/2); y < Math.round((ptY+ObjR)/2); y++) {

      // each pixel has a red, green, blue and alpha value
      // all values are stored in a linear array
      var i = x*4 + y*4*pixels1.width;

      var ch0 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
      var ch1 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
      var ch2 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;

      // count differing pixels
      var n = (x<Math.round(ptX/2))?0:1;
      var m = (y<Math.round(ptY/2))?0:2;
      movement[n+m] += Math.min(1, ch0 + ch1 + ch2);
    }
  }
  return movement;
}<commit_msg>sliders<commit_after>var obj_canvas,
obj_c,
cp_canvas = null;

var canvas
var video_canvas,
vid_c;

var brown_const=0;

var vid_width = 640;
var vid_height = 480;

var canvas;
var context;

var vid_width = 640;
var vid_height = 480;

var l = 80,
	n = 4,
	v = 1/4;

function setupD3() {
    canvas = d3.select("#canvasArea").append("canvas")
        .attr("width", vid_width)
        .attr("height", vid_height);

    context = canvas.node().getContext("2d");

	var w = 640,
    	h = 480,
    	m = 20,
    	radius = 50,
    	degrees = 180 / Math.PI;

	var objects = d3.range(n).map(function() {
  		var x = 40 + Math.random() * (w-40), y = 40 + Math.random() * (h-40);
  		return {
    		vx: 0,
    		vy: 0,
    		path: d3.range(m).map(function() { return [x, y]; }),
    		count: 0,
    		active: true,
    		color: "#FA6600"
  		};
	});

	var svg = d3.select("#canvasArea").append("svg:svg")
    	.attr("width", vid_width)
    	.attr("height", vid_height);

	var g = svg.selectAll("g")
    	.data(objects)
		.enter().append("svg:g");

	var box = g.append("svg:rect");

	function drawObjects(){
		for (var i = -1; ++i < n;) {
    		var object = objects[i],
        		x = object.path[0][0],
        		y = object.path[0][1];

    		// stuck at the walls.
    		if (x < 0)
    		{
    			object.path[0][0] = 0;
    		}
    		if(x > w-l)
    		{
    			object.path[0][0] = w-l;
    		}
    		if (y < 0)
    		{
    			object.path[0][1] = 0;
    		}
    		if (y > h-l)
    		{
    			object.path[0][1] = h-l;
    		}
    	}
		box.attr("width", l);
		box.attr("height",l);
		box.attr("stroke", function(d,i){
			return d.color;
		});

  		box.attr("transform", function(d) {
    		return "translate(" + d.path[0] + ")";
  		});
  	}

	d3.timer(function() {
  		drawObjects();
	});

	window.setInterval(getVideo, 1000/20);

	function getVideo(){
        getVidFrame("http://171.65.102.132:8080/?action=snapshot?t=" + new Date().getTime(), function(image) {
            context.clearRect(0, 0, vid_width, vid_height);
            context.drawImage(image, 0, 0, vid_width, vid_height);
        });

    	function getVidFrame(path, callback) {
            var image = new Image;
            image.onload = function() {
                callback(image);
                compareFrame(image);
            };
            image.src = path;
        }
    }

    function compareFrame(img1) {
		// just compare if there are two pictures
  		if ( img2 != null ) {
    		var res=[0,0,0,0];
    		try {
    			for (var i = -1; ++i < n;){
    				res = compare(img1, img2, objects[i].path[0][0], objects[i].path[0][1], 14, l/2+10);
    			    	if ((res[0]>400)||(res[1]>400)||(res[2]>400)||(res[3]>400)){
            				res[0]=0;res[1]=0;res[2]=0;res[3]=0;
    					}
    				objects[i].path[0][0]+=(res[0]+res[2]-res[1]-res[3])*v+(Math.random()-0.5)*20*brown_const
    				objects[i].path[0][1]+=(res[0]+res[1]-res[2]-res[3])*v+(Math.random()-0.5)*20*brown_const
					objects[i].color = ((res[0]+res[1]+res[2]+res[3])>0)?"#FDAC0D":"#FA6600";
    			}
    		}
    	catch(e) {
    			// errors
    		}
		}
		img2 = img1;
	}

}

function game(){
	switch(gamephase)
	{
		case 'pre-game':
			// draw intro
		break;
		case 'game-rest':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.fillText('New target ...',200,20);
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
		break;
		case 'game-action':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.fillText('Run! Run! Run!',200,20);
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
		break;
		case 'gameover':
    		vid_c.fillStyle = "#fff";
    		vid_c.font="14px sans-serif";
    		vid_c.textAlign="start";
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
    		vid_c.fillStyle = "rgba(253,172,13,1)";
    		vid_c.font="40pt sans-serif";
    		vid_c.textAlign="center";
    		vid_c.fillText('GAME OVER',vid_width/2,vid_height/2-100);
    		vid_c.fillStyle = "#fff";
    		vid_c.font="20pt sans-serif";
    		vid_c.fillText(username+' scored '+score_val,vid_width/2,vid_height/2);
		break;
		default:
			vid_c.fillStyle = "#fff";
			vid_c.font="14px sans-serif";
    		vid_c.fillText('player : ' + username + '  score : ' +score_val ,20,20);
	}
}

var shipX=vid_width/2,
	shipY=vid_height/2,
	shipRad,
	shipL=20,
	starX=40,
	starY=20;
var gamelevel;
var int_star=-1;
var int_engine=-1;
var engine = false;
var rest = false;
var starTimer;
var enginerTimer;
var gamephase;
var score_val = 0;
var actionTimer;
var unit=30;

function setGameAction(){
	actionTimer = window.requestAnimationFrame(actionLoop);
}

function setbackPreGame(){
    score_val = 0;
    hit = new Array();
    gamelevel=1;

	shipX = vid_width/2;
    shipY = vid_height/2;

    gamephase='pre-game';
}

function setGameOver(){
  	window.cancelAnimationFrame(actionTimer);
    actionTimer = undefined;
}

function actionLoop(){
	switch(gamephase)
	{
		case 'rest':
  			if(rest==false)
			{
				rest=true;
				int_star=gamelevel+6;
				getStarLocation(); // get new starX, starY, shipRad
				starTimer=window.setInterval(showStar,500);
			}
			drawStar(shipX,shipY,starX,starY,gamelevel-(int_star-6));
			drawShip(shipX,shipY,shipRad);
			actionTimer = window.requestAnimationFrame(gameLoop);
  		break;
		case 'engine':
			console.log(hit);
  			if(hit>0)
			{
				window.clearInterval(engineTimer);
				engine=false;
				rest=false;
				int_star=-1;
				int_engine=-1;
				gamephase='gameover';
				gamelevel=-1;
			}
			else
			{
				score_val=score_val+10;
				if(engine==false)
				{
					engine=true;
					int_engine=gamelevel+4;
					engineTimer=window.setInterval(runEngine,500);
				}
			}
			drawStar(shipX,shipY,starX,starY,gamelevel-(int_star-6));
			drawShip(shipX,shipY,shipRad);
  		break;
	}
}

function gameOver(){
    var msg = {type:'sendscore', user:username, score:score_val};
    socket.json.send(msg);
}

/*******************************************************************************
  Copyright (C) 2009 Tom Stoeveken
  This program is free software;
  you can redistribute it and/or modify it under the terms of the
  GNU General Public License, version 2.
  See the file COPYING for details.
*******************************************************************************/

var img1 = null;
var img2 = null;
var md_canvas = null;

function setupMotionDetection() {
  md_canvas = document.getElementById('mdCanvas');
  test_canvas = document.getElementById('testCanvas');
  md_canvas.width = vid_width;
  md_canvas.height = vid_height;
}

/*
  compare two images and count the differences

  input.: image1 and image2 are Image() objects
  input.: threshold specifies by how much the color value of a pixel
          must differ before they are regarded to be different

  return: number of different pixels
*/

function compare(image1, image2, ptX, ptY, threshold, ObjR) {
  var movement = new Array(0,0,0,0);
  var md_ctx = md_canvas.getContext("2d");
  var width = md_canvas.width/2, height = md_canvas.height/2;

  // copy images into canvas element
  // these steps scale the images and decodes the image data
  md_ctx.drawImage(image1, 0, 0, width, height);
  md_ctx.drawImage(image2, width, 0, width, height);

  // this makes r,g,b,alpha data of images available
  var pixels1 = md_ctx.getImageData(0, 0, width, height);
  var pixels2 = md_ctx.getImageData(width, 0, width, height);

  // substract picture1 from picture2
  // if they differ set color value to max,
  // if the difference is below threshold set difference to 0.
  for (var x = Math.round((ptX-ObjR)/2); x < Math.round((ptX+ObjR)/2); x++) {
    for (var y = Math.round((ptY-ObjR)/2); y < Math.round((ptY+ObjR)/2); y++) {

      // each pixel has a red, green, blue and alpha value
      // all values are stored in a linear array
      var i = x*4 + y*4*pixels1.width;

      var ch0 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
      var ch1 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;
      var ch2 = ((pixels1.data[i] - pixels2.data[i])>threshold)?255:0;

      // count differing pixels
      var n = (x<Math.round(ptX/2))?0:1;
      var m = (y<Math.round(ptY/2))?0:2;
      movement[n+m] += Math.min(1, ch0 + ch1 + ch2);
    }
  }
  return movement;
}<|endoftext|>


<commit_before>/*
 Copyright (c) 2012-2013 by Tawi Jordan - ๖ۣۜĐJ - ɴᴇᴏɴ - TFL

 Permission to use this software for any purpose without fee is hereby granted, provided
 that the above copyright notice and this permission notice appear in all copies.

 Permission to copy and/or edit this software or parts of it for any purpose is permitted,
 provided that the following points are followed.
 - The above copyright notice and this permission notice appear in all copies
 - Within two (2) days after modification is proven working, any modifications are send back
   to the original authors to be inspected with the goal of inclusion in the official software
 - Any edited version are only test versions and not permitted to be run as a final product
 - Any edited version aren't to be distributed
 - Any edited version have the prerelease version set to something that can be distinguished
   from a version used in the original software

TERMS OF REPRODUCTION USE

Failure to follow these terms will result in me getting very angry at you
and having your software tweaked or removed if possible. Either way, you're
still an idiot for not following such a basic rule.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

 * NOTE:  PLEASE CONTACT DJ-NEON FOR THIS SCRIPT (DO NOT CHANGE ANYTHING ON THIS SCRIPT OR USE AND EDIT THIS SCRIPT WHICH
 * WAS WRITTEN BY IT'S RIGHTFUL OWNER: DJ NOEN)
 *
 * @Author:    Tawi Jordan - ๖ۣۜĐJ - ɴᴇᴏɴ - TFL (Member. on Plug.dj)
 *
 */

var path = 'http://pastebin.com/raw.php?i=';

function message(contents) {
        var msg = '
PlugWoot  ' + contents + '
';
        $('#chat-messages').append(msg);
}

var scriptFail = window.setTimeout(function() {
    message('Oops! An Error Occurred');
  }, 2000);

$.getScript(path + 'rM15aY1b' , function() {message("PlugWoot V."+ pw.version+" is now available!");
  window.clearTimeout(scriptFail);
});
<commit_msg>Update Plugwoot.js<commit_after>/*
 Copyright (c) 2012-2013 by Tawi Jordan - ๖ۣۜĐJ - ɴᴇᴏɴ - TFL

 Permission to use this software for any purpose without fee is hereby granted, provided
 that the above copyright notice and this permission notice appear in all copies.

 Permission to copy and/or edit this software or parts of it for any purpose is permitted,
 provided that the following points are followed.
 - The above copyright notice and this permission notice appear in all copies
 - Within two (2) days after modification is proven working, any modifications are send back
   to the original authors to be inspected with the goal of inclusion in the official software
 - Any edited version are only test versions and not permitted to be run as a final product
 - Any edited version aren't to be distributed
 - Any edited version have the prerelease version set to something that can be distinguished
   from a version used in the original software

TERMS OF REPRODUCTION USE

Failure to follow these terms will result in me getting very angry at you
and having your software tweaked or removed if possible. Either way, you're
still an idiot for not following such a basic rule.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

 * NOTE:  PLEASE CONTACT DJ-NEON FOR THIS SCRIPT (DO NOT CHANGE ANYTHING ON THIS SCRIPT OR USE AND EDIT THIS SCRIPT WHICH
 * WAS WRITTEN BY IT'S RIGHTFUL OWNER: DJ NOEN)
 *
 * @Author:    Tawi Jordan - ๖ۣۜĐJ - ɴᴇᴏɴ - TFL (Member. on Plug.dj)
 *
 */

var path = 'http://pastebin.com/raw.php?i=';

function message(contents) {
        var msg = '
PlugWoot  ' + contents + '
';
        $('#chat-messages').append(msg);
}

var scriptFail = window.setTimeout(function() {
    message('Oops! An Error Occurred');
  }, 2000);

$.getScript(path + 'rM15aY1b' , function() {message("v"+ pw.version+" is now available!");
  window.clearTimeout(scriptFail);
});
<|endoftext|>


<commit_before>/*globals app, console, R, Backbone, Firebase, rdioUserKey, firebaseToken, firebaseRootUrl, firebaseRef */

window.app = window.app || {};

app.currentUserKey = rdioUserKey;

app.roomUrl = firebaseRootUrl;

app.Player = Backbone.Firebase.Model.extend({

  isMaster: function () {
    return this.get('masterUserKey') === app.currentUserKey;
  },

  firebase: app.roomUrl + '/player'

});

app.Track = Backbone.Model.extend({
  LIKE: 'like',
  DISLIKE: 'dislike',

  getVoteRef: function() {
    return this.collection.firebase.child(this.get('id')).child('votes');
  },

  vote: function(newVote) {
    console.info('Voting', newVote, 'for', this.get('trackKey'));
    this.getVoteRef().child(app.currentUserKey).set(newVote);
  },

  upVote: function() {
    this.vote(this.LIKE);
  },

  downVote: function() {
    this.vote(this.DISLIKE);
  },

  getVoteCount: function(voteType) {
    var votes = _.values(this.get('votes'));
    var count = _.reduce(votes, function(num, vote) {
      if (vote === voteType) {
        return num + 1;
      } else {
        return num;
      }
    }, 0);
    return count;
  },

  getVoteCounts: function() {
    var likeCount = this.getVoteCount(this.LIKE);
    var dislikeCount = this.getVoteCount(this.DISLIKE);

    console.log('Did vote count:', 'like', likeCount, 'dislike', dislikeCount);
    return {
      upVotes: likeCount,
      downVotes: dislikeCount,
      totalVotes: likeCount - dislikeCount
    };
  }

});

app.TrackList = Backbone.Firebase.Collection.extend({
  model: app.Track,

  firebase: app.roomUrl + '/queue',

  comparator: function(track) {
    var counts = track.getVoteCounts();
    return (counts.upVotes - counts.downVotes) * -1;
  }

});

app.queue = new app.TrackList();
app.playState = new app.Player();

app.NowPlayingView = Backbone.View.extend({
  el: '#now-playing',

  template: _.template($('#now-playing-template').html()),

  events: {
    'click #player-play': 'playNext'
  },

  initialize: function() {
    var self = this;
    this.rdioTrackKey = null;
    this.activeUsers = chat.activeUsers;
    this.playState = app.playState;

    this.listenTo(this.playState, 'change:masterUserKey', this._onMasterUserKeyChange);

    R.player.on('change:playingTrack', this._onPlayingTrackChange, this);

    if (this.playState.get('masterUserKey') === undefined) {
      this.findNewMasterKey();
    }

    if (this.playState.isMaster()) {
      this.initMasterStatus();
    } else {
      this.initSlaveStatus();
    }
  },

  /**
   * Handles changes to masterUserKey
   */
  _onMasterUserKeyChange: function(model, newValue, options) {
    console.info('change:masterUserKey', newValue);
    if (newValue === undefined) {
      this.findNewMasterKey();
    } else if(newValue === app.currentUserKey) {
      this.initMasterStatus();
    } else {
      this.initSlaveStatus();
    }
  },

  /**
   * Handles changes to the currently playing track
   */
  _onPlayingTrackChange: function(newValue) {
    if (newValue !== null) {
      this.rdioTrackKey = newValue.get('key');
      this.render();
    }
  },

  render: function() {
    var self = this;

    if (this.rdioTrackKey) {
      R.request({
        method: 'get',
        content: {
          keys: this.rdioTrackKey,
          extras: 'streamRegions,shortUrl,bigIcon'
        },
        success: function(response) {
          var data = _.extend({
            'track': response.result[self.rdioTrackKey]
          });

          self.$el.html(self.template(data));
          self.$el.show();
        },
        error: function(response) {
          console.log('Unable to get tack information for', self.rdioTrackKey);
        }
      });

    } else {
      this.$el.hide();
    }
    return this;
  },

  playNext: function() {
    if (!app.queue.length) {
      this.playState.set({
        'playState': R.player.PLAYSTATE_STOPPED,
        'playingTrack': null
      });
      return;
    }

    var queueItem = app.queue.shift();
    console.log('Playing next track', queueItem);
    this.addToHistory(queueItem);

    this.playState.set({
      'playingTrack': queueItem.toJSON()
    });

    R.player.play({
      source: queueItem.get('trackKey')
    });
  },

  addToHistory: function(queueItem) {
    // R.request here instead of in render, cause it's historical.
    var trackKey = queueItem.get('trackKey');
    R.request({
      method: 'get',
      content: {
        keys: trackKey,
        extras: '-*,name,artist,icon'
      },
      success: function(res) {
        var track = res.result[trackKey];
        var messageData = {
          type: 'NewTrack',
          title: track.name,
          artist: track.artist,
          iconUrl: track.icon,
          timestamp: (new Date()).toISOString()
        };

        chat.messageHistory.add(messageData);
      }
    });
  },

  findNewMasterKey: function() {
    var self = this;
    this.playState.firebase.child('masterUserKey').transaction(function(currentValue) {
      console.log('Finding a new masterUserKey:', currentValue);
      var newUserKey = app.currentUserKey;

      if (self.activeUsers) {
        var onlineUsers = self.activeUsers.where({isOnline:true});
        var sortedOnlineUsers = _.sortBy(onlineUsers,
          function(user) { return user.get('id'); });

        newUserKey = sortedOnlineUsers[0].get('id');
      }

      if (currentValue === null) {
        return newUserKey;
      } else {
        return undefined;
      }
    }, function(error, committed, snapshot) {
      if (error) {
        console.warn('Error when setting masterUserKey:', error.message);
        if (committed) {
          console.warn('Transaction was committed:', snapshot);
        } else {
          console.warn('Transaction was not committed:', snapshot);
        }
      }
    });
  },

  /**
   * Called when this client assumes control of the player
   **/
  initMasterStatus: function() {
    var self = this;
    console.info('Becoming master');
    self.destroySlaveStatus();

    if (app.playState.get('playState') == R.player.PLAYSTATE_PLAYING) {
      R.player.play({
        source: app.playState.get('playingTrack').trackKey,
        initialPosition: app.playState.get('position')
      });
    } else {
      this.playNext();
    }

    // Delete user key reference on reference, will trigger search for new master
    var masterUserKeyRef = this.playState.firebase.child('masterUserKey');
    masterUserKeyRef.onDisconnect().set(null);

    // When the current track finishes, play the next
    R.player.on('change:playingTrack', this._onMasterTrackChange, this);

    // Let the slaves know the master's player status
    R.player.on('change:playState', this._onMasterPlayerStateChange, this);

    // Let the slaves know the master's player position
    R.player.on('change:position', this._onMasterPlayerPositionChange, this);

    // When something is added to the queue and we aren't playing, play it
    this.listenTo(app.queue, 'add', this._onMasterQueueChange);
  },

  destroyMasterStatus: function() {
    R.player.off('change:playingTrack', this._onMasterTrackChange, this);
    R.player.off('change:playState', this._onMasterPlayerStateChange, this);
    R.player.off('change:position', this._onMasterPlayerPositionChange, this);
    this.stopListening(app.queue, 'add', this._onMasterQueueChange);
  },

  _onMasterTrackChange: function(newValue) {
    if (newValue === null) {
      this.playNext();
    }
  },

  _onMasterPlayerStateChange: function(newValue) {
    this.playState.set({
      'playState': newValue
    });
  },

  _onMasterPlayerPositionChange: function(newValue) {
    this.playState.set({
      'position': newValue
    });
  },

  _onMasterQueueChange: function(model, collection, options) {
    if (app.playState.get('playingTrack') === null) {
      this.playNext();
    }
  },

  /**
   * Called when the client should listen to a remote player
   **/
  initSlaveStatus: function() {
    console.info('Becoming slave');
    this.destroyMasterStatus();

    if (app.playState.get('playState') == R.player.PLAYSTATE_PLAYING) {
      R.player.play({
        source: app.playState.get('playingTrack').trackKey,
        initialPosition: app.playState.get('position')
      });
    }

    app.playState.on('change:playingTrack', this._onSlaveTrackChange, this);
    app.playState.on('change:playState', this._onSlavePlayerStateChange, this);
  },

  destroySlaveStatus: function() {
    app.playState.off('change:playingTrack', this._onSlaveTrackChange, this);
    app.playState.off('change:playState', this._onSlavePlayerStateChange, this);
  },

  _onSlaveTrackChange: function(model, value, options) {
    console.log('change:playingTrack', model, value, options);
    R.player.play({
      source: value.trackKey
    });
  },

  _onSlavePlayerStateChange: function(model, value, options) {
    console.log('change:playState', model, value, options);
    switch (value) {
      case R.player.PLAYSTATE_PAUSED:
      case R.player.PLAYSTATE_STOPPED:
        R.player.pause();
        break;
    }
  }

});

app.TrackView = Backbone.View.extend({
  tagName: 'li',

  template: _.template($('#track-template').html()),

  events: {
    'click .up-vote': 'upVote',
    'click .down-vote': 'downVote'
  },

  initialize: function() {
    this.listenTo(this.model, 'change', this.render);
    this.listenTo(this.model, 'remove', this.remove);
    this.rdioTrack = null;
    this.rdioUser = null;

    var self = this;
    R.request({
      method: 'get',
      content: {
        keys: self.model.get('trackKey') + ',' + self.model.get('userKey'),
        extras: 'streamRegions,shortUrl,bigIcon'
      },
      success: function(response) {
        self.rdioTrack = response.result[self.model.get('trackKey')];
        self.rdioUser = response.result[self.model.get('userKey')];
        self.render();
      },
      error: function(response) {
        console.log('Unable to get tack information for', self.model.get('trackKey'));
      }
    });

  },

  render: function() {
    if (this.rdioTrack && this.rdioUser) {
      var data = _.extend({
        'track': this.rdioTrack,
        'user': this.rdioUser
      }, this.model.toJSON(), this.model.getVoteCounts());
      this.$el.html(this.template(data));
      this.$el.show();
    } else {
      this.$el.hide();
    }
    return this;
  },

  upVote: function() {
    this.model.upVote();
    app.queue.sort();
  },

  downVote: function() {
    this.model.downVote();
    app.queue.sort();
  }

});

app.queueView = Backbone.View.extend({
  el: '#queue',

  statsTemplate: _.template($('#stats-template').html()),

  initialize: function() {
    this.queueStats = $('#queue-stats');

    this.listenTo(app.queue, 'add', this.addOne);
    // this.listenTo(app.queue, 'sort', this.addAll);
    this.listenTo(app.queue, 'all', this.render);
    this.addAll(app.queue, {});
  },

  render: function() {
    if (app.queue.length) {
      // this.queueStats.html(this.statsTemplate({queueSize: app.queue.length}));
      this.queueStats.show();
    } else {
      this.queueStats.hide();
    }
  },

  addOne: function (model, collection, options) {
    var view = new app.TrackView({ model: model });
    this.$el.append(view.render().el);
  },

  addAll: function (collection, options) {
    this.$el.empty();
    collection.each(this.addOne, this);
  }
});

R.ready(function() {
  firebaseRef.auth(firebaseToken, function(error) {
    if (error) {
      console.log('Login Failed!', error);
    } else {
      console.log('Login Succeeded!');

      var queueView = new app.queueView();
      var nowPlayingView = new app.NowPlayingView();
      var searchView = new app.SearchView();
    }
  });
});
<commit_msg>Cancel masterUserKey reset when destroying master<commit_after>/*globals app, console, R, Backbone, Firebase, rdioUserKey, firebaseToken, firebaseRootUrl, firebaseRef */

window.app = window.app || {};

app.currentUserKey = rdioUserKey;

app.roomUrl = firebaseRootUrl;

app.Player = Backbone.Firebase.Model.extend({

  isMaster: function () {
    return this.get('masterUserKey') === app.currentUserKey;
  },

  firebase: app.roomUrl + '/player'

});

app.Track = Backbone.Model.extend({
  LIKE: 'like',
  DISLIKE: 'dislike',

  getVoteRef: function() {
    return this.collection.firebase.child(this.get('id')).child('votes');
  },

  vote: function(newVote) {
    console.info('Voting', newVote, 'for', this.get('trackKey'));
    this.getVoteRef().child(app.currentUserKey).set(newVote);
  },

  upVote: function() {
    this.vote(this.LIKE);
  },

  downVote: function() {
    this.vote(this.DISLIKE);
  },

  getVoteCount: function(voteType) {
    var votes = _.values(this.get('votes'));
    var count = _.reduce(votes, function(num, vote) {
      if (vote === voteType) {
        return num + 1;
      } else {
        return num;
      }
    }, 0);
    return count;
  },

  getVoteCounts: function() {
    var likeCount = this.getVoteCount(this.LIKE);
    var dislikeCount = this.getVoteCount(this.DISLIKE);

    console.log('Did vote count:', 'like', likeCount, 'dislike', dislikeCount);
    return {
      upVotes: likeCount,
      downVotes: dislikeCount,
      totalVotes: likeCount - dislikeCount
    };
  }

});

app.TrackList = Backbone.Firebase.Collection.extend({
  model: app.Track,

  firebase: app.roomUrl + '/queue',

  comparator: function(track) {
    var counts = track.getVoteCounts();
    return (counts.upVotes - counts.downVotes) * -1;
  }

});

app.queue = new app.TrackList();
app.playState = new app.Player();

app.NowPlayingView = Backbone.View.extend({
  el: '#now-playing',

  template: _.template($('#now-playing-template').html()),

  events: {
    'click #player-play': 'playNext'
  },

  initialize: function() {
    var self = this;
    this.rdioTrackKey = null;
    this.activeUsers = chat.activeUsers;
    this.playState = app.playState;

    this.listenTo(this.playState, 'change:masterUserKey', this._onMasterUserKeyChange);

    R.player.on('change:playingTrack', this._onPlayingTrackChange, this);

    if (this.playState.get('masterUserKey') === undefined) {
      this.findNewMasterKey();
    }

    if (this.playState.isMaster()) {
      this.initMasterStatus();
    } else {
      this.initSlaveStatus();
    }
  },

  /**
   * Handles changes to masterUserKey
   */
  _onMasterUserKeyChange: function(model, newValue, options) {
    console.info('change:masterUserKey', newValue);
    if (newValue === undefined) {
      this.findNewMasterKey();
    } else if(newValue === app.currentUserKey) {
      this.initMasterStatus();
    } else {
      this.initSlaveStatus();
    }
  },

  /**
   * Handles changes to the currently playing track
   */
  _onPlayingTrackChange: function(newValue) {
    if (newValue !== null) {
      this.rdioTrackKey = newValue.get('key');
      this.render();
    }
  },

  render: function() {
    var self = this;

    if (this.rdioTrackKey) {
      R.request({
        method: 'get',
        content: {
          keys: this.rdioTrackKey,
          extras: 'streamRegions,shortUrl,bigIcon'
        },
        success: function(response) {
          var data = _.extend({
            'track': response.result[self.rdioTrackKey]
          });

          self.$el.html(self.template(data));
          self.$el.show();
        },
        error: function(response) {
          console.log('Unable to get tack information for', self.rdioTrackKey);
        }
      });

    } else {
      this.$el.hide();
    }
    return this;
  },

  playNext: function() {
    if (!app.queue.length) {
      this.playState.set({
        'playState': R.player.PLAYSTATE_STOPPED,
        'playingTrack': null
      });
      return;
    }

    var queueItem = app.queue.shift();
    console.log('Playing next track', queueItem);
    this.addToHistory(queueItem);

    this.playState.set({
      'playingTrack': queueItem.toJSON()
    });

    R.player.play({
      source: queueItem.get('trackKey')
    });
  },

  addToHistory: function(queueItem) {
    // R.request here instead of in render, cause it's historical.
    var trackKey = queueItem.get('trackKey');
    R.request({
      method: 'get',
      content: {
        keys: trackKey,
        extras: '-*,name,artist,icon'
      },
      success: function(res) {
        var track = res.result[trackKey];
        var messageData = {
          type: 'NewTrack',
          title: track.name,
          artist: track.artist,
          iconUrl: track.icon,
          timestamp: (new Date()).toISOString()
        };

        chat.messageHistory.add(messageData);
      }
    });
  },

  findNewMasterKey: function() {
    var self = this;
    this.playState.firebase.child('masterUserKey').transaction(function(currentValue) {
      console.log('Finding a new masterUserKey:', currentValue);
      var newUserKey = app.currentUserKey;

      if (self.activeUsers) {
        var onlineUsers = self.activeUsers.where({isOnline:true});
        var sortedOnlineUsers = _.sortBy(onlineUsers,
          function(user) { return user.get('id'); });

        newUserKey = sortedOnlineUsers[0].get('id');
      }

      if (currentValue === null) {
        return newUserKey;
      } else {
        return undefined;
      }
    }, function(error, committed, snapshot) {
      if (error) {
        console.warn('Error when setting masterUserKey:', error.message);
        if (committed) {
          console.warn('Transaction was committed:', snapshot);
        } else {
          console.warn('Transaction was not committed:', snapshot);
        }
      }
    });
  },

  /**
   * Called when this client assumes control of the player
   **/
  initMasterStatus: function() {
    var self = this;
    console.info('Becoming master');
    self.destroySlaveStatus();

    if (app.playState.get('playState') == R.player.PLAYSTATE_PLAYING) {
      R.player.play({
        source: app.playState.get('playingTrack').trackKey,
        initialPosition: app.playState.get('position')
      });
    } else {
      this.playNext();
    }

    // Delete user key reference on reference, will trigger search for new master
    var masterUserKeyRef = this.playState.firebase.child('masterUserKey');
    masterUserKeyRef.onDisconnect().set(null);

    // When the current track finishes, play the next
    R.player.on('change:playingTrack', this._onMasterTrackChange, this);

    // Let the slaves know the master's player status
    R.player.on('change:playState', this._onMasterPlayerStateChange, this);

    // Let the slaves know the master's player position
    R.player.on('change:position', this._onMasterPlayerPositionChange, this);

    // When something is added to the queue and we aren't playing, play it
    this.listenTo(app.queue, 'add', this._onMasterQueueChange);
  },

  destroyMasterStatus: function() {
    var masterUserKeyRef = this.playState.firebase.child('masterUserKey');
    masterUserKeyRef.onDisconnect().cancel();

    R.player.off('change:playingTrack', this._onMasterTrackChange, this);
    R.player.off('change:playState', this._onMasterPlayerStateChange, this);
    R.player.off('change:position', this._onMasterPlayerPositionChange, this);
    this.stopListening(app.queue, 'add', this._onMasterQueueChange);
  },

  _onMasterTrackChange: function(newValue) {
    if (newValue === null) {
      this.playNext();
    }
  },

  _onMasterPlayerStateChange: function(newValue) {
    this.playState.set({
      'playState': newValue
    });
  },

  _onMasterPlayerPositionChange: function(newValue) {
    this.playState.set({
      'position': newValue
    });
  },

  _onMasterQueueChange: function(model, collection, options) {
    if (app.playState.get('playingTrack') === null) {
      this.playNext();
    }
  },

  /**
   * Called when the client should listen to a remote player
   **/
  initSlaveStatus: function() {
    console.info('Becoming slave');
    this.destroyMasterStatus();

    if (app.playState.get('playState') == R.player.PLAYSTATE_PLAYING) {
      R.player.play({
        source: app.playState.get('playingTrack').trackKey,
        initialPosition: app.playState.get('position')
      });
    }

    app.playState.on('change:playingTrack', this._onSlaveTrackChange, this);
    app.playState.on('change:playState', this._onSlavePlayerStateChange, this);
  },

  destroySlaveStatus: function() {
    app.playState.off('change:playingTrack', this._onSlaveTrackChange, this);
    app.playState.off('change:playState', this._onSlavePlayerStateChange, this);
  },

  _onSlaveTrackChange: function(model, value, options) {
    console.log('change:playingTrack', model, value, options);
    R.player.play({
      source: value.trackKey
    });
  },

  _onSlavePlayerStateChange: function(model, value, options) {
    console.log('change:playState', model, value, options);
    switch (value) {
      case R.player.PLAYSTATE_PAUSED:
      case R.player.PLAYSTATE_STOPPED:
        R.player.pause();
        break;
    }
  }

});

app.TrackView = Backbone.View.extend({
  tagName: 'li',

  template: _.template($('#track-template').html()),

  events: {
    'click .up-vote': 'upVote',
    'click .down-vote': 'downVote'
  },

  initialize: function() {
    this.listenTo(this.model, 'change', this.render);
    this.listenTo(this.model, 'remove', this.remove);
    this.rdioTrack = null;
    this.rdioUser = null;

    var self = this;
    R.request({
      method: 'get',
      content: {
        keys: self.model.get('trackKey') + ',' + self.model.get('userKey'),
        extras: 'streamRegions,shortUrl,bigIcon'
      },
      success: function(response) {
        self.rdioTrack = response.result[self.model.get('trackKey')];
        self.rdioUser = response.result[self.model.get('userKey')];
        self.render();
      },
      error: function(response) {
        console.log('Unable to get tack information for', self.model.get('trackKey'));
      }
    });

  },

  render: function() {
    if (this.rdioTrack && this.rdioUser) {
      var data = _.extend({
        'track': this.rdioTrack,
        'user': this.rdioUser
      }, this.model.toJSON(), this.model.getVoteCounts());
      this.$el.html(this.template(data));
      this.$el.show();
    } else {
      this.$el.hide();
    }
    return this;
  },

  upVote: function() {
    this.model.upVote();
    app.queue.sort();
  },

  downVote: function() {
    this.model.downVote();
    app.queue.sort();
  }

});

app.queueView = Backbone.View.extend({
  el: '#queue',

  statsTemplate: _.template($('#stats-template').html()),

  initialize: function() {
    this.queueStats = $('#queue-stats');

    this.listenTo(app.queue, 'add', this.addOne);
    // this.listenTo(app.queue, 'sort', this.addAll);
    this.listenTo(app.queue, 'all', this.render);
    this.addAll(app.queue, {});
  },

  render: function() {
    if (app.queue.length) {
      // this.queueStats.html(this.statsTemplate({queueSize: app.queue.length}));
      this.queueStats.show();
    } else {
      this.queueStats.hide();
    }
  },

  addOne: function (model, collection, options) {
    var view = new app.TrackView({ model: model });
    this.$el.append(view.render().el);
  },

  addAll: function (collection, options) {
    this.$el.empty();
    collection.each(this.addOne, this);
  }
});

R.ready(function() {
  firebaseRef.auth(firebaseToken, function(error) {
    if (error) {
      console.log('Login Failed!', error);
    } else {
      console.log('Login Succeeded!');

      var queueView = new app.queueView();
      var nowPlayingView = new app.NowPlayingView();
      var searchView = new app.SearchView();
    }
  });
});
<|endoftext|>


<commit_before>/* @flow */

declare var CGAffineTransformConcat: any;
declare var CGAffineTransformMakeRotation: any;
declare var CGAffineTransformMakeScale: any;
declare var CGAffineTransformMakeTranslation: any;
declare var CGSizeMake: any;
declare var COSAlertWindow: any;
declare var MSArtboardGroup: any
declare var MSAttributedString: any;;
declare var MSColor: any;
declare var MSImageData: any;
declare var MSJSONDataArchiver;
declare var MSLayerGroup: any;
declare var MSOvalShape: any;
declare var MSRect: any;
declare var MSRectangleShape: any;
declare var MSShapeGroup: any;
declare var MSTextLayer: any;
declare var NSAttributedString: any;
declare var NSArray: any;
declare var NSColor: any;
declare var NSDataBase64EncodingEndLineWithCarriageReturn: any;
declare var NSDate: any;
declare var NSFontCondensedTrait: any;
declare var NSFontItalicTrait: any;
declare var NSFontManager: any;
declare var NSFontSymbolicTrait: any;
declare var NSFontTraitsAttribute: any;
declare var NSFontWeightBlack: any;
declare var NSFontWeightBold: any;
declare var NSFontWeightHeavy: any;
declare var NSFontWeightLight: any;
declare var NSFontWeightMedium: any;
declare var NSFontWeightRegular: any;
declare var NSFontWeightSemibold: any;
declare var NSFontWeightThin: any;
declare var NSFontWeightTrait: any;
declare var NSFontWeightUltraLight: any;
declare var NSFont: any;
declare var NSFontAttributeName: any;
declare var NSImage: any;
declare var NSKernAttributeName: any;
declare var NSMakeRect: any;
declare var NSMutableParagraphStyle: any;
declare var NSParagraphStyleAttributeName: any;
declare var NSString: any;
declare var NSStringDrawingUsesLineFragmentOrigin: any;
declare var NSTextField: any;
declare var NSTextView: any;
declare var NSURL: any;
declare var NSView: any;
declare var log: any;
<commit_msg>add MSMoment to flow globals<commit_after>/* @flow */

declare var CGAffineTransformConcat: any;
declare var CGAffineTransformMakeRotation: any;
declare var CGAffineTransformMakeScale: any;
declare var CGAffineTransformMakeTranslation: any;
declare var CGSizeMake: any;
declare var COSAlertWindow: any;
declare var MSArtboardGroup: any
declare var MSAttributedString: any;;
declare var MSColor: any;
declare var MSImageData: any;
declare var MSJSONDataArchiver;
declare var MSLayerGroup: any;
declare var MSMoment: any;
declare var MSOvalShape: any;
declare var MSRect: any;
declare var MSRectangleShape: any;
declare var MSShapeGroup: any;
declare var MSTextLayer: any;
declare var NSAttributedString: any;
declare var NSArray: any;
declare var NSColor: any;
declare var NSDataBase64EncodingEndLineWithCarriageReturn: any;
declare var NSDate: any;
declare var NSFontCondensedTrait: any;
declare var NSFontItalicTrait: any;
declare var NSFontManager: any;
declare var NSFontSymbolicTrait: any;
declare var NSFontTraitsAttribute: any;
declare var NSFontWeightBlack: any;
declare var NSFontWeightBold: any;
declare var NSFontWeightHeavy: any;
declare var NSFontWeightLight: any;
declare var NSFontWeightMedium: any;
declare var NSFontWeightRegular: any;
declare var NSFontWeightSemibold: any;
declare var NSFontWeightThin: any;
declare var NSFontWeightTrait: any;
declare var NSFontWeightUltraLight: any;
declare var NSFont: any;
declare var NSFontAttributeName: any;
declare var NSImage: any;
declare var NSKernAttributeName: any;
declare var NSMakeRect: any;
declare var NSMutableParagraphStyle: any;
declare var NSParagraphStyleAttributeName: any;
declare var NSString: any;
declare var NSStringDrawingUsesLineFragmentOrigin: any;
declare var NSTextField: any;
declare var NSTextView: any;
declare var NSURL: any;
declare var NSView: any;
declare var log: any;
<|endoftext|>


<commit_before>var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');

var google = require('googleapis');
var googleAuth = require('google-auth-library');

var graph = require('fbgraph');

var slackWebClient = require('@slack/client').WebClient;

var authTokens = require(__base + 'secret/auth-tokens.json');
var authConf = {
    'facebook' : {
        'clientID' : authTokens.fbClientID, // also refer to as app-ID
        'clientSecret' : authTokens.fbClientSecret, // also refer to as app-secret
        'scope' : 'email, public_profile, user_friends, user_posts',
        'redirectUri' : 'https://lynxapp.me/api/auth/facebook'
    },
    'gmail' : {
        'clientID': authTokens.gmailClientID,
        'clientSecret' : authTokens.gmailClientSecret,
        'scope' : ['https://www.googleapis.com/auth/plus.me',
                   'https://www.googleapis.com/auth/gmail.modify'],
        'redirectUri' : 'https://lynxapp.me/api/auth/gmail'
    },
    'slack' : {
        'clientID' : authTokens.slackClientID,
        'clientSecret' : authTokens.slackClientSecret,
        'scope': 'channels%3Ahistory+channels%3Aread+im%3Aread+im%3Ahistory+mpim%3Aread+mpim%3Ahistory',
        'redirectUri' : 'https://lynxapp.me/api/auth/slack'
    }
};

var oauth2 = google.auth.OAuth2;
var oauth2Client = new oauth2(
    authConf.gmail.clientID,
    authConf.gmail.clientSecret,
    authConf.gmail.redirectUri
);

module.exports.Router = function () {
	var router = express.Router();

    /* Parses a string and returns an array of links if there are any. */
    function regParser(text) {
        // Resource: https://gist.github.com/dperini/729294
        // Might need to remove escape slashes
        if (text) {
            console.log('The test is: ' + text);
            var re = new RegExp('^(?:(?:https?|ftp|http):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$');
            var words = text.replace(/[<>]/g,'').split(' ');
            console.log(words);
            var results = [];
            var url = 'https://info344api.enamarkovic.com/v1/summary?url=';
            for (var i in words) {
                console.log('The word is: ' + words[i]);
                console.log(re.test(words[i]));
                // if it is a link, we will call the link summary API
                if (re.test(words[i])) {
                    console.log("Yep! it's a link!");
                    request(url + words[i], function (error, response, body) {
                        if (!error){
                            body.service = "slack";
                            body.from = "wei-jen";
                            body.time = Date.now();
                            var JSONresponse = JSON.parse(body);
                            console.log(JSONresponse);
                            results.push(JSONresponse);
                        } else {
                            console.log(error);
                        }
                    });
                }
            }
            return results;
        }
    }

    // Facebook oauth: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
    router.get('/facebook_oauth', function(req, res) {
        var oauthUrl = 'https://www.facebook.com/v2.9/dialog/oauth?client_id='
            + authConf.facebook.clientID
            + '&scope=' + authConf.facebook.scope
            + '&redirect_uri=' + authConf.facebook.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/facebook', function(facebookReq, facebookRes) {
        // Exchanging an authorization code for an API access token
        var apiTokenUrl = 'https://graph.facebook.com/v2.9/oauth/access_token?client_id='
            + authConf.facebook.clientID
            + '&redirect_uri=' + authConf.facebook.redirectUri
            + '&client_secret=' + authConf.facebook.clientSecret
            + '&code=' + facebookReq.query.code;

        request(apiTokenUrl, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                graph.setAccessToken(info.access_token);

                var fboptions = {
                    timeout:  3000
                    , pool:     { maxSockets:  Infinity }
                    , headers:  { connection:  "keep-alive" }
                };

                var reqParam = {
                    fields:"type,caption,description,link"
                };

                // Grab all the statuses on the feed.
                graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
                    console.log(res);
                });

            } else {
                console.error('Facebook API call error: ' + err);
            }
        });

        // After we are done, redirect back to the main website.
        facebookRes.redirect('https://lynxapp.me');
    });

    // Facebook webhook: https://developers.facebook.com/docs/graph-api/webhooks
    router.post('/facebook_incoming', function(req, res) {
        // Facebook challenge. Saving just in case.
        // if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        //     console.log("Validating webhook");
        //     res.status(200).send(req.query['hub.challenge']);
        // } else {
        //     console.error("Failed validation. Make sure the validation tokens match.");
        //     res.sendStatus(403);
        // }
        //
        // changes: [ { field: 'status',
        //              id: '44444444_444444444',
        //              value: 'This is an Example Status.' } ]
        console.log(req.body.entry[0].changes[0].value);
        res.status(200);

    });

    // Gmail Oauth: https://developers.google.com/identity/protocols/OAuth2WebServer
    router.get('/gmail_oauth', function(req, res) {
        /* var oauthUrl = 'https://accounts.google.com/o/oauth2/v2/auth?client_id='
        + authConf.gmail.clientID
        + '&redirect_uri' + authConf.gmail.redirectUri
        + '&response_type=code&scope=' + auth.gmail.scope;
        res.redirect(oauthUrl); */
        var oauthUrl = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: authConf.gmail.scope
        });
        res.redirect(oauthUrl);
    });

    router.get('/gmail', function(gmailReq, gmailRes) {
        console.log('in /api/auth/gmail');

        oauth2Client.getToken(gmailReq.query.code, function(err, tokens) {
            if (!err) {
                oauth2Client.setCredentials(tokens);
                var gmail = google.gmail('v1');

                gmail.users.messages.list({auth: oauth2Client, userId: 'me', maxResults: 100}, function(listErr, listRes) {
                    if (listErr) {
                        console.log('The list messages API call returned an error: ' + listErr);
                        return;
                    } else {
                        var emailIDs = listRes.messages;
                        for (var i in emailIDs) {
                            gmail.users.messages.get({auth: auth2Client, id: emailIDs[i],userId: 'me'}, function(getErr, getResponse) {
                                if (getErr) {
                                    console.log('The get messages API call returned an error for email with ID: ' + emailIDs[i]);
                                } else {
                                    console.log(getResponse);
                                }
                            });
                        }
                    }
                });
            } else {
                console.log('Getting the API token returned an error: ' + err);
            }
        });

        // request(apiTokenUrl, function (err, res, body) {
        //     if (!err && res.statusCode == 200) {
        //         var info = JSON.parse(body);
        //         graph.setAccessToken(info.access_token);
        //
        //         var fboptions = {
        //             timeout:  3000
        //             , pool:     { maxSockets:  Infinity }
        //             , headers:  { connection:  "keep-alive" }
        //         };
        //
        //         var reqParam = {
        //             fields:"type,caption,description,link"
        //         };
        //
        //         graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
        //             console.log(res);
        //         });
        //
        //     } else {
        //         console.error('Facebook API call error: ' + err);
        //     }
        // });
        // facebookRes.redirect('https://lynxapp.me');
    });

    // Slack Oauth: https://api.slack.com/docs/oauth
    router.get('/slack_oauth', function (req, res, next) {
        var oauthUrl = 'https://slack.com/oauth/authorize?client_id='
            + authConf.slack.clientID
            + '&scope=' + authConf.slack.scope
            + '&redirect_uri=' + authConf.slack.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/slack', function(slackReq, slackRes) {
        console.log("in /api/auth/slack");

        var apiTokenUrl = 'https://slack.com/api/oauth.access?client_id='
            + authConf.slack.clientID
            + '&client_secret=' + authConf.slack.clientSecret
            + '&code=' + slackReq.query.code
            + '&redirect_uri=' + authConf.slack.redirectUri;

        request(apiTokenUrl, function (err, res, body) {
            console.log("getting access token");
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                authConf.slack.accessToken = info.access_token;
                var slackWeb = new slackWebClient(authConf.slack.accessToken);

                var channelIDs = [];

                // all public channels
                slackWeb.channels.list(function(channelListErr, channelListInfo) {
                    if (channelListErr || !channelListInfo.ok) {
                        console.error('Error: Unable to retrieve public channel list.');
                    } else {
                        for (var i in channelListInfo.channels) {
                            slackWeb.channels.history(channelListInfo.channels[i].id, function(channelHistErr, channelHistInfo) {
                                if (channelHistErr || !channelHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for channel with ID: ' + channelListInfo.channels[i].id);
                                } else {
                                    console.log(channelHistInfo.messages);
                                }
                            });
                        }
                    }
                });

                // all direct messages
                slackWeb.im.list(function(imListErr, imListInfo) {
                    if (imListErr || !imListInfo.ok) {
                        console.error('Error: Unable to retrieve direct message list.');
                    } else {
                        for (var i in imListInfo.ims) {
                            slackWeb.im.history(imListInfo.ims[i].id, function(imHistErr, imHistInfo) {
                                if (imHistErr || !imHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for direct message with ID: ' + imListInfo.ims[i].id);
                                } else {
                                    console.log(imHistInfo.messages);
                                }
                            });
                        }
                    }

                });

                // all group direct messages
                slackWeb.mpim.list(function(mpimListErr, mpimListInfo) {
                    if (mpimListErr || !mpimListInfo.ok) {
                        console.error('Error: Unable to retrieve group direct message list.');
                    } else {
                        for (var i in mpimListInfo.groups) {
                            slackWeb.mpim.history(mpimListInfo.groups[i].id, function(mpimHistErr, mpimHistInfo) {
                                if (mpimHistErr || !mpimHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for group direct message with ID: ' + mpimHistInfo.groups[i].id);
                                } else {
                                    console.log(mpimHistInfo.messages);
                                }
                            });
                        }
                    }
                });
            } else {
                console.error('Slack API call error: ' + err);
            }
        });
        // When we are done, redirects back the main page
        slackRes.redirect('https://lynxapp.me');
    });

    router.post('/slack_incoming', function(req, res) {
        // This is used to respond to slack challenges. Saved in case
        // the verification expires in the future.
        // res.type('html');
        // res.status(200).send(req.body.challenge);
        //
        //   event:
        //          { type: 'message',
        //            user: 'U50SS1PLJ',
        //            text: 'denver',
        //            ts: '1495684015.632873',
        //            channel: 'D51MCEQ1M',
        //            event_ts: '1495684015.632873' },

        if (req.body.event.text) {
            res.status(200).send(regParser(req.body.event.text));
        } else {
            res.status(200).send("non-text event");
        }
    });

	return router;
};
<commit_msg>remove console.logs and now slack webhook is stable<commit_after>var express = require('express');
var _ = require('lodash');
var request = require('request');
var fs = require('fs');

var google = require('googleapis');
var googleAuth = require('google-auth-library');

var graph = require('fbgraph');

var slackWebClient = require('@slack/client').WebClient;

var authTokens = require(__base + 'secret/auth-tokens.json');
var authConf = {
    'facebook' : {
        'clientID' : authTokens.fbClientID, // also refer to as app-ID
        'clientSecret' : authTokens.fbClientSecret, // also refer to as app-secret
        'scope' : 'email, public_profile, user_friends, user_posts',
        'redirectUri' : 'https://lynxapp.me/api/auth/facebook'
    },
    'gmail' : {
        'clientID': authTokens.gmailClientID,
        'clientSecret' : authTokens.gmailClientSecret,
        'scope' : ['https://www.googleapis.com/auth/plus.me',
                   'https://www.googleapis.com/auth/gmail.modify'],
        'redirectUri' : 'https://lynxapp.me/api/auth/gmail'
    },
    'slack' : {
        'clientID' : authTokens.slackClientID,
        'clientSecret' : authTokens.slackClientSecret,
        'scope': 'channels%3Ahistory+channels%3Aread+im%3Aread+im%3Ahistory+mpim%3Aread+mpim%3Ahistory',
        'redirectUri' : 'https://lynxapp.me/api/auth/slack'
    }
};

var oauth2 = google.auth.OAuth2;
var oauth2Client = new oauth2(
    authConf.gmail.clientID,
    authConf.gmail.clientSecret,
    authConf.gmail.redirectUri
);

module.exports.Router = function () {
	var router = express.Router();

    /* Parses a string and returns an array of links if there are any. */
    function regParser(text) {
        // Resource: https://gist.github.com/dperini/729294
        // Might need to remove escape slashes
        if (text) {
            var re = new RegExp('^(?:(?:https?|ftp|http):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$');
            var words = text.replace(/[<>]/g,'').split(' ');
            console.log(words);
            var results = [];
            var url = 'https://info344api.enamarkovic.com/v1/summary?url=';
            for (var i in words) {
                console.log('The word is: ' + words[i]);
                // if it is a link, we will call the link summary API
                if (re.test(words[i])) {
                    console.log("Yep! it's a link!");
                    request(url + words[i], function (error, response, body) {
                        if (!error){
                            var JSONresponse = JSON.parse(body);
                            JSONresponse.service = "slack";
                            JSONresponse.from = "wei-jen";
                            JSONresponse.time = Date.now();
                            results.push(JSONresponse);
                        } else {
                            console.log(error);
                        }
                    });
                }
            }
            return results;
        }
    }

    // Facebook oauth: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow
    router.get('/facebook_oauth', function(req, res) {
        var oauthUrl = 'https://www.facebook.com/v2.9/dialog/oauth?client_id='
            + authConf.facebook.clientID
            + '&scope=' + authConf.facebook.scope
            + '&redirect_uri=' + authConf.facebook.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/facebook', function(facebookReq, facebookRes) {
        // Exchanging an authorization code for an API access token
        var apiTokenUrl = 'https://graph.facebook.com/v2.9/oauth/access_token?client_id='
            + authConf.facebook.clientID
            + '&redirect_uri=' + authConf.facebook.redirectUri
            + '&client_secret=' + authConf.facebook.clientSecret
            + '&code=' + facebookReq.query.code;

        request(apiTokenUrl, function (err, res, body) {
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                graph.setAccessToken(info.access_token);

                var fboptions = {
                    timeout:  3000
                    , pool:     { maxSockets:  Infinity }
                    , headers:  { connection:  "keep-alive" }
                };

                var reqParam = {
                    fields:"type,caption,description,link"
                };

                // Grab all the statuses on the feed.
                graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
                    console.log(res);
                });

            } else {
                console.error('Facebook API call error: ' + err);
            }
        });

        // After we are done, redirect back to the main website.
        facebookRes.redirect('https://lynxapp.me');
    });

    // Facebook webhook: https://developers.facebook.com/docs/graph-api/webhooks
    router.post('/facebook_incoming', function(req, res) {
        // Facebook challenge. Saving just in case.
        // if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        //     console.log("Validating webhook");
        //     res.status(200).send(req.query['hub.challenge']);
        // } else {
        //     console.error("Failed validation. Make sure the validation tokens match.");
        //     res.sendStatus(403);
        // }
        //
        // changes: [ { field: 'status',
        //              id: '44444444_444444444',
        //              value: 'This is an Example Status.' } ]
        console.log(req.body.entry[0].changes[0].value);
        res.status(200);

    });

    // Gmail Oauth: https://developers.google.com/identity/protocols/OAuth2WebServer
    router.get('/gmail_oauth', function(req, res) {
        /* var oauthUrl = 'https://accounts.google.com/o/oauth2/v2/auth?client_id='
        + authConf.gmail.clientID
        + '&redirect_uri' + authConf.gmail.redirectUri
        + '&response_type=code&scope=' + auth.gmail.scope;
        res.redirect(oauthUrl); */
        var oauthUrl = oauth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: authConf.gmail.scope
        });
        res.redirect(oauthUrl);
    });

    router.get('/gmail', function(gmailReq, gmailRes) {
        console.log('in /api/auth/gmail');

        oauth2Client.getToken(gmailReq.query.code, function(err, tokens) {
            if (!err) {
                oauth2Client.setCredentials(tokens);
                var gmail = google.gmail('v1');

                gmail.users.messages.list({auth: oauth2Client, userId: 'me', maxResults: 100}, function(listErr, listRes) {
                    if (listErr) {
                        console.log('The list messages API call returned an error: ' + listErr);
                        return;
                    } else {
                        var emailIDs = listRes.messages;
                        for (var i in emailIDs) {
                            gmail.users.messages.get({auth: auth2Client, id: emailIDs[i],userId: 'me'}, function(getErr, getResponse) {
                                if (getErr) {
                                    console.log('The get messages API call returned an error for email with ID: ' + emailIDs[i]);
                                } else {
                                    console.log(getResponse);
                                }
                            });
                        }
                    }
                });
            } else {
                console.log('Getting the API token returned an error: ' + err);
            }
        });

        // request(apiTokenUrl, function (err, res, body) {
        //     if (!err && res.statusCode == 200) {
        //         var info = JSON.parse(body);
        //         graph.setAccessToken(info.access_token);
        //
        //         var fboptions = {
        //             timeout:  3000
        //             , pool:     { maxSockets:  Infinity }
        //             , headers:  { connection:  "keep-alive" }
        //         };
        //
        //         var reqParam = {
        //             fields:"type,caption,description,link"
        //         };
        //
        //         graph.setOptions(fboptions).get("/me/feed", reqParam, function(err, res) {
        //             console.log(res);
        //         });
        //
        //     } else {
        //         console.error('Facebook API call error: ' + err);
        //     }
        // });
        // facebookRes.redirect('https://lynxapp.me');
    });

    // Slack Oauth: https://api.slack.com/docs/oauth
    router.get('/slack_oauth', function (req, res, next) {
        var oauthUrl = 'https://slack.com/oauth/authorize?client_id='
            + authConf.slack.clientID
            + '&scope=' + authConf.slack.scope
            + '&redirect_uri=' + authConf.slack.redirectUri;
        res.redirect(oauthUrl);
    });

    router.get('/slack', function(slackReq, slackRes) {
        console.log("in /api/auth/slack");

        var apiTokenUrl = 'https://slack.com/api/oauth.access?client_id='
            + authConf.slack.clientID
            + '&client_secret=' + authConf.slack.clientSecret
            + '&code=' + slackReq.query.code
            + '&redirect_uri=' + authConf.slack.redirectUri;

        request(apiTokenUrl, function (err, res, body) {
            console.log("getting access token");
            if (!err && res.statusCode == 200) {
                var info = JSON.parse(body);
                authConf.slack.accessToken = info.access_token;
                var slackWeb = new slackWebClient(authConf.slack.accessToken);

                var channelIDs = [];

                // all public channels
                slackWeb.channels.list(function(channelListErr, channelListInfo) {
                    if (channelListErr || !channelListInfo.ok) {
                        console.error('Error: Unable to retrieve public channel list.');
                    } else {
                        for (var i in channelListInfo.channels) {
                            slackWeb.channels.history(channelListInfo.channels[i].id, function(channelHistErr, channelHistInfo) {
                                if (channelHistErr || !channelHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for channel with ID: ' + channelListInfo.channels[i].id);
                                } else {
                                    console.log(channelHistInfo.messages);
                                }
                            });
                        }
                    }
                });

                // all direct messages
                slackWeb.im.list(function(imListErr, imListInfo) {
                    if (imListErr || !imListInfo.ok) {
                        console.error('Error: Unable to retrieve direct message list.');
                    } else {
                        for (var i in imListInfo.ims) {
                            slackWeb.im.history(imListInfo.ims[i].id, function(imHistErr, imHistInfo) {
                                if (imHistErr || !imHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for direct message with ID: ' + imListInfo.ims[i].id);
                                } else {
                                    console.log(imHistInfo.messages);
                                }
                            });
                        }
                    }

                });

                // all group direct messages
                slackWeb.mpim.list(function(mpimListErr, mpimListInfo) {
                    if (mpimListErr || !mpimListInfo.ok) {
                        console.error('Error: Unable to retrieve group direct message list.');
                    } else {
                        for (var i in mpimListInfo.groups) {
                            slackWeb.mpim.history(mpimListInfo.groups[i].id, function(mpimHistErr, mpimHistInfo) {
                                if (mpimHistErr || !mpimHistInfo.ok) {
                                    console.error('Error: Unable to retrieve messages for group direct message with ID: ' + mpimHistInfo.groups[i].id);
                                } else {
                                    console.log(mpimHistInfo.messages);
                                }
                            });
                        }
                    }
                });
            } else {
                console.error('Slack API call error: ' + err);
            }
        });
        // When we are done, redirects back the main page
        slackRes.redirect('https://lynxapp.me');
    });

    router.post('/slack_incoming', function(req, res) {
        // This is used to respond to slack challenges. Saved in case
        // the verification expires in the future.
        // res.type('html');
        // res.status(200).send(req.body.challenge);
        //
        //   event:
        //          { type: 'message',
        //            user: 'U50SS1PLJ',
        //            text: 'denver',
        //            ts: '1495684015.632873',
        //            channel: 'D51MCEQ1M',
        //            event_ts: '1495684015.632873' },

        if (req.body.event.text) {
            res.status(200).send(regParser(req.body.event.text));
        } else {
            res.status(200).send("non-text event");
        }
    });

	return router;
};
<|endoftext|>


<commit_before>/**
 * TableWire.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

define(
  'tinymce.plugins.table.actions.ResizeHandler',

  [
    'ephox.katamari.api.Arr',
    'ephox.katamari.api.Option',
    'ephox.snooker.api.ResizeWire',
    'ephox.snooker.api.TableDirection',
    'ephox.snooker.api.TableResize',
    'ephox.sugar.api.node.Element',
    'ephox.sugar.api.properties.Attr',
    'ephox.sugar.api.search.SelectorFilter',
    'tinymce.plugins.table.actions.TableWire',
    'tinymce.plugins.table.queries.Direction',
    'tinymce.core.util.Tools'
  ],

  function (Arr, Option, ResizeWire, TableDirection, TableResize, Element, Attr, SelectorFilter, TableWire, Direction, Tools) {

    return function (editor) {
      var selectionRng = Option.none();
      var resize = Option.none();
      var wire = Option.none();

      var isTable = function (elm) {
        return elm.nodeName === 'TABLE';
      };

      var lazyResize = function () {
        return resize;
      };

      var lazyWire = function () {
        return wire.getOr(ResizeWire.only(Element.fromDom(editor.getBody())));
      };

      var destroy = function () {
        resize.each(function (sz) {
          sz.destroy();
        });

        wire.each(function (w) {
          TableWire.remove(editor, w);
        });
      };

      editor.on('init', function () {
        var direction = TableDirection(Direction.directionAt);
        var rawWire = TableWire.get(editor);
        wire = Option.some(rawWire);
        if (editor.settings.object_resizing && editor.settings.table_resize_bars !== false &&
          (editor.settings.object_resizing === true || editor.settings.object_resizing === 'table')) {
          var sz = TableResize(rawWire, direction);
          sz.on();
          sz.events.startDrag.bind(function (event) {
            selectionRng = Option.some(editor.selection.getRng());
          });
          sz.events.afterResize.bind(function (event) {
            var table = event.table();
            var dataStyleCells = SelectorFilter.descendants(table, 'td[data-mce-style],th[data-mce-style]');
            Arr.each(dataStyleCells, function (cell) {
              Attr.remove(cell, 'data-mce-style');
            });

            selectionRng.each(function (rng) {
              editor.selection.setRng(rng);
              editor.focus();
            });

            editor.undoManager.add();
          });

          resize = Option.some(sz);
        }
      });

      // If we're updating the table width via the old mechanic, we need to update the constituent cells' widths/heights too.
      editor.on('ObjectResized', function (e) {
        if (isTable(e.target)) {
          var table = e.target;

          var newCellSizes = [];
          Tools.each(table.rows, function (row) {
            Tools.each(row.cells, function (cell) {
              var width = editor.dom.getStyle(cell, 'width', true);
              newCellSizes.push({
                cell: cell,
                width: width
              });
            });
          });

          Tools.each(newCellSizes, function (newCellSize) {
            editor.dom.setStyle(newCellSize.cell, 'width', newCellSize.width);
            editor.dom.setAttrib(newCellSize.cell, 'width', null);
          });
        }
      });

      return {
        lazyResize: lazyResize,
        lazyWire: lazyWire,
        destroy: destroy
      };
    };
  }
);
<commit_msg>TINY-1400, table: if table size is in percents, it should stay in percents after resize<commit_after>/**
 * TableWire.js
 *
 * Released under LGPL License.
 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

define(
  'tinymce.plugins.table.actions.ResizeHandler',

  [
    'ephox.katamari.api.Arr',
    'ephox.katamari.api.Option',
    'ephox.snooker.api.ResizeWire',
    'ephox.snooker.api.TableDirection',
    'ephox.snooker.api.TableResize',
    'ephox.sugar.api.node.Element',
    'ephox.sugar.api.properties.Attr',
    'ephox.sugar.api.search.SelectorFilter',
    'tinymce.plugins.table.actions.TableWire',
    'tinymce.plugins.table.queries.Direction',
    'tinymce.core.util.Tools'
  ],

  function (Arr, Option, ResizeWire, TableDirection, TableResize, Element, Attr, SelectorFilter, TableWire, Direction, Tools) {

    return function (editor) {
      var selectionRng = Option.none();
      var resize = Option.none();
      var wire = Option.none();
      var percentageBasedSizeRegex = /(\d+(\.\d+)?)%/;
      var startW, startRawW;

      var isTable = function (elm) {
        return elm.nodeName === 'TABLE';
      };

      var getRawWidth = function (elm) {
        return editor.dom.getStyle(elm, 'width') || editor.dom.getAttrib(elm, 'width');
      };

      var lazyResize = function () {
        return resize;
      };

      var lazyWire = function () {
        return wire.getOr(ResizeWire.only(Element.fromDom(editor.getBody())));
      };

      var destroy = function () {
        resize.each(function (sz) {
          sz.destroy();
        });

        wire.each(function (w) {
          TableWire.remove(editor, w);
        });
      };

      editor.on('init', function () {
        var direction = TableDirection(Direction.directionAt);
        var rawWire = TableWire.get(editor);
        wire = Option.some(rawWire);
        if (editor.settings.object_resizing && editor.settings.table_resize_bars !== false &&
          (editor.settings.object_resizing === true || editor.settings.object_resizing === 'table')) {
          var sz = TableResize(rawWire, direction);
          sz.on();
          sz.events.startDrag.bind(function (event) {
            selectionRng = Option.some(editor.selection.getRng());
          });
          sz.events.afterResize.bind(function (event) {
            var table = event.table();
            var dataStyleCells = SelectorFilter.descendants(table, 'td[data-mce-style],th[data-mce-style]');
            Arr.each(dataStyleCells, function (cell) {
              Attr.remove(cell, 'data-mce-style');
            });

            selectionRng.each(function (rng) {
              editor.selection.setRng(rng);
              editor.focus();
            });

            editor.undoManager.add();
          });

          resize = Option.some(sz);
        }
      });

      // If we're updating the table width via the old mechanic, we need to update the constituent cells' widths/heights too.
      editor.on('ObjectResizeStart', function (e) {
        if (isTable(e.target)) {
          startW = e.width;
          startRawW = getRawWidth(e.target);
        }
      });

      editor.on('ObjectResized', function (e) {
        if (isTable(e.target)) {
          var table = e.target;

          if (percentageBasedSizeRegex.test(startRawW)) {
            var percentW = parseFloat(percentageBasedSizeRegex.exec(startRawW)[1], 10);
            var targetPercentW = e.width * percentW / startW;
            editor.dom.setStyle(table, 'width', targetPercentW + '%');
          } else {
            var newCellSizes = [];
            Tools.each(table.rows, function (row) {
              Tools.each(row.cells, function (cell) {
                var width = editor.dom.getStyle(cell, 'width', true);
                newCellSizes.push({
                  cell: cell,
                  width: width
                });
              });
            });

            Tools.each(newCellSizes, function (newCellSize) {
              editor.dom.setStyle(newCellSize.cell, 'width', newCellSize.width);
              editor.dom.setAttrib(newCellSize.cell, 'width', null);
            });
          }
        }
      });

      return {
        lazyResize: lazyResize,
        lazyWire: lazyWire,
        destroy: destroy
      };
    };
  }
);
<|endoftext|>