<commit_before>#!/usr/bin/env node

var express = require('express');
var http = require('http')
var path = require('path');
var fs = require('fs');
var async = require('async');
var _ = require('underscore');
var crypto = require('crypto');
var MobileDetect = require('mobile-detect');
var config = require('./config');
var mosaic = require('./mosaic');
var mongobase = require('./mongobase');
var utils = require('./utils');
var twitimage = require('./twitimage');

var ROOTDIR = path.join(__dirname, config.mosaic.folders.root);

var app = express();

app.configure(function(){
	app.set('port', process.env.PORT || 3000);
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');
	app.use(express.favicon());
	app.use(express.logger('tiny'));
	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(express.cookieParser('kerstkaart2013bbbbb4645sf6s4fs'));
	app.use(express.session());
	app.use(app.router);
	app.use(require('stylus').middleware(__dirname + '/public'));
	app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
	app.use(express.errorHandler());
});

http.createServer(app).listen(app.get('port'), function(){
	console.log("Express server listening on port " + app.get('port'));
});

app.get('/fancybg', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);

	mongobase.getAllTilesWithTitle(function (err, fulltiles) {
		if(err) return utils.sendError(err, res);

		var tiles = _.map(fulltiles, function (tile){
			return {
				title: tile.title,
				image: '/mosaic/' + tile.tileflying
			};
		});

		tiles = _.shuffle(tiles); //shuffle the tiles

		tiles = tiles.slice(0, 40); // limit to 50 tiles everywhere

		if( md.mobile() ){
			console.log('its a mobile');
			tiles = tiles.slice(0, 16); // limit to 20 tiles on mobile
		}

		res.render('fancybg', {
			title: 'background | MiX Kerstkaart 2013',
			tiles: tiles,
			mobile: md.mobile()
		});
	})
});

app.get('/', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, true, md.mobile(), false);  // put the first boolean back on 'true' if your really want the fancy bg
});

app.get('/simple', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, false, md.mobile(), false);
});

// force mobile (for testing purposes):
app.get('/mobile', function (req, res){
	renderView(req, res, false, true, false);
});

// force oldfashion upload (for testing purposes):
app.get('/oldfashionupload', function (req, res) {
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, false, md.mobile(), true);
});

// force desktop
app.get('/desktop', function (req, res) {
	renderView(req, res, false, false, false);
});

function renderView(req, res, fancybg, mobile, forceOldFashionUpload, userid){
	getSomeRandomTilesWithPosition(50, function (err, tiles) {
		if(err) return utils.sendError(err, res);

		res.render('index', {
			title: '| MiX Kerstkaart 2013',
			tiles: tiles,
			card : {
				width: config.mosaic.greetingcard.lowres.width,
				height: config.mosaic.greetingcard.lowres.height,
				mosaicOffsetX: config.mosaic.greetingcard.lowres.offset.x,
				mosaicOffsetY: config.mosaic.greetingcard.lowres.offset.y
			},
			fancybg: fancybg,
			mobile: mobile,
			forceOldFashionUpload: forceOldFashionUpload,
			userid: userid
		});
	});
}

app.post('/xhrupload', function (req, res){
	if(!req.xhr) return utils.sendError(new Error('got no xhr request'), res);

	var size = req.header('x-file-size');
	var type = req.header('x-file-type');
	var name = path.basename(req.header('x-file-name'));

	//name = crypto.createHash('md5').update( ''+(Date.now()) ).digest('hex') + '_' + name;
	name = (Date.now()) + '_' + (utils.removeFileExt(name)).substr(0,6) + path.extname(name) ;
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	var ws = fs.createWriteStream( uploadedFile );

	req.on('data', function (data) {
		ws.write(data);
	});

	req.on('end', function () {
		console.log("Upload done");
		ws.end();
		renderMosaic(null, uploadedFile, req, res);
	});
});

app.post('/oldfashionupload', function (req, res) {
	if(!req.files.file) return renderView(req, res, false, false); // just render the normal page

	var name = req.files.file.name;

	name = (Date.now()) + '_' + (utils.removeFileExt(name)).substr(0,6) + path.extname(name) ;
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	fs.rename(req.files.file.path, uploadedFile, function (err) {
		if(err) return utils.sendError(err, res);

		var user = {
			userimage: uploadedFile,
		};

		mongobase.saveUser(user, function (err, user) {
			if(err) return utils.sendError(err, res);

			// dont render now, this is an old fashion upload: the browser is loading the page again

			// send user id (generated by DB) back to browser so it can request the creation of its mosaic:
			renderView(req, res, false, false, true, user._id);
		});
	});
});

app.post('/api/startrender', function (req, res) {
	if(!req.body.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser( req.body.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		renderMosaic( user, user.userimage, req, res );
	});
});

app.post('/api/uploaddataurl', function (req, res) {
	if(!req.body.dataURL) return utils.sendError(new Error('got no dataURL'), res);

	// incomming data:image/png;base64,iVBORw0KGgoAAAANSUh

	var base64Data = req.body.dataURL.replace(/^data:image\/png;base64,/,"");

	var name = (Date.now()) + '_webcam.png';
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	require("fs").writeFile(uploadedFile, base64Data, 'base64', function (err) {
		if(err) return utils.sendError(err, res);

		renderMosaic( null, uploadedFile, req, res );
	});
});

function renderMosaic (user, userimage, req, res) {

	function renderMosaicCallbackHandler (err, mosaicimage, user) {
		if(err) return utils.sendError(err, res);

		console.log( "Mosaic ready... sending it back to browser" );
		console.log( utils.wwwdfy(mosaicimage) );
		console.log( "Generating twitpic url" );
		twitimage.twitPicImage(mosaicimage, function (err, twiturl) {

			// dont check errors
			// if twitpic failes, the app still works
			res.send({
				mosaicimage: utils.wwwdfy(mosaicimage),
				userid: user._id,
				twitpic: (twiturl)?twiturl: config.sharing.hardcodedUrl + utils.wwwdfy(mosaicimage),
				sharing: config.sharing,
				sharingurl: config.sharing.hardcodedUrl  + '/sharable/' + user._id
			});
		});
	}

	if(!user){
		var user = {
			userimage: userimage
		}
		mongobase.saveUser(user, function (err, user) {
			if(err) return utils.sendError(err, res);

			mosaic.renderMosaic( renderMosaicCallbackHandler );
		});
	}else{
		mosaic.renderMosaic( renderMosaicCallbackHandler );
	}
}

app.get('/highquality/:userid', function (req, res) {
	if(!req.params.userid) return utils.sendError(new Error('got no user id'), res);

	res.render('highquality', {
		title: 'Hoge Kwaliteitsversie| MiX Kerstkaart 2013',
		userid: req.params.userid
	});
});

app.post('/api/renderhq', function (req, res) {
	if(!req.body.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser( req.body.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		mosaic.renderMosaicHQ( user, function (err, mosaicimageHQ, user) {
			if(err) return utils.sendError(err, res);

			console.log( "Mosaic HQ ready... sending it back to browser" );
			console.log( mosaicimageHQ );
			console.log( utils.wwwdfy(mosaicimageHQ) );
			res.send({
				mosaicimageHQ: utils.wwwdfy(mosaicimageHQ),
				userid: user._id
			});

		});
	});
});

function getSomeRandomTilesWithPosition(nrOfTiles, callback){
	var tilesinfo = utils.getTilesInfo();

	// don't put fake tiles beyond a certain point (defined in config.js)
	var maxTilesHeigh = Math.floor(config.mosaic.greetingcard.dontPutFakeTilesBeyond / config.mosaic.tile.size);
	var maxTiles = maxTilesHeigh * tilesinfo.wide;

	mongobase.getAllTilesWithTitle(function (err, fulltiles) {
		if(err) return callback(err);

		var tiles = _.map(fulltiles, function (tile){
			return {
				title: tile.title,
				image: '/mosaic/' + tile.tileflying
			};
		});

		var possibleIndexes = [];
		for (var i = 0; i < maxTiles; i++) {
			possibleIndexes.push(i);
		};

		tiles = _.shuffle(tiles); //shuffle the tiles
		possibleIndexes = _.shuffle(possibleIndexes); // shuffle possible indexes

		tiles = tiles.slice(0, nrOfTiles);
		// add an index to each tile:
		for (var i = tiles.length - 1; i >= 0; i--) {
			tiles[i].index = possibleIndexes[i];
			tiles[i].top = utils.getTilePosition( possibleIndexes[i] ).y_px,
			tiles[i].left = utils.getTilePosition( possibleIndexes[i] ).x_px,
			tiles[i].size = config.mosaic.tile.size,
			tiles[i].maxsize = config.mosaic.flyingtile.size
		};

		callback( null, tiles );
	});
}

app.get('/sharable/:userid', function (req, res) {
	if(!req.params.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser(req.params.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		res.render('sharable', {
			title: '| MiX Kerstkaart 2013',
			userid: req.params.userid,
			mosaicimage: utils.wwwdfy(user.finalOverlay)
		});
	});
});

<commit_msg>fix in code clean up<commit_after>#!/usr/bin/env node

var express = require('express');
var http = require('http')
var path = require('path');
var fs = require('fs');
var async = require('async');
var _ = require('underscore');
var crypto = require('crypto');
var MobileDetect = require('mobile-detect');
var config = require('./config');
var mosaic = require('./mosaic');
var mongobase = require('./mongobase');
var utils = require('./utils');
var twitimage = require('./twitimage');

var ROOTDIR = path.join(__dirname, config.mosaic.folders.root);

var app = express();

app.configure(function(){
	app.set('port', process.env.PORT || 3000);
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');
	app.use(express.favicon());
	app.use(express.logger('tiny'));
	app.use(express.bodyParser());
	app.use(express.methodOverride());
	app.use(express.cookieParser('kerstkaart2013bbbbb4645sf6s4fs'));
	app.use(express.session());
	app.use(app.router);
	app.use(require('stylus').middleware(__dirname + '/public'));
	app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
	app.use(express.errorHandler());
});

http.createServer(app).listen(app.get('port'), function(){
	console.log("Express server listening on port " + app.get('port'));
});

app.get('/fancybg', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);

	mongobase.getAllTilesWithTitle(function (err, fulltiles) {
		if(err) return utils.sendError(err, res);

		var tiles = _.map(fulltiles, function (tile){
			return {
				title: tile.title,
				image: '/mosaic/' + tile.tileflying
			};
		});

		tiles = _.shuffle(tiles); //shuffle the tiles

		tiles = tiles.slice(0, 40); // limit to 50 tiles everywhere

		if( md.mobile() ){
			console.log('its a mobile');
			tiles = tiles.slice(0, 16); // limit to 20 tiles on mobile
		}

		res.render('fancybg', {
			title: 'background | MiX Kerstkaart 2013',
			tiles: tiles,
			mobile: md.mobile()
		});
	})
});

app.get('/', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, true, md.mobile(), false);  // put the first boolean back on 'true' if your really want the fancy bg
});

app.get('/simple', function (req, res){
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, false, md.mobile(), false);
});

// force mobile (for testing purposes):
app.get('/mobile', function (req, res){
	renderView(req, res, false, true, false);
});

// force oldfashion upload (for testing purposes):
app.get('/oldfashionupload', function (req, res) {
	var md = new MobileDetect(req.headers['user-agent']);
	renderView(req, res, false, md.mobile(), true);
});

// force desktop
app.get('/desktop', function (req, res) {
	renderView(req, res, false, false, false);
});

function renderView(req, res, fancybg, mobile, forceOldFashionUpload, userid){
	getSomeRandomTilesWithPosition(50, function (err, tiles) {
		if(err) return utils.sendError(err, res);

		res.render('index', {
			title: '| MiX Kerstkaart 2013',
			tiles: tiles,
			card : {
				width: config.mosaic.greetingcard.lowres.width,
				height: config.mosaic.greetingcard.lowres.height,
				mosaicOffsetX: config.mosaic.greetingcard.lowres.offset.x,
				mosaicOffsetY: config.mosaic.greetingcard.lowres.offset.y
			},
			fancybg: fancybg,
			mobile: mobile,
			forceOldFashionUpload: forceOldFashionUpload,
			userid: userid
		});
	});
}

app.post('/xhrupload', function (req, res){
	if(!req.xhr) return utils.sendError(new Error('got no xhr request'), res);

	var size = req.header('x-file-size');
	var type = req.header('x-file-type');
	var name = path.basename(req.header('x-file-name'));

	//name = crypto.createHash('md5').update( ''+(Date.now()) ).digest('hex') + '_' + name;
	name = (Date.now()) + '_' + (utils.removeFileExt(name)).substr(0,6) + path.extname(name) ;
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	var ws = fs.createWriteStream( uploadedFile );

	req.on('data', function (data) {
		ws.write(data);
	});

	req.on('end', function () {
		console.log("Upload done");
		ws.end();
		renderMosaic(null, uploadedFile, req, res);
	});
});

app.post('/oldfashionupload', function (req, res) {
	if(!req.files.file) return renderView(req, res, false, false); // just render the normal page

	var name = req.files.file.name;

	name = (Date.now()) + '_' + (utils.removeFileExt(name)).substr(0,6) + path.extname(name) ;
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	fs.rename(req.files.file.path, uploadedFile, function (err) {
		if(err) return utils.sendError(err, res);

		var user = {
			userimage: uploadedFile,
		};

		mongobase.saveUser(user, function (err, user) {
			if(err) return utils.sendError(err, res);

			// dont render now, this is an old fashion upload: the browser is loading the page again

			// send user id (generated by DB) back to browser so it can request the creation of its mosaic:
			renderView(req, res, false, false, true, user._id);
		});
	});
});

app.post('/api/startrender', function (req, res) {
	if(!req.body.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser( req.body.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		renderMosaic( user, user.userimage, req, res );
	});
});

app.post('/api/uploaddataurl', function (req, res) {
	if(!req.body.dataURL) return utils.sendError(new Error('got no dataURL'), res);

	// incomming data:image/png;base64,iVBORw0KGgoAAAANSUh

	var base64Data = req.body.dataURL.replace(/^data:image\/png;base64,/,"");

	var name = (Date.now()) + '_webcam.png';
	var uploadedFile = path.join(ROOTDIR, config.mosaic.folders.main, name);

	require("fs").writeFile(uploadedFile, base64Data, 'base64', function (err) {
		if(err) return utils.sendError(err, res);

		renderMosaic( null, uploadedFile, req, res );
	});
});

function renderMosaic (user, userimage, req, res) {

	function renderMosaicCallbackHandler (err, mosaicimage, user) {
		if(err) return utils.sendError(err, res);

		console.log( "Mosaic ready... sending it back to browser" );
		console.log( utils.wwwdfy(mosaicimage) );
		console.log( "Generating twitpic url" );
		twitimage.twitPicImage(mosaicimage, function (err, twiturl) {

			// dont check errors
			// if twitpic failes, the app still works
			res.send({
				mosaicimage: utils.wwwdfy(mosaicimage),
				userid: user._id,
				twitpic: (twiturl)?twiturl: config.sharing.hardcodedUrl + utils.wwwdfy(mosaicimage),
				sharing: config.sharing,
				sharingurl: config.sharing.hardcodedUrl  + '/sharable/' + user._id
			});
		});
	}

	if(!user){
		var user = {
			userimage: userimage
		}
		mongobase.saveUser(user, function (err, user) {
			if(err) return utils.sendError(err, res);

			mosaic.renderMosaic( user, renderMosaicCallbackHandler );
		});
	}else{
		mosaic.renderMosaic( user, renderMosaicCallbackHandler );
	}
}

app.get('/highquality/:userid', function (req, res) {
	if(!req.params.userid) return utils.sendError(new Error('got no user id'), res);

	res.render('highquality', {
		title: 'Hoge Kwaliteitsversie| MiX Kerstkaart 2013',
		userid: req.params.userid
	});
});

app.post('/api/renderhq', function (req, res) {
	if(!req.body.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser( req.body.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		mosaic.renderMosaicHQ( user, function (err, mosaicimageHQ, user) {
			if(err) return utils.sendError(err, res);

			console.log( "Mosaic HQ ready... sending it back to browser" );
			console.log( mosaicimageHQ );
			console.log( utils.wwwdfy(mosaicimageHQ) );
			res.send({
				mosaicimageHQ: utils.wwwdfy(mosaicimageHQ),
				userid: user._id
			});

		});
	});
});

function getSomeRandomTilesWithPosition(nrOfTiles, callback){
	var tilesinfo = utils.getTilesInfo();

	// don't put fake tiles beyond a certain point (defined in config.js)
	var maxTilesHeigh = Math.floor(config.mosaic.greetingcard.dontPutFakeTilesBeyond / config.mosaic.tile.size);
	var maxTiles = maxTilesHeigh * tilesinfo.wide;

	mongobase.getAllTilesWithTitle(function (err, fulltiles) {
		if(err) return callback(err);

		var tiles = _.map(fulltiles, function (tile){
			return {
				title: tile.title,
				image: '/mosaic/' + tile.tileflying
			};
		});

		var possibleIndexes = [];
		for (var i = 0; i < maxTiles; i++) {
			possibleIndexes.push(i);
		};

		tiles = _.shuffle(tiles); //shuffle the tiles
		possibleIndexes = _.shuffle(possibleIndexes); // shuffle possible indexes

		tiles = tiles.slice(0, nrOfTiles);
		// add an index to each tile:
		for (var i = tiles.length - 1; i >= 0; i--) {
			tiles[i].index = possibleIndexes[i];
			tiles[i].top = utils.getTilePosition( possibleIndexes[i] ).y_px,
			tiles[i].left = utils.getTilePosition( possibleIndexes[i] ).x_px,
			tiles[i].size = config.mosaic.tile.size,
			tiles[i].maxsize = config.mosaic.flyingtile.size
		};

		callback( null, tiles );
	});
}

app.get('/sharable/:userid', function (req, res) {
	if(!req.params.userid) return utils.sendError(new Error('got no user id'), res);

	mongobase.getUser(req.params.userid, function (err, user) {
		if(err) return utils.sendError(err, res);

		res.render('sharable', {
			title: '| MiX Kerstkaart 2013',
			userid: req.params.userid,
			mosaicimage: utils.wwwdfy(user.finalOverlay)
		});
	});
});

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

var bl = require('bl');
var config = require('./config');
var express = require('express');
var fs = require('fs');
var mentionBot = require('./mention-bot.js');
var messageGenerator = require('./message.js');
var util = require('util');
var twss = require('twss');
twss.threshold = 0.9;

var GitHubApi = require('github');

var CONFIG_PATH = '.hubturbot';

if (!process.env.GITHUB_TOKEN) {
  console.error('The bot was started without a github account to post with.');
  console.error('To get started:');
  console.error('1) Create a new account for the bot');
  console.error('2) Settings > Personal access tokens > Generate new token');
  console.error('3) Only check `public_repo` and click Generate token');
  console.error('4) Run the following command:');
  console.error('GITHUB_TOKEN=insert_token_here npm start');
  console.error('5) Run the following command in another tab:');
  console.error('curl -X POST -d @__tests__/data/23.webhook http://localhost:5000/');
  console.error('6) Check that it commented here: https://github.com/fbsamples/bot-testing/pull/23');
  process.exit(1);
}

if (!process.env.GITHUB_USER) {
  console.warn(
    'There was no github user detected.',
    'This is fine, but mention-bot won\'t work with private repos.'
  );
  console.warn(
    'To make mention-bot work with private repos, please expose',
    'GITHUB_USER and GITHUB_PASSWORD as environment variables.',
    'The user and password must have access to the private repo',
    'you want to use.'
  );
}

var github = new GitHubApi({
  version: '3.0.0',
  host: config.github.apiHost,
  pathPrefix: config.github.pathPrefix,
  protocol: config.github.protocol,
  port: config.github.port
});

github.authenticate({
  type: 'oauth',
  token: process.env.GITHUB_TOKEN
});

var app = express();

function buildMentionSentence(reviewers) {

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

  var atReviewers = reviewers.map(function(owner) { return '@' + owner; });

  if (reviewers.length === 1) {
    return atReviewers[0];
  }

  return (
    atReviewers.slice(0, atReviewers.length - 1).join(', ') +
    ' and ' + atReviewers[atReviewers.length - 1]
  );
}

function defaultMessageGenerator(reviewers) {
  return util.format(
    'By analyzing the blame information on this pull request' +
     ', we identified %s to be%s potential reviewer%s. Good luck!',
     buildMentionSentence(reviewers),
     reviewers.length > 1 ? '' : ' a',
     reviewers.length > 1 ? 's' : ''
  );
}

function getRepoConfig(request) {
  return new Promise(function(resolve, reject) {
    github.repos.getContent(request, function(err, result) {
      if(err) {
        reject(err);
      }
      resolve(result);
    });
  });
}

async function suggestReviewer(config, data) {

  var reviewers = await mentionBot.guessOwnersForPullRequest(
    data.repository.html_url, // 'https://github.com/fbsamples/bot-testing'
    data.pull_request.number, // 23
    data.pull_request.user.login, // 'mention-bot'
    data.pull_request.base.ref, // 'master'
    config,
    github
  );

  console.log(data.pull_request.html_url, reviewers);

  if (reviewers.length === 0) {
    console.log('Skipping because there are no reviewers found.');
    return;
  }

  github.issues.createComment({
    user: data.repository.owner.login, // 'fbsamples'
    repo: data.repository.name, // 'bot-testing'
    number: data.pull_request.number, // 23
    body: messageGenerator(
      reviewers,
      buildMentionSentence,
      defaultMessageGenerator
    )
  });
}

function promisify(f) {
  return function() {
    var args = Array.prototype.slice.call(arguments);
    return new Promise(function(resolve, reject) {
      return f.apply(null, args.concat([function(err, res) {
        if (err) {
          reject(err);
        } else {
          resolve(res);
        }
      }]));
    });
  };
}

function applyToReview(config, user, repo, number) {
  return promisify(github.issues.getIssueLabels)({
    user, repo, number
  }).then(function(res) {

    var labels = res.map(r => r.name);

    // Remove other prefixed labels
    var groupRegex = new RegExp('^' + config.statusPrefix);
    var newLabels = labels
      .filter(label => !groupRegex.test(label))
      .concat([config.statusPrefix + config.reviewLabel]);

    return promisify(github.issues.edit)({
      user, repo, number, labels: newLabels
    });
  }).catch(function(e) {
    console.log('Failed to change label', e, e.stack)
    if (e.code === 404) {
      console.log('Have you added HubTurbot as a collaborator to your repository?');
    }
  });
}

function getIssueLabels(config, user, repo, number) {
  return promisify(github.issues.getIssueLabels)({
    user, repo, number
  }).then(res => res.map(r => r.name));
}

function getAllLabels(config, user, repo) {
  return promisify(github.issues.getLabels)({
    user, repo
  }).then(res => res.map(r => r.name));
}

function setLabels(config, user, repo, number, labels) {
  return promisify(github.issues.edit)({
    user, repo, number, labels
  }).catch(function (e) {
    console.log('Failed to set labels to', labels, e, e.stack);
    if (e.code === 404) {
      console.log('Have you added HubTurbot as a collaborator to your repository?');
    }
  });
}

function createDefaultLabels(config, data) {

  var statusPrefix = config.statusPrefix;

  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "Discarded",
    color: "000000"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "MergeApproved",
    color: "2A6E2F"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "Ongoing",
    color: "6BC471"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "OnHold",
    color: "E2F3E8"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToDiscuss",
    color: "bfe5bf"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToReview",
    color: "47B74E"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToMerge",
    color: "38923D"
  });
}

function determineLabelName(name) {
  var exclusive = /([\w\s]+)\.([\w\s]+)/;
  var nonexclusive = /([\w\s]+)-([\w\s]+)/;
  var match;

  if (match = exclusive.exec(name)) {
    return {
      group: match[1],
      name: match[2],
      full: name,
      exclusive: true
    };
  } else if (match = nonexclusive.exec(name)) {
    return {
      group: match[1],
      name: match[2],
      full: name,
      exclusive: false
    };
  } else {
    return {
      group: '',
      name,
      full: name,
      exclusive: false
    };
  }
}

function labelExists(allLabels, label) {
  var actualLabel = null

  for (var lab of allLabels) {
    var l = determineLabelName(lab);
    if (l.name.toLowerCase() === label.toLowerCase() || l.full.toLowerCase() === label.toLowerCase()) {
      if (actualLabel) {
        // Already set, label is ambiguous
        return null;
      }
      actualLabel = l.full
    }
  }

  return actualLabel;
}

async function handleIssueComment(config, data) {

  // HubTurbot will not reply to itself
  if (data.comment.user.login === "HubTurbot") {
    console.log('I don\'t respond to myself');
    return;
  }

  // Add or remove labels

  var comment = data.comment.body;
  var myself = /^@HubTurbot/i;
  var shouldRespond = myself.test(comment);
  if (!shouldRespond) {
    console.log('Not mentioned, not responding');
    return;
  }

  var existingLabels = data.issue.labels.map(r => r.name);
  console.log('Existing labels:', existingLabels);

  var mentionedLabel = comment.replace(myself, '').trim();

  var allLabels = await getAllLabels(config,data.repository.owner.login, data.repository.name);

  var mentionedLabel = labelExists(allLabels, mentionedLabel);
  if (!mentionedLabel) {
    console.log('Label does not exist or is ambiguous! Not adding.')
    return;
  }

  if (existingLabels.indexOf(mentionedLabel) >= 0) {
    var newLabels = existingLabels.filter(l => l !== mentionedLabel);
  } else {
    var parsedLabel = determineLabelName(mentionedLabel);
    if (parsedLabel.exclusive) {
      var newLabels = existingLabels
        .filter(l => determineLabelName(l).group !== parsedLabel.group)
        .concat([parsedLabel.full]);
    } else {
      var newLabels = existingLabels
        .concat([parsedLabel.full]);
    }
  }

  await setLabels(config,
    data.repository.owner.login,
    data.repository.name,
    data.issue.number,
    newLabels);

  console.log('New labels:', newLabels);
}

async function handlePRLabelChange(config, data) {

  if (data.sender.login === "HubTurbot")
    return;

  // Label added to PR
  if (data.action === "labeled") {
    if (data.label.name.toLowerCase().indexOf(config.reviewLabel.toLowerCase()) > 0) {
      if (data.pull_request.assignee) {
        console.log('Tagging reviewer');
        github.issues.createComment({
          user: data.repository.owner.login,
          repo: data.repository.name,
          number: data.pull_request.number,
          body: "Ready to review. " + buildMentionSentence(data.pull_request.assignee.login)
        });
      } else {
        console.log('Tagging team lead');
        github.issues.createComment({
          user: data.repository.owner.login,
          repo: data.repository.name,
          number: data.pull_request.number,
          body: "Ready to review, please assign a reviewer. " + buildMentionSentence(config.teamLead)
        });
      }
    } else if (data.label.name.toLowerCase().indexOf("critical") > 0) {
      console.log('Posting critical gif');
      github.issues.createComment({
        user: data.repository.owner.login,
        repo: data.repository.name,
        number: data.pull_request.number,
        body: "![Alt Text](https://media.giphy.com/media/AhjXalGPAfJg4/giphy.gif)"
      });
    }
  }

}

function handlePullRequest(config, data) {

  var actions = {
    opened: suggestReviewer,
    labeled: handlePRLabelChange
  };

  if (actions[data.action]) {
    return actions[data.action](config, data);
  }

  return Promise.resolve();
}

async function loadConfig(data) {

  var repoConfig = {
    maxReviewers: 3,
    numFilesToCheck: 5,
    userBlacklist: [],
    userBlacklistForPR: [],
    userWhitelist: [],
    fileBlacklist: [],
    requiredOrgs: [],
    findPotentialReviewers: true,

    teamLead: '',
    statusPrefix: 'status.',
    reviewLabel: 'toReview'
  };

  var user = data.repository.owner.login;
  var repo = data.repository.name;

  if (!(user && repo)) {
    console.log(util.format('Can\'t load config from %s/%s', user, repo));
    return repoConfig;
  }

  try {
    console.log(util.format('Getting config from %s/%s', user, repo));

    var configRes = await getRepoConfig({
      user, repo,
      path: CONFIG_PATH,
      headers: {
        Accept: 'application/vnd.github.v3.raw'
      }
    });

    repoConfig = {...repoConfig, ...JSON.parse(configRes)};
  } catch (e) {
    console.log('Failed to find or parse config file', e);
  }

  if (process.env.REQUIRED_ORG) {
    repoConfig.requiredOrgs.push(process.env.REQUIRED_ORG);
  }

  // TODO this won't work for all requests, since data.pull_requests sometimes will have no value

  // if (repoConfig.userBlacklistForPR.indexOf(data.pull_request.user.login) >= 0) {
  //   console.log('Skipping because blacklisted user ' +
  //     data.pull_request.user.login + 'created Pull Request.');
  //   return;
  // }

  return repoConfig;
}

async function work(body, req) {

  // console.log('\nbody: ' + body.toString());
  // console.log('\nheaders: ' + JSON.stringify(req.headers));

  var type = req.headers["x-github-event"];
  console.log('Event type:', type);

  var data = {};
  try {
    data = JSON.parse(body.toString());
  } catch (e) {
    console.error('Parse error in request body', e);
  }

  var config = await loadConfig(data);

  var actions = {
    issue_comment: handleIssueComment
  };

  // Call event type handler
  if (!actions[type]) {
    console.log("Not handling action: " + data.action);
  } else {
    console.log("Handling action: " + data.action);
    await actions[type](config, data);
  }
};

app.post('/', function(req, res) {
  req.pipe(bl(function(err, body) {
    work(body, req)
      .then(() => res.end())
      .catch(e => {
        console.error('An error occurred:', e, e.stack);
        res.end();
      });
 }));
});

app.get('/', function(req, res) {
  res.send(
    'GitHub Mention Bot Active. ' +
    'Go to https://github.com/facebook/mention-bot for more information.'
  );
});

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

app.listen(app.get('port'), function() {
  console.log('Listening on port', app.get('port'));
});

module.exports = app;<commit_msg>Removed redundant parameters<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

var bl = require('bl');
var config = require('./config');
var express = require('express');
var fs = require('fs');
var mentionBot = require('./mention-bot.js');
var messageGenerator = require('./message.js');
var util = require('util');
var twss = require('twss');
twss.threshold = 0.9;

var GitHubApi = require('github');

var CONFIG_PATH = '.hubturbot';

if (!process.env.GITHUB_TOKEN) {
  console.error('The bot was started without a github account to post with.');
  console.error('To get started:');
  console.error('1) Create a new account for the bot');
  console.error('2) Settings > Personal access tokens > Generate new token');
  console.error('3) Only check `public_repo` and click Generate token');
  console.error('4) Run the following command:');
  console.error('GITHUB_TOKEN=insert_token_here npm start');
  console.error('5) Run the following command in another tab:');
  console.error('curl -X POST -d @__tests__/data/23.webhook http://localhost:5000/');
  console.error('6) Check that it commented here: https://github.com/fbsamples/bot-testing/pull/23');
  process.exit(1);
}

if (!process.env.GITHUB_USER) {
  console.warn(
    'There was no github user detected.',
    'This is fine, but mention-bot won\'t work with private repos.'
  );
  console.warn(
    'To make mention-bot work with private repos, please expose',
    'GITHUB_USER and GITHUB_PASSWORD as environment variables.',
    'The user and password must have access to the private repo',
    'you want to use.'
  );
}

var github = new GitHubApi({
  version: '3.0.0',
  host: config.github.apiHost,
  pathPrefix: config.github.pathPrefix,
  protocol: config.github.protocol,
  port: config.github.port
});

github.authenticate({
  type: 'oauth',
  token: process.env.GITHUB_TOKEN
});

var app = express();

function buildMentionSentence(reviewers) {

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

  var atReviewers = reviewers.map(function(owner) { return '@' + owner; });

  if (reviewers.length === 1) {
    return atReviewers[0];
  }

  return (
    atReviewers.slice(0, atReviewers.length - 1).join(', ') +
    ' and ' + atReviewers[atReviewers.length - 1]
  );
}

function defaultMessageGenerator(reviewers) {
  return util.format(
    'By analyzing the blame information on this pull request' +
     ', we identified %s to be%s potential reviewer%s. Good luck!',
     buildMentionSentence(reviewers),
     reviewers.length > 1 ? '' : ' a',
     reviewers.length > 1 ? 's' : ''
  );
}

function getRepoConfig(request) {
  return new Promise(function(resolve, reject) {
    github.repos.getContent(request, function(err, result) {
      if(err) {
        reject(err);
      }
      resolve(result);
    });
  });
}

async function suggestReviewer(config, data) {

  var reviewers = await mentionBot.guessOwnersForPullRequest(
    data.repository.html_url, // 'https://github.com/fbsamples/bot-testing'
    data.pull_request.number, // 23
    data.pull_request.user.login, // 'mention-bot'
    data.pull_request.base.ref, // 'master'
    config,
    github
  );

  console.log(data.pull_request.html_url, reviewers);

  if (reviewers.length === 0) {
    console.log('Skipping because there are no reviewers found.');
    return;
  }

  github.issues.createComment({
    user: data.repository.owner.login, // 'fbsamples'
    repo: data.repository.name, // 'bot-testing'
    number: data.pull_request.number, // 23
    body: messageGenerator(
      reviewers,
      buildMentionSentence,
      defaultMessageGenerator
    )
  });
}

function promisify(f) {
  return function() {
    var args = Array.prototype.slice.call(arguments);
    return new Promise(function(resolve, reject) {
      return f.apply(null, args.concat([function(err, res) {
        if (err) {
          reject(err);
        } else {
          resolve(res);
        }
      }]));
    });
  };
}

function getAllLabels(user, repo) {
  return promisify(github.issues.getLabels)({
    user, repo
  }).then(res => res.map(r => r.name));
}

function setLabels(user, repo, number, labels) {
  return promisify(github.issues.edit)({
    user, repo, number, labels
  }).catch(function (e) {
    console.log('Failed to set labels to', labels, e, e.stack);
    if (e.code === 404) {
      console.log('Have you added HubTurbot as a collaborator to your repository?');
    }
  });
}

function createDefaultLabels(config, data) {

  var statusPrefix = config.statusPrefix;

  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "Discarded",
    color: "000000"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "MergeApproved",
    color: "2A6E2F"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "Ongoing",
    color: "6BC471"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "OnHold",
    color: "E2F3E8"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToDiscuss",
    color: "bfe5bf"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToReview",
    color: "47B74E"
  });
  github.issues.createLabel({
    user: data.repository.owner.login,
    repo: data.repository.name,
    name: statusPrefix + "ToMerge",
    color: "38923D"
  });
}

function determineLabelName(name) {
  var exclusive = /([\w\s]+)\.([\w\s]+)/;
  var nonexclusive = /([\w\s]+)-([\w\s]+)/;
  var match;

  if (match = exclusive.exec(name)) {
    return {
      group: match[1],
      name: match[2],
      full: name,
      exclusive: true
    };
  } else if (match = nonexclusive.exec(name)) {
    return {
      group: match[1],
      name: match[2],
      full: name,
      exclusive: false
    };
  } else {
    return {
      group: '',
      name,
      full: name,
      exclusive: false
    };
  }
}

function labelExists(allLabels, label) {
  var actualLabel = null

  for (var lab of allLabels) {
    var l = determineLabelName(lab);
    if (l.name.toLowerCase() === label.toLowerCase() || l.full.toLowerCase() === label.toLowerCase()) {
      if (actualLabel) {
        // Already set, label is ambiguous
        return null;
      }
      actualLabel = l.full
    }
  }

  return actualLabel;
}

async function handleIssueComment(config, data) {

  // HubTurbot will not reply to itself
  if (data.comment.user.login === "HubTurbot") {
    console.log('I don\'t respond to myself');
    return;
  }

  // Add or remove labels

  var comment = data.comment.body;
  var myself = /^@HubTurbot/i;
  var shouldRespond = myself.test(comment);
  if (!shouldRespond) {
    console.log('Not mentioned, not responding');
    return;
  }

  var existingLabels = data.issue.labels.map(r => r.name);
  console.log('Existing labels:', existingLabels);

  var mentionedLabel = comment.replace(myself, '').trim();

  var allLabels = await getAllLabels(data.repository.owner.login, data.repository.name);

  var mentionedLabel = labelExists(allLabels, mentionedLabel);
  if (!mentionedLabel) {
    console.log('Label does not exist or is ambiguous! Not adding.')
    return;
  }

  if (existingLabels.indexOf(mentionedLabel) >= 0) {
    var newLabels = existingLabels.filter(l => l !== mentionedLabel);
  } else {
    var parsedLabel = determineLabelName(mentionedLabel);
    if (parsedLabel.exclusive) {
      var newLabels = existingLabels
        .filter(l => determineLabelName(l).group !== parsedLabel.group)
        .concat([parsedLabel.full]);
    } else {
      var newLabels = existingLabels
        .concat([parsedLabel.full]);
    }
  }

  await setLabels(
    data.repository.owner.login,
    data.repository.name,
    data.issue.number,
    newLabels);

  console.log('New labels:', newLabels);
}

async function handlePRLabelChange(config, data) {

  if (data.sender.login === "HubTurbot")
    return;

  // Label added to PR
  if (data.action === "labeled") {
    if (data.label.name.toLowerCase().indexOf(config.reviewLabel.toLowerCase()) > 0) {
      if (data.pull_request.assignee) {
        console.log('Tagging reviewer');
        github.issues.createComment({
          user: data.repository.owner.login,
          repo: data.repository.name,
          number: data.pull_request.number,
          body: "Ready to review. " + buildMentionSentence(data.pull_request.assignee.login)
        });
      } else {
        console.log('Tagging team lead');
        github.issues.createComment({
          user: data.repository.owner.login,
          repo: data.repository.name,
          number: data.pull_request.number,
          body: "Ready to review, please assign a reviewer. " + buildMentionSentence(config.teamLead)
        });
      }
    } else if (data.label.name.toLowerCase().indexOf("critical") > 0) {
      console.log('Posting critical gif');
      github.issues.createComment({
        user: data.repository.owner.login,
        repo: data.repository.name,
        number: data.pull_request.number,
        body: "![Alt Text](https://media.giphy.com/media/AhjXalGPAfJg4/giphy.gif)"
      });
    }
  }

}

function handlePullRequest(config, data) {

  var actions = {
    opened: suggestReviewer,
    labeled: handlePRLabelChange
  };

  if (actions[data.action]) {
    return actions[data.action](config, data);
  }

  return Promise.resolve();
}

async function loadConfig(data) {

  var repoConfig = {
    maxReviewers: 3,
    numFilesToCheck: 5,
    userBlacklist: [],
    userBlacklistForPR: [],
    userWhitelist: [],
    fileBlacklist: [],
    requiredOrgs: [],
    findPotentialReviewers: true,

    teamLead: '',
    statusPrefix: 'status.',
    reviewLabel: 'toReview'
  };

  var user = data.repository.owner.login;
  var repo = data.repository.name;

  if (!(user && repo)) {
    console.log(util.format('Can\'t load config from %s/%s', user, repo));
    return repoConfig;
  }

  try {
    console.log(util.format('Getting config from %s/%s', user, repo));

    var configRes = await getRepoConfig({
      user, repo,
      path: CONFIG_PATH,
      headers: {
        Accept: 'application/vnd.github.v3.raw'
      }
    });

    repoConfig = {...repoConfig, ...JSON.parse(configRes)};
  } catch (e) {
    console.log('Failed to find or parse config file', e);
  }

  if (process.env.REQUIRED_ORG) {
    repoConfig.requiredOrgs.push(process.env.REQUIRED_ORG);
  }

  // TODO this won't work for all requests, since data.pull_requests sometimes will have no value

  // if (repoConfig.userBlacklistForPR.indexOf(data.pull_request.user.login) >= 0) {
  //   console.log('Skipping because blacklisted user ' +
  //     data.pull_request.user.login + 'created Pull Request.');
  //   return;
  // }

  return repoConfig;
}

async function work(body, req) {

  // console.log('\nbody: ' + body.toString());
  // console.log('\nheaders: ' + JSON.stringify(req.headers));

  var type = req.headers["x-github-event"];
  console.log('Event type:', type);

  var data = {};
  try {
    data = JSON.parse(body.toString());
  } catch (e) {
    console.error('Parse error in request body', e);
  }

  var config = await loadConfig(data);

  var actions = {
    issue_comment: handleIssueComment
  };

  // Call event type handler
  if (!actions[type]) {
    console.log("Not handling action: " + data.action);
  } else {
    console.log("Handling action: " + data.action);
    await actions[type](config, data);
  }
};

app.post('/', function(req, res) {
  req.pipe(bl(function(err, body) {
    work(body, req)
      .then(() => res.end())
      .catch(e => {
        console.error('An error occurred:', e, e.stack);
        res.end();
      });
 }));
});

app.get('/', function(req, res) {
  res.send(
    'GitHub Mention Bot Active. ' +
    'Go to https://github.com/facebook/mention-bot for more information.'
  );
});

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

app.listen(app.get('port'), function() {
  console.log('Listening on port', app.get('port'));
});

module.exports = app;<|endoftext|>


<commit_before>"use strict";

var express = require("express");

var app = express(),
    port = 8000,
    pubdir = __dirname + "/app";

app.configure(function () {
    app.use(express.static(pubdir));
    app.use(express.favicon(__dirname + pubdir + "/favicon.ico"));
    app.use(express.errorHandler());
});

app.listen(port, function () {
    console.log("piadinamia listening on port %s on folder %s",
        this.address().port, pubdir);
});
<commit_msg>Refactor server.js<commit_after>"use strict";

var path = require("path");

var express = require("express");

var app = express(),
    port = 8000,
    pubdir = path.join(__dirname, "/app");

app.configure(function () {
    app.use(express.static(pubdir));
    app.use(express.favicon(__dirname + pubdir + "/favicon.ico"));
    app.use(express.errorHandler());
});

app.listen(port, function () {
    console.log("piadinamia listening on port %s", port);
    console.log("static folder %s", pubdir);
});
<|endoftext|>


<commit_before>var dataRef = new Firebase("https://sudarshan.firebaseio.com/");
var chatRef = new Firebase("https://sudarshan.firebaseio.com/**chats**");
var id = Math.random().toString(16).slice(2);

filepicker.setKey("AzauR2MBSBeslVoQIcZ8gz");

var ytplayer = null;
var mp4player = null;

var roomName = null;
var tokboxSession = null;
var tokboxToken = null;

var disableUntil;

var last_in = null;

function makeRoom (name) {
  $.getJSON("http://www.smuralidhar.com/pennapps2014s/generate.php", function(res){
      dataRef = dataRef.root();
      dataRef = dataRef.child(name);
      dataRef.on('value', incoming);
      dataRef.update(
      {
        type: null,
        video: null,
        seek: 0,
        timestamp: now(),
        playing: false,
        sessionId: res.sessionId,
        token: res.token,
        owner: id
      }
    );
    chatRef = chatRef.child(name);
    chatRef.on('child_added', chatIn)
  });
}

function joinRoom (name) {
  dataRef = dataRef.root();
  dataRef = dataRef.child(name);
  dataRef.on('value', incoming);
  chatRef = chatRef.child(name);
  chatRef.on('child_added', chatIn)
}

function chatIn (fb) {
  var data = fb.val();
  var date = new Date(data.timestamp).toLocaleTimeString()
  var me = data.id == id ? " class='self'" : "";
  var html = "
" +
                "" + data.name + " " +
                "" +
                date.substring(0, date.length - 6) + " " +
                "" + data.message + "" +
            "
";
  $("#chat ul").append(html);
}

function chatOut (msg) {
  var nickname = $("#nickname")[0].value;
  chatRef.push({
    id: id,
    name: (nickname ? nickname : id),
    message: msg,
    timestamp: new Date().getTime()
  })
}

function incoming (fb) {
  var data = fb.val();
  last_in = data;
  console.log("inc");
  console.log(data);

  if (data == null){
    alert("room does not exist");
  }

  if (roomName == null){
    roomName = name;
    tokboxSession = data.sessionId;
    tokboxToken = data.token;
    showWelcomeMessage();
    $("#chat").show();
    $("#chat").prepend("
"+roomName+"
");

    runWebcam(tokboxSession, tokboxToken);
  }

  if (data.type == "YT") {
    if (ytplayer == null)
      makeYtPlayer(data.video);
    else
      handleYtInc(data);
  }
  else if (data.type == "mp4"){
    if (mp4player == null)
      makeMp4Player(data);
    else
      handleMp4Inc(data);
  }
}

function outgoing (playing, seek) {
  console.log("out");
  console.log({playing:playing, seek:seek});
  dataRef.update(
    {playing: playing, seek: seek, timestamp: now(), owner: id}
  );
}

function showWelcomeMessage () {
  $("#inputs").html("
	" +
    "<input id='vid' type='text' placeholder='Choose a video (Youtube or MP4)'></input>	" +
    "<button id='choose'>Load</button><button id='upload'>Upload</button>
");
  $("#choose").click(function(){
    var vid = $("#vid")[0].value + "#";
    if (vid.indexOf("youtube.com")>-1){
      var key = vid.substring(vid.indexOf("v=")+2, vid.indexOf("#"));
      var type = "YT";
      dataRef.update({type: type, video: key});
    }
    else if (vid.indexOf(".mp4") > -1){
      dataRef.update({type:"mp4", video: $("#vid")[0].value});
    }
    else
      alert ("Link not recognized");
  });
  $("#upload").click(function(){
    filepicker.pickAndStore(
      {extension: '.mp4', multiple:false},
      {location: 'S3'},
      function(InkBlobs){
        console.log(InkBlobs);
        var key = InkBlobs[0].key;
        dataRef.update({type: "mp4", video: res.url});
      });
    coverUp();
  });
}

function makeYtPlayer(vid) {
  disableUntil = -1;
  var params = { allowScriptAccess: "always" };
  var atts = { id: "myytplayer" };
  swfobject.embedSWF("http://www.youtube.com/v/" + vid + "?version=3&controls=1&enablejsapi=1&playerapiid=ytplayer&allowfullscreen=1",
    "ytapiplayer", "100%", "100%", "8", null, null, params, atts);
}
function makeMp4Player(data) {
  disableUntil = false;
  jwplayer("ytapiplayer").setup({file: data.video, width: "80%", height: "90%"});
  mp4player = jwplayer();
  mp4player.onReady(function() {
    console.log('setup');

    mp4player.onSeek(mp4SeekListener);
    mp4player.onPlay(function() {mp4PlayPauseListener(true)});
    mp4player.onPause(function() {mp4PlayPauseListener(false)});

    handleMp4Inc(data);

    setInterval(function(){
      dataRef.once('value', function(data){
        var pres = now();
        var curr = mp4player.getPosition();
        data = data.val();
        if (data.playing)
          loc = data.seek + pres - data.timestamp;
        else
          loc = data.seek;
        var playing = mp4player.getState() == "PLAYING";

        console.log(curr - loc);
        if (Math.abs (curr - loc) > 2 ||
            data.playing != playing){
          if (data.owner == id)
            outgoing(playing, mp4player.getPosition());
          else
            handleMp4Inc(data);
      }
      })
    }, 2000);
  })
}

function onYouTubePlayerReady(playerId) {
  ytplayer = $("#myytplayer")[0];
  ytplayer.addEventListener("onStateChange", "ytListener");

  handleYtInc(last_in);

  setInterval(function(){
    dataRef.once('value', function(data){
      var pres = now();
      var curr = ytplayer.getCurrentTime();
      data = data.val();
      if (data.playing)
        loc = data.seek + pres - data.timestamp;
      else
        loc = data.seek;
      var playing = ytplayer.getPlayerState() == 1;

      //console.log(curr - loc);
      if (Math.abs (curr - loc) > 0.5 ||
          data.playing != playing)
        handleYtInc(data);
    })
  }, 2000);
}

function handleYtInc(data) {
  // disable the listener until state is correct
  if (data.playing)
    disableUntil = 1;
  else
    disableUntil = 2;

  if (data.playing)
    data.seek += now() - data.timestamp;

  ytplayer.seekTo(data.seek);

  if (data.playing)
    ytplayer.playVideo();
  else
    ytplayer.pauseVideo();
}

function handleMp4Inc(data) {
  if(data.owner == id){
    console.log("ignoring own")
    return;
  }
  if (data.playing)
    data.seek += now() - data.timestamp;

  // ignore 2 events (assume it take under .05 seconds)
  disableUntil = true;
  console.log("disabling handlers");
  setTimeout(function(){
    disableUntil = false;
    console.log("TIME UP!")
  }, 50)
  mp4player.seek(data.seek);
  mp4player.play(data.playing);

  console.log('done handle');
}

function ytListener (value){
  if (disableUntil > -1){
    console.log("ignoring- " + value);
    if (disableUntil == value)
      disableUntil = -1;
    return;
  }
  switch (value) {
    case -1:
      console.log("unstarted");
      disableUntil = 2;
      ytplayer.seekTo(0);
      ytplayer.pauseVideo();
      break;
    case 0:
      console.log("ended");
      break;
    case 1:
      console.log("playing");
      disableUntil = 1;
      ytplayer.pauseVideo();
      outgoing (true, ytplayer.getCurrentTime());
      break;
    case 2:
      console.log("paused");
      disableUntil = 2;
      ytplayer.playVideo();
      outgoing (false, ytplayer.getCurrentTime());
      break;
    case 3:
      console.log("buffering");
      break;
    case 5:
      console.log("cued");
      break;
  }
}

function mp4PlayPauseListener (play){
  if (disableUntil){
    console.log("ignoring " + play);
    return;
  }

  console.log(play);

  //mp4player.pause(play);
  outgoing (play, mp4player.getPosition());
}
function mp4SeekListener () {
  if (disableUntil){
    console.log("ignoring seek");
    return;
  }
  console.log("seek");
  outgoing (false, mp4player.getPosition(), function(){
    mp4player.pause();
  });
}

function now () {
  return new Date().getTime() / 1000;
}

$(document).ready (function() {
  $("#create").click(function() {
    makeRoom($("#room")[0].value)
  });
  $("#join").click(function() {
    joinRoom($("#room")[0].value)
  });

  $("#message").keyup(function(e){
    e.preventDefault();
    var key = window.event ? e.keyCode : e.which;
    if (key == '13') {
        chatOut($("#message")[0].value);
	$("#message")[0].value = null;
    }
  })
})

function coverUp() {
  var iframe = $("#filepicker_dialog")
  var x = iframe.offset().left;
  var y = iframe.offset().top;
  var cover = $("<div style=\"z-index: 99999999999999; position:absolute;background:white; width:200px; height:75px;top:"+y+";left:"+x+"\"
").appendTo("body")

}
<commit_msg>chat css<commit_after>var dataRef = new Firebase("https://sudarshan.firebaseio.com/");
var chatRef = new Firebase("https://sudarshan.firebaseio.com/**chats**");
var id = Math.random().toString(16).slice(2);

filepicker.setKey("AzauR2MBSBeslVoQIcZ8gz");

var ytplayer = null;
var mp4player = null;

var roomName = null;
var tokboxSession = null;
var tokboxToken = null;

var disableUntil;

var last_in = null;

function makeRoom (name) {
  $.getJSON("http://www.smuralidhar.com/pennapps2014s/generate.php", function(res){
      dataRef = dataRef.root();
      dataRef = dataRef.child(name);
      dataRef.on('value', incoming);
      dataRef.update(
      {
        type: null,
        video: null,
        seek: 0,
        timestamp: now(),
        playing: false,
        sessionId: res.sessionId,
        token: res.token,
        owner: id
      }
    );
    chatRef = chatRef.child(name);
    chatRef.on('child_added', chatIn)
  });
}

function joinRoom (name) {
  dataRef = dataRef.root();
  dataRef = dataRef.child(name);
  dataRef.on('value', incoming);
  chatRef = chatRef.child(name);
  chatRef.on('child_added', chatIn)
}

function chatIn (fb) {
  var data = fb.val();
  var date = new Date(data.timestamp).toLocaleTimeString()
  var me = data.id == id ? " class='self'" : "";
  var html = "
" +
                "" + data.name + " " +
                "" +
                date.substring(0, date.length - 6) + " " +
                "" + data.message + "" +
            "
";
  $("#chat ul").append(html);
}

function chatOut (msg) {
  var nickname = $("#nickname")[0].value;
  chatRef.push({
    id: id,
    name: (nickname ? nickname : id),
    message: msg,
    timestamp: new Date().getTime()
  })
}

function incoming (fb) {
  var data = fb.val();
  last_in = data;
  console.log("inc");
  console.log(data);

  if (data == null){
    alert("room does not exist");
  }

  if (roomName == null){
    roomName = name;
    tokboxSession = data.sessionId;
    tokboxToken = data.token;
    showWelcomeMessage();
    $("#chat").show();
    $("#chat").prepend("
"+name+"
");

    runWebcam(tokboxSession, tokboxToken);
  }

  if (data.type == "YT") {
    if (ytplayer == null)
      makeYtPlayer(data.video);
    else
      handleYtInc(data);
  }
  else if (data.type == "mp4"){
    if (mp4player == null)
      makeMp4Player(data);
    else
      handleMp4Inc(data);
  }
}

function outgoing (playing, seek) {
  console.log("out");
  console.log({playing:playing, seek:seek});
  dataRef.update(
    {playing: playing, seek: seek, timestamp: now(), owner: id}
  );
}

function showWelcomeMessage () {
  $("#inputs").html("
	" +
    "<input id='vid' type='text' placeholder='Choose a video (Youtube or MP4)'></input>	" +
    "<button id='choose'>Load</button><button id='upload'>Upload</button>
");
  $("#choose").click(function(){
    var vid = $("#vid")[0].value + "#";
    if (vid.indexOf("youtube.com")>-1){
      var key = vid.substring(vid.indexOf("v=")+2, vid.indexOf("#"));
      var type = "YT";
      dataRef.update({type: type, video: key});
    }
    else if (vid.indexOf(".mp4") > -1){
      dataRef.update({type:"mp4", video: $("#vid")[0].value});
    }
    else
      alert ("Link not recognized");
  });
  $("#upload").click(function(){
    filepicker.pickAndStore(
      {extension: '.mp4', multiple:false},
      {location: 'S3'},
      function(InkBlobs){
        console.log(InkBlobs);
        var key = InkBlobs[0].key;
        dataRef.update({type: "mp4", video: res.url});
      });
    coverUp();
  });
}

function makeYtPlayer(vid) {
  disableUntil = -1;
  var params = { allowScriptAccess: "always" };
  var atts = { id: "myytplayer" };
  swfobject.embedSWF("http://www.youtube.com/v/" + vid + "?version=3&controls=1&enablejsapi=1&playerapiid=ytplayer&allowfullscreen=1",
    "ytapiplayer", "100%", "100%", "8", null, null, params, atts);
}
function makeMp4Player(data) {
  disableUntil = false;
  jwplayer("ytapiplayer").setup({file: data.video, width: "80%", height: "90%"});
  mp4player = jwplayer();
  mp4player.onReady(function() {
    console.log('setup');

    mp4player.onSeek(mp4SeekListener);
    mp4player.onPlay(function() {mp4PlayPauseListener(true)});
    mp4player.onPause(function() {mp4PlayPauseListener(false)});

    handleMp4Inc(data);

    setInterval(function(){
      dataRef.once('value', function(data){
        var pres = now();
        var curr = mp4player.getPosition();
        data = data.val();
        if (data.playing)
          loc = data.seek + pres - data.timestamp;
        else
          loc = data.seek;
        var playing = mp4player.getState() == "PLAYING";

        console.log(curr - loc);
        if (Math.abs (curr - loc) > 2 ||
            data.playing != playing){
          if (data.owner == id)
            outgoing(playing, mp4player.getPosition());
          else
            handleMp4Inc(data);
      }
      })
    }, 2000);
  })
}

function onYouTubePlayerReady(playerId) {
  ytplayer = $("#myytplayer")[0];
  ytplayer.addEventListener("onStateChange", "ytListener");

  handleYtInc(last_in);

  setInterval(function(){
    dataRef.once('value', function(data){
      var pres = now();
      var curr = ytplayer.getCurrentTime();
      data = data.val();
      if (data.playing)
        loc = data.seek + pres - data.timestamp;
      else
        loc = data.seek;
      var playing = ytplayer.getPlayerState() == 1;

      //console.log(curr - loc);
      if (Math.abs (curr - loc) > 0.5 ||
          data.playing != playing)
        handleYtInc(data);
    })
  }, 2000);
}

function handleYtInc(data) {
  // disable the listener until state is correct
  if (data.playing)
    disableUntil = 1;
  else
    disableUntil = 2;

  if (data.playing)
    data.seek += now() - data.timestamp;

  ytplayer.seekTo(data.seek);

  if (data.playing)
    ytplayer.playVideo();
  else
    ytplayer.pauseVideo();
}

function handleMp4Inc(data) {
  if(data.owner == id){
    console.log("ignoring own")
    return;
  }
  if (data.playing)
    data.seek += now() - data.timestamp;

  // ignore 2 events (assume it take under .05 seconds)
  disableUntil = true;
  console.log("disabling handlers");
  setTimeout(function(){
    disableUntil = false;
    console.log("TIME UP!")
  }, 50)
  mp4player.seek(data.seek);
  mp4player.play(data.playing);

  console.log('done handle');
}

function ytListener (value){
  if (disableUntil > -1){
    console.log("ignoring- " + value);
    if (disableUntil == value)
      disableUntil = -1;
    return;
  }
  switch (value) {
    case -1:
      console.log("unstarted");
      disableUntil = 2;
      ytplayer.seekTo(0);
      ytplayer.pauseVideo();
      break;
    case 0:
      console.log("ended");
      break;
    case 1:
      console.log("playing");
      disableUntil = 1;
      ytplayer.pauseVideo();
      outgoing (true, ytplayer.getCurrentTime());
      break;
    case 2:
      console.log("paused");
      disableUntil = 2;
      ytplayer.playVideo();
      outgoing (false, ytplayer.getCurrentTime());
      break;
    case 3:
      console.log("buffering");
      break;
    case 5:
      console.log("cued");
      break;
  }
}

function mp4PlayPauseListener (play){
  if (disableUntil){
    console.log("ignoring " + play);
    return;
  }

  console.log(play);

  //mp4player.pause(play);
  outgoing (play, mp4player.getPosition());
}
function mp4SeekListener () {
  if (disableUntil){
    console.log("ignoring seek");
    return;
  }
  console.log("seek");
  outgoing (false, mp4player.getPosition(), function(){
    mp4player.pause();
  });
}

function now () {
  return new Date().getTime() / 1000;
}

$(document).ready (function() {
  $("#create").click(function() {
    makeRoom($("#room")[0].value)
  });
  $("#join").click(function() {
    joinRoom($("#room")[0].value)
  });

  $("#message").keyup(function(e){
    e.preventDefault();
    var key = window.event ? e.keyCode : e.which;
    if (key == '13') {
        chatOut($("#message")[0].value);
	$("#message")[0].value = null;
    }
  })
})

function coverUp() {
  var iframe = $("#filepicker_dialog")
  var x = iframe.offset().left;
  var y = iframe.offset().top;
  var cover = $("<div style=\"z-index: 99999999999999; position:absolute;background:white; width:200px; height:75px;top:"+y+";left:"+x+"\"
").appendTo("body")

}
<|endoftext|>


<commit_before>/**
* The main app
*/
var App = angular.module('Video', [
  'lumx'
]);

App.config(function($locationProvider) {
  $locationProvider
  .html5Mode({ enabled: true, requireBase: false });
});

App.controller('Main', function($scope, $http, $location, $timeout, LxNotificationService, LxProgressService, LxDialogService) {
  // Namespaces
  var CHAT  = $rdf.Namespace("https://ns.rww.io/chat#");
  var CURR  = $rdf.Namespace("https://w3id.org/cc#");
  var DCT   = $rdf.Namespace("http://purl.org/dc/terms/");
  var FACE  = $rdf.Namespace("https://graph.facebook.com/schema/~/");
  var FOAF  = $rdf.Namespace("http://xmlns.com/foaf/0.1/");
  var LIKE  = $rdf.Namespace("http://ontologi.es/like#");
  var LDP   = $rdf.Namespace("http://www.w3.org/ns/ldp#");
  var MBLOG = $rdf.Namespace("http://www.w3.org/ns/mblog#");
  var OWL   = $rdf.Namespace("http://www.w3.org/2002/07/owl#");
  var PIM   = $rdf.Namespace("http://www.w3.org/ns/pim/space#");
  var RDF   = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
  var RDFS  = $rdf.Namespace("http://www.w3.org/2000/01/rdf-schema#");
  var SIOC  = $rdf.Namespace("http://rdfs.org/sioc/ns#");
  var SOLID = $rdf.Namespace("http://www.w3.org/ns/solid/app#");
  var TMP   = $rdf.Namespace("urn:tmp:");

  var f,g;

  /**
  * Init app
  */
  $scope.initApp = function() {
    $scope.init();
  };

  /**
  * TLS Login with WebID
  */
  $scope.TLSlogin = function() {
    var AUTHENDPOINT = "https://databox.me/";
    $scope.loginTLSButtonText = 'Logging in...';
    $http({
      method: 'HEAD',
      url: AUTHENDPOINT,
      withCredentials: true
    }).success(function(data, status, headers) {
      var header = 'User';
      var scheme = 'http';
      var user = headers(header);
      if (user && user.length > 0 && user.slice(0,scheme.length) === scheme) {
        $scope.notify('Login Successful!');
        $scope.loggedIn = true;
        $scope.user = user;
        $scope.fetchVideo();
      } else {
        $scope.notify('WebID-TLS authentication failed.', 'error');
      }
      $scope.loginTLSButtonText = 'Login';
    }).error(function(data, status, headers) {
      $scope.notify('Could not connect to auth server: HTTP '+status);
      $scope.loginTLSButtonText = 'Login';
    });
  };

  /**
  * Logout
  */
  $scope.logout = function() {
    $scope.init();
    $scope.notify('Logout Successful!');
  };

  /**
  * Notify
  * @param  {String} message the message to display
  * @param  {String} type the type of notification, error or success
  */
  $scope.notify = function(message, type) {
    console.log(message);
    if (type === 'error') {
      LxNotificationService.error(message);
    } else {
      LxNotificationService.success(message);
    }
  };

  /**
  * Set video in UI
  */
  $scope.setVideo = function (uri) {
    $scope.video = uri;
    var width = $('#video').width();
    if (width > 425) {
      width = 425;
    }
    var height = Math.round(( width * 3 ) / 4);
    var iframe = '';
    console.log(iframe);
    $('#video').empty().append(iframe);
  };

  /**
  * openDialog opens a dialog box
  * @param  {String} elem  The element to display
  */
  $scope.openDialog = function(elem) {
    LxDialogService.open(elem);
    $(document).keyup(function(e) {
      if (e.keyCode===27) {
        LxDialogService.close(elem);
      }
    });
  };

  /**
  * Save video
  */
  $scope.save = function() {
    var video = $scope.video;
    if (!video) {
      $scope.notify('video is empty', 'error');
      return;
    }
    console.log(video);

    $http({
      method: 'PUT',
      url: $scope.storageURI,
      withCredentials: true,
      headers: {
        "Content-Type": "text/turtle"
      },
      data: '<#this> ' + SIOC('content') + ' """' + video + '""" .',
    }).
    success(function(data, status, headers) {
      $scope.notify('video saved');
      $location.search('storageURI', $scope.storageURI);
    }).
    error(function(data, status, headers) {
      $scope.notify('could not save video', 'error');
    });

  };

  /**
  * Set Initial variables
  */
  $scope.init = function() {

    $scope.initialized = true;
    $scope.loggedIn = false;
    $scope.loginTLSButtonText = "Login";

    // start in memory DB
    g = $rdf.graph();
    f = $rdf.fetcher(g);

    $scope.storageURI = 'https://video.databox.me/Public/.video/test';
    if ($location.search().storageURI) {
      $scope.storageURI = $location.search().storageURI;
    }

  };

  /**
   * Fetches the video
   */
  $scope.fetchVideo = function() {
    f.nowOrWhenFetched($scope.storageURI, undefined, function(ok, body) {
      var video = g.any($rdf.sym($scope.storageURI + '#this'), SIOC('content'));
      $scope.setVideo(video);
    });
  };

  $scope.initApp();

});
<commit_msg>Set query string storageURI<commit_after>/**
* The main app
*/
var App = angular.module('Video', [
  'lumx'
]);

App.config(function($locationProvider) {
  $locationProvider
  .html5Mode({ enabled: true, requireBase: false });
});

App.controller('Main', function($scope, $http, $location, $timeout, LxNotificationService, LxProgressService, LxDialogService) {
  // Namespaces
  var CHAT  = $rdf.Namespace("https://ns.rww.io/chat#");
  var CURR  = $rdf.Namespace("https://w3id.org/cc#");
  var DCT   = $rdf.Namespace("http://purl.org/dc/terms/");
  var FACE  = $rdf.Namespace("https://graph.facebook.com/schema/~/");
  var FOAF  = $rdf.Namespace("http://xmlns.com/foaf/0.1/");
  var LIKE  = $rdf.Namespace("http://ontologi.es/like#");
  var LDP   = $rdf.Namespace("http://www.w3.org/ns/ldp#");
  var MBLOG = $rdf.Namespace("http://www.w3.org/ns/mblog#");
  var OWL   = $rdf.Namespace("http://www.w3.org/2002/07/owl#");
  var PIM   = $rdf.Namespace("http://www.w3.org/ns/pim/space#");
  var RDF   = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
  var RDFS  = $rdf.Namespace("http://www.w3.org/2000/01/rdf-schema#");
  var SIOC  = $rdf.Namespace("http://rdfs.org/sioc/ns#");
  var SOLID = $rdf.Namespace("http://www.w3.org/ns/solid/app#");
  var TMP   = $rdf.Namespace("urn:tmp:");

  var f,g;

  /**
  * Init app
  */
  $scope.initApp = function() {
    $scope.init();
  };

  /**
  * TLS Login with WebID
  */
  $scope.TLSlogin = function() {
    var AUTHENDPOINT = "https://databox.me/";
    $scope.loginTLSButtonText = 'Logging in...';
    $http({
      method: 'HEAD',
      url: AUTHENDPOINT,
      withCredentials: true
    }).success(function(data, status, headers) {
      var header = 'User';
      var scheme = 'http';
      var user = headers(header);
      if (user && user.length > 0 && user.slice(0,scheme.length) === scheme) {
        $scope.notify('Login Successful!');
        $scope.loggedIn = true;
        $scope.user = user;
        $scope.fetchVideo();
      } else {
        $scope.notify('WebID-TLS authentication failed.', 'error');
      }
      $scope.loginTLSButtonText = 'Login';
    }).error(function(data, status, headers) {
      $scope.notify('Could not connect to auth server: HTTP '+status);
      $scope.loginTLSButtonText = 'Login';
    });
  };

  /**
  * Logout
  */
  $scope.logout = function() {
    $scope.init();
    $scope.notify('Logout Successful!');
  };

  /**
  * Notify
  * @param  {String} message the message to display
  * @param  {String} type the type of notification, error or success
  */
  $scope.notify = function(message, type) {
    console.log(message);
    if (type === 'error') {
      LxNotificationService.error(message);
    } else {
      LxNotificationService.success(message);
    }
  };

  /**
  * Set video in UI
  */
  $scope.setVideo = function (uri) {
    $scope.video = uri;
    var width = $('#video').width();
    if (width > 425) {
      width = 425;
    }
    var height = Math.round(( width * 3 ) / 4);
    var iframe = '';
    $('#video').empty().append(iframe);
    $location.search('storageURI', $scope.storageURI);
  };

  /**
  * openDialog opens a dialog box
  * @param  {String} elem  The element to display
  */
  $scope.openDialog = function(elem) {
    LxDialogService.open(elem);
    $(document).keyup(function(e) {
      if (e.keyCode===27) {
        LxDialogService.close(elem);
      }
    });
  };

  /**
  * Save video
  */
  $scope.save = function() {
    var video = $scope.video;
    if (!video) {
      $scope.notify('video is empty', 'error');
      return;
    }
    console.log(video);

    $http({
      method: 'PUT',
      url: $scope.storageURI,
      withCredentials: true,
      headers: {
        "Content-Type": "text/turtle"
      },
      data: '<#this> ' + SIOC('content') + ' """' + video + '""" .',
    }).
    success(function(data, status, headers) {
      $scope.notify('video saved');
      $location.search('storageURI', $scope.storageURI);
    }).
    error(function(data, status, headers) {
      $scope.notify('could not save video', 'error');
    });

  };

  /**
  * Set Initial variables
  */
  $scope.init = function() {

    $scope.initialized = true;
    $scope.loggedIn = false;
    $scope.loginTLSButtonText = "Login";

    // start in memory DB
    g = $rdf.graph();
    f = $rdf.fetcher(g);

    $scope.storageURI = 'https://video.databox.me/Public/.video/test';
    if ($location.search().storageURI) {
      $scope.storageURI = $location.search().storageURI;
    }

  };

  /**
   * Fetches the video
   */
  $scope.fetchVideo = function() {
    f.nowOrWhenFetched($scope.storageURI, undefined, function(ok, body) {
      var video = g.any($rdf.sym($scope.storageURI + '#this'), SIOC('content'));
      $scope.setVideo(video);
    });
  };

  $scope.initApp();

});
<|endoftext|>


<commit_before>;

import angular from 'angular';
import squareImageModule from '../components/square-image';
import { attach, decodeUriComponentProperly } from '../utils';
import won from '../won-es6';
import { labels } from '../won-label-utils';
import {
    selectOpenPostUri,
    selectAllMessagesByNeedUri,
} from '../selectors';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                    <won-square-image
                        ng-class="{'inactive' : !self.isActive}"
                        src="self.post.get('titleImgSrc')"
                        title="self.post.get('title')"
                        uri="self.post.get('uri')">
                    </won-square-image>

                        <hgroup>

{{ self.post.get('title') }}

{{self.labels.type[self.post.get('type')]}}

                        </hgroup>

                                <button
                                    class="won-button--filled thin red"
                                    ng-show="self.isActive"
                                    ng-click="self.closePost()">
                                        Close Post
                                </button>
                                <button
                                    class="won-button--filled thin red"
                                    ng-show="!self.isActive"
                                    ng-click="self.reOpenPost()">
                                        Reopen Post
                                </button>

                                    Post Info

                                    Messages
                                    {{ self.unreadMessagesCount }}

                                    Matches
                                    {{ self.unreadMatchesCount }}

                                    Requests
                                    {{ self.unreadIncomingRequestsCount }}

                                    Sent Requests
                                    {{ self.unreadSentRequestsCount }}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);

            window.otb = this;
            this.labels = labels;
            this.settingsOpen = false;

            const selectFromState = (state)=>{
                const postUri = selectOpenPostUri(state);
                const post = state.getIn(["needs", postUri]);

                const connections = post && post.get("connections");

                const sentRequests = connections && connections.filter(conn => conn.get("state") === won.WON.RequestSent);
                const incomingRequests = connections && connections.filter(conn => conn.get("state") === won.WON.RequestReceived);
                const matches = connections && connections.filter(conn => conn.get("state") === won.WON.Suggested);
                const connected = connections && connections.filter(conn => conn.get("state") === won.WON.Connected);
                const messages = selectAllMessagesByNeedUri(state, postUri);

                const unreadMatchesCount = matches && matches.filter(conn => conn.get("newConnection")).size;
                const unreadSentRequestsCount = sentRequests && sentRequests.filter(conn => conn.get("newConnection")).size;
                const unreadIncomingRequestsCount = incomingRequests && incomingRequests.filter(conn => conn.get("newConnection")).size;
                const unreadMessagesCount = messages && messages.filter(msg => msg.get('newMessage')).size ;

                return {
                    selectedTab: decodeUriComponentProperly(state.getIn(['router', 'currentParams', 'connectionType'])) || 'Info',
                    WON: won.WON,
                    postUri: postUri,
                    post: post,
                    hasIncomingRequests: incomingRequests && incomingRequests.size > 0,
                    hasSentRequests: sentRequests && sentRequests.size > 0,
                    hasMatches: matches && matches.size > 0,
                    hasConnected: connected && connected.size > 0,
                    unreadMessagesCount: unreadMessagesCount > 0 ? unreadMessagesCount : undefined,
                    unreadIncomingRequestsCount: unreadIncomingRequestsCount > 0 ? unreadIncomingRequestsCount : undefined,
                    unreadSentRequestsCount: unreadSentRequestsCount > 0 ? unreadSentRequestsCount : undefined,
                    unreadMatchesCount: unreadMatchesCount > 0 ? unreadMatchesCount : undefined,
                    isActive: post && post.get('state') === won.WON.ActiveCompacted,
                };
            };

            const disconnect = this.$ngRedux.connect(selectFromState, actionCreators)(this);
            this.$scope.$on('$destroy', disconnect);
        }

        closePost() {
            console.log("CLOSING THE POST: "+this.postUri);
            this.settingsOpen = false;
            this.needs__close(this.postUri);
        }

        reOpenPost() {
            console.log("RE-OPENING THE POST: "+this.postUri);
            this.settingsOpen = false;
            this.needs__reopen(this.postUri);
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        template: template,
        scope: {
            selection: "=",
        }
    }
}

export default angular.module('won.owner.components.needTitleBar', [])
    .directive('wonOwnerTitleBar', genComponentConf)
    .name;
<commit_msg>do not count connectmessages as new messages<commit_after>;

import angular from 'angular';
import squareImageModule from '../components/square-image';
import { attach, decodeUriComponentProperly } from '../utils';
import won from '../won-es6';
import { labels } from '../won-label-utils';
import {
    selectOpenPostUri,
    selectAllMessagesByNeedUri,
} from '../selectors';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                    <won-square-image
                        ng-class="{'inactive' : !self.isActive}"
                        src="self.post.get('titleImgSrc')"
                        title="self.post.get('title')"
                        uri="self.post.get('uri')">
                    </won-square-image>

                        <hgroup>

{{ self.post.get('title') }}

{{self.labels.type[self.post.get('type')]}}

                        </hgroup>

                                <button
                                    class="won-button--filled thin red"
                                    ng-show="self.isActive"
                                    ng-click="self.closePost()">
                                        Close Post
                                </button>
                                <button
                                    class="won-button--filled thin red"
                                    ng-show="!self.isActive"
                                    ng-click="self.reOpenPost()">
                                        Reopen Post
                                </button>

                                    Post Info

                                    Messages
                                    {{ self.unreadMessagesCount }}

                                    Matches
                                    {{ self.unreadMatchesCount }}

                                    Requests
                                    {{ self.unreadIncomingRequestsCount }}

                                    Sent Requests
                                    {{ self.unreadSentRequestsCount }}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);

            window.otb = this;
            this.labels = labels;
            this.settingsOpen = false;

            const selectFromState = (state)=>{
                const postUri = selectOpenPostUri(state);
                const post = state.getIn(["needs", postUri]);

                const connections = post && post.get("connections");

                const sentRequests = connections && connections.filter(conn => conn.get("state") === won.WON.RequestSent);
                const incomingRequests = connections && connections.filter(conn => conn.get("state") === won.WON.RequestReceived);
                const matches = connections && connections.filter(conn => conn.get("state") === won.WON.Suggested);
                const connected = connections && connections.filter(conn => conn.get("state") === won.WON.Connected);
                const messages = selectAllMessagesByNeedUri(state, postUri);

                const unreadMatchesCount = matches && matches.filter(conn => conn.get("newConnection")).size;
                const unreadSentRequestsCount = sentRequests && sentRequests.filter(conn => conn.get("newConnection")).size;
                const unreadIncomingRequestsCount = incomingRequests && incomingRequests.filter(conn => conn.get("newConnection")).size;
                const unreadMessagesCount = messages && messages.filter(msg => msg.get('newMessage') && !msg.get("connectMessage")).size;

                return {
                    selectedTab: decodeUriComponentProperly(state.getIn(['router', 'currentParams', 'connectionType'])) || 'Info',
                    WON: won.WON,
                    postUri: postUri,
                    post: post,
                    hasIncomingRequests: incomingRequests && incomingRequests.size > 0,
                    hasSentRequests: sentRequests && sentRequests.size > 0,
                    hasMatches: matches && matches.size > 0,
                    hasConnected: connected && connected.size > 0,
                    unreadMessagesCount: unreadMessagesCount > 0 ? unreadMessagesCount : undefined,
                    unreadIncomingRequestsCount: unreadIncomingRequestsCount > 0 ? unreadIncomingRequestsCount : undefined,
                    unreadSentRequestsCount: unreadSentRequestsCount > 0 ? unreadSentRequestsCount : undefined,
                    unreadMatchesCount: unreadMatchesCount > 0 ? unreadMatchesCount : undefined,
                    isActive: post && post.get('state') === won.WON.ActiveCompacted,
                };
            };

            const disconnect = this.$ngRedux.connect(selectFromState, actionCreators)(this);
            this.$scope.$on('$destroy', disconnect);
        }

        closePost() {
            console.log("CLOSING THE POST: "+this.postUri);
            this.settingsOpen = false;
            this.needs__close(this.postUri);
        }

        reOpenPost() {
            console.log("RE-OPENING THE POST: "+this.postUri);
            this.settingsOpen = false;
            this.needs__reopen(this.postUri);
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        template: template,
        scope: {
            selection: "=",
        }
    }
}

export default angular.module('won.owner.components.needTitleBar', [])
    .directive('wonOwnerTitleBar', genComponentConf)
    .name;
<|endoftext|>


<commit_before>/* jshint node: true */

module.exports = function(deployTarget) {
  var ENV = {
    build: {}
    // include other plugin configuration that applies to all deploy targets here
  };
  ENV.s3 = {
    bucket: process.env.AWS_BUCKET,
    region: process.env.AWS_REGION
  };

  ENV['s3-index'] = {
    bucket: process.env.AWS_BUCKET,
    region: process.env.AWS_REGION,
    allowOverwrite: true
  };

  ENV.slack = {
    webhookURL: process.env.WEBHOOK_URL,
    channel: '#github',
    username: 'ember-cli-deploy'
  }

  ENV.cloudfront = {
  distribution: 'E17GXVYW7G712O'
}

  if (deployTarget === 'development') {
    ENV.build.environment = 'development';
    // configure other plugins for development deploy target here
    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed development frontend!'
        });
      };
    }
  }

  if (deployTarget === 'staging') {
    ENV.build.environment = 'staging';
    // configure other plugins for staging deploy target here

    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed staging frontend!'
        });
      };
    }
  }

  if (deployTarget === 'production') {
    ENV.build.environment = 'production';
    // configure other plugins for production deploy target here

    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed production frontend!'
        });
      };
    }
  }

  // Note: if you need to build some configuration asynchronously, you can return
  // a promise that resolves with the ENV object instead of returning the
  // ENV object synchronously.
  return ENV;
};
<commit_msg>use proper distribution id<commit_after>/* jshint node: true */

module.exports = function(deployTarget) {
  var ENV = {
    build: {}
    // include other plugin configuration that applies to all deploy targets here
  };
  ENV.s3 = {
    bucket: process.env.AWS_BUCKET,
    region: process.env.AWS_REGION
  };

  ENV['s3-index'] = {
    bucket: process.env.AWS_BUCKET,
    region: process.env.AWS_REGION,
    allowOverwrite: true
  };

  ENV.slack = {
    webhookURL: process.env.WEBHOOK_URL,
    channel: '#github',
    username: 'ember-cli-deploy'
  }

  ENV.cloudfront = {
  distribution: 'E2YVUU4RPYNUI2'
}

  if (deployTarget === 'development') {
    ENV.build.environment = 'development';
    // configure other plugins for development deploy target here
    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed development frontend!'
        });
      };
    }
  }

  if (deployTarget === 'staging') {
    ENV.build.environment = 'staging';
    // configure other plugins for staging deploy target here

    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed staging frontend!'
        });
      };
    }
  }

  if (deployTarget === 'production') {
    ENV.build.environment = 'production';
    // configure other plugins for production deploy target here

    ENV.slack.didDeploy = function(context) {
      return function(slack) {
        return slack.notify({
          text: 'Deployed production frontend!'
        });
      };
    }
  }

  // Note: if you need to build some configuration asynchronously, you can return
  // a promise that resolves with the ENV object instead of returning the
  // ENV object synchronously.
  return ENV;
};
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')
const Database = require('./database')
const Pipedrive = require('pipedrive')
const BeepBoop = require('beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000
var db = new Database(
			  process.env.DB_HOST,
			  process.env.DB_PORT || 3306,
			  process.env.DB_USER,
			  process.env.DB_PASSWORD)
var pdClients = {}

var beepboop = BeepBoop.start()
beepboop.on('open', function () {
  console.log('connection to Beep Boop server opened')
})
beepboop.on('error', function (error) {
  console.log('Error from Beep Boop connection: ', err)
})
beepboop.on('close', function (code, message) {
  console.log('Connection to Beep Boop was closed')
})
beepboop.on('add_resource', function (message) {
  console.log('Team added: ', message)
  pdClients[message.resource.SlackTeamID] = new Pipedrive.Client(message.resource.PIPEDRIVE_API_KEY)
  console.log('Pipedrive client created with API key: ', message.resource.PIPEDRIVE_API_KEY)
})

var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})
//*********************************************
// Setup different handlers for messages
//*********************************************

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
  .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    msg
      .say(`${text}, how are you?`)
      // sends next event from user to this route, passing along state
      .route('how-are-you', { greeting: text })
  })
  .route('how-are-you', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("Whoops, I'm still waiting to hear how you're doing.")
        .say('How are you?')
        .route('how-are-you', state)
    }

    // add their response to state
    state.status = text

    msg
      .say(`Ok then. What's your favorite color?`)
      .route('color', state)
  })
  .route('color', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("I'm eagerly awaiting to hear your favorite color.")
        .route('color', state)
    }

    // add their response to state
    state.color = text

    msg
      .say('Thanks for sharing.')
      .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // At this point, since we don't route anywhere, the "conversation" is over
  })

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

// demonstrate returning an attachment...
slapp.message('attachment', ['direct_mention', 'direct_message'], (msg, text) => {
	var deal = db.getDealForChannel(text)
	msg.say(`Found deal: $(deal)`)
/*  msg.say({
    text: 'Check out this amazing attachment! :confetti_ball: ',
    attachments: [{
      text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      title: 'Slapp Library - Open Source',
      image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      title_link: 'https://beepboophq.com/',
      color: '#7CD197'
    }]
  })*/
})

// handle channel join
slapp.event('message', (msg) => {
    if (msg.isBot() && msg.isMessage() && msg.body.event.subtype === 'channel_join') {
    	msg.say("thanks for inviting me!")
    }
})

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<commit_msg>enabled debugging for beepboop resourcer<commit_after>'use strict'

const express = require('express')
const Slapp = require('slapp')
const ConvoStore = require('slapp-convo-beepboop')
const Context = require('slapp-context-beepboop')
const Database = require('./database')
const Pipedrive = require('pipedrive')
const BeepBoop = require('beepboop')

// use `PORT` env var on Beep Boop - default to 3000 locally
var port = process.env.PORT || 3000
var db = new Database(
			  process.env.DB_HOST,
			  process.env.DB_PORT || 3306,
			  process.env.DB_USER,
			  process.env.DB_PASSWORD)
var pdClients = {}

var beepboop = BeepBoop.start({
	debug: true
	})
beepboop.on('open', () => {
  console.log('connection to Beep Boop server opened')
})
beepboop.on('error', (error) => {
  console.log('Error from Beep Boop connection: ', err)
})
beepboop.on('close', (code, message) => {
  console.log('Connection to Beep Boop was closed')
})
beepboop.on('add_resource', (message) => {
  console.log('Team added: ', message)
  pdClients[message.resource.SlackTeamID] = new Pipedrive.Client(message.resource.PIPEDRIVE_API_KEY)
  console.log('Pipedrive client created with API key: ', message.resource.PIPEDRIVE_API_KEY)
})
var slapp = Slapp({
  // Beep Boop sets the SLACK_VERIFY_TOKEN env var
  verify_token: process.env.SLACK_VERIFY_TOKEN,
  convo_store: ConvoStore(),
  context: Context()
})
//*********************************************
// Setup different handlers for messages
//*********************************************

// "Conversation" flow that tracks state - kicks off when user says hi, hello or hey
slapp
  .message('^(hi|hello|hey)$', ['direct_mention', 'direct_message'], (msg, text) => {
    msg
      .say(`${text}, how are you?`)
      // sends next event from user to this route, passing along state
      .route('how-are-you', { greeting: text })
  })
  .route('how-are-you', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("Whoops, I'm still waiting to hear how you're doing.")
        .say('How are you?')
        .route('how-are-you', state)
    }

    // add their response to state
    state.status = text

    msg
      .say(`Ok then. What's your favorite color?`)
      .route('color', state)
  })
  .route('color', (msg, state) => {
    var text = (msg.body.event && msg.body.event.text) || ''

    // user may not have typed text as their next action, ask again and re-route
    if (!text) {
      return msg
        .say("I'm eagerly awaiting to hear your favorite color.")
        .route('color', state)
    }

    // add their response to state
    state.color = text

    msg
      .say('Thanks for sharing.')
      .say(`Here's what you've told me so far: \`\`\`${JSON.stringify(state)}\`\`\``)
    // At this point, since we don't route anywhere, the "conversation" is over
  })

// Can use a regex as well
slapp.message(/^(thanks|thank you)/i, ['mention', 'direct_message'], (msg) => {
  // You can provide a list of responses, and a random one will be chosen
  // You can also include slack emoji in your responses
  msg.say([
    "You're welcome :smile:",
    'You bet',
    ':+1: Of course',
    'Anytime :sun_with_face: :full_moon_with_face:'
  ])
})

// demonstrate returning an attachment...
slapp.message('attachment', ['direct_mention', 'direct_message'], (msg, text) => {
	var deal = db.getDealForChannel(text)
	msg.say(`Found deal: $(deal)`)
/*  msg.say({
    text: 'Check out this amazing attachment! :confetti_ball: ',
    attachments: [{
      text: 'Slapp is a robust open source library that sits on top of the Slack APIs',
      title: 'Slapp Library - Open Source',
      image_url: 'https://storage.googleapis.com/beepboophq/_assets/bot-1.22f6fb.png',
      title_link: 'https://beepboophq.com/',
      color: '#7CD197'
    }]
  })*/
})

// handle channel join
slapp.event('message', (msg) => {
    if (msg.isBot() && msg.isMessage() && msg.body.event.subtype === 'channel_join') {
    	msg.say("thanks for inviting me!")
    }
})

// attach Slapp to express server
var server = slapp.attachToExpress(express())

// start http server
server.listen(port, (err) => {
  if (err) {
    return console.error(err)
  }

  console.log(`Listening on port ${port}`)
})
<|endoftext|>