<commit_before>var express = require('express')
  , http = require('http')
  , path = require('path')
  , routes = require('./routes')
  , db = require('./db')
  , auth = require('./auth')
  , util = require('./util')
  , async = require('async')
  , fundmanager = require('./fundmanager')
  , fs = require('fs')
  , resize = require('./resize')

var app = express();

var HTTP_PORT = 8080; // main webserver
var WS_PORT = 8081; // websockets for notifications

app.configure(function(){
	// all environments
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');

	app.disable('x-powered-by');
	app.use(express.cookieParser());
	app.use(express.logger('dev'));
	app.use(express.bodyParser({
		uploadDir: './tmp'
	}));
	app.use(function(req, res, next) {
		var discardOriginalFile = function() {
			if (!req.files) return;

			for (name in req.files) {
				fs.unlinkSync(req.files[name].path);
			}
		}

		if (req.url.match(/^\/uploadimage/)) {
			if (!req.files.file) {
				discardOriginalFile();
				res.statusCode = 500;
				res.send("500 Internal Server Error: No file submitted.");
				return;
			}

			var path = "/" + req.files.file.path;
			var newname = util.token();

			async.parallel({
				orig: function(cb) {
					resize(path, "/public/uploads/" + newname + "_orig", false, false, cb)
				},
				thumb32: function(cb) {
					resize(path, "/public/uploads/" + newname + "_32", 32, 32, cb)
				},
				thumb55: function(cb) {
					resize(path, "/public/uploads/" + newname + "_55", 55, 55, cb)
				},
				thumb64: function(cb) {
					resize(path, "/public/uploads/" + newname + "_64", 64, 64, cb)
				},
				thumb140: function(cb) {
					resize(path, "/public/uploads/" + newname + "_140", 140, 140, cb)
				}
			}, function(err, results) {
				if (err) {
					console.log(err);
					discardOriginalFile();
					res.statusCode = 500;
					res.send("500 Internal Server Error: Invalid file format.");
					return;
				}

				for (name in results) {
					results[name] = results[name].replace("/public", "")
				}

				db.query("INSERT INTO imageuploads (orig, thumb32, thumb55, thumb64, thumb140, ip) values (?, ?, ?, ?, ?, ?)",
					[results.orig, results.thumb32, results.thumb55, results.thumb64, results.thumb140, util.ip(req)],
					function(err, r) {
						if (err) {
							discardOriginalFile();
							res.statusCode = 500;
							res.send("500 Internal Server Error: Couldn't save attachment.");
							return;
						}

						results.id = r.insertId;

						discardOriginalFile();
						res.send(JSON.stringify(results));
					}
				);
			})
		} else {
			discardOriginalFile();
			next();
		}
	})
	app.use(express.methodOverride());
	app.use(function(req, res, next) {
		var method = req.method;

		if (method == "POST" && req.path != "/qps_login") {
			if ((!util.isValidToken(req.body.csrf)) || (req.body.csrf != req.cookies.csrf)) {
				res.statusCode = 403;
				res.send("403 Forbidden: CSRF validation failure.");
			} else {
				next();
			}
		} else {
			next();
		}
	})
	app.use(function(req, res, next) {
		if (!util.isValidToken(req.cookies.csrf)) {
			res.cookie('csrf', util.token(), {maxAge: 94636000000, httpOnly:false})
		}
		next();
	})
	app.use(util.verifyRecaptcha);
	app.use(function(req, res, next) {
		res.locals._nl2br_escape = util.nl2br_escape;
		res.locals._quote = util.quote;
		res.locals._isset = util.isset;
		res.locals._timeSince = util.timeSince;
		res.locals._timeUntil = util.timeUntil;
		res.locals._attachment = util.attachment;
		res.locals._slug = util.slug;
		res.locals._repeat = util.repeat;

		if (req.url.substring(0, 6) == '/ajax/') {
			req.url = req.url.substring(5);
			res.locals.__REQUEST_TYPE = 'ajax';
			res.locals.__REQUEST_URL = req.url;
		} else {
			res.locals.__REQUEST_TYPE = 'normal';
			res.locals.__REQUEST_URL = req.url;
		}

		next();
	});

	app.use(express.static(path.join(__dirname, 'public'), {
		maxAge: 86400000
	}));
	app.use(app.router);

	app.use(function(err, req, res, next) {
		if (!err) next();

		console.log(err);
		res.statusCode = 500;
		res.send("<script>notifybox(\"We're sorry, there was an error with your request. :(\");</script>");
	});
});

/// ROUTEWARE:
// auth.require - require authentication
// auth.build - build authentication
// util.prepareLayout - prepare layout (navbar, footer) if non-ajax request // todo consider placing this on everything
//////////////////////////////////////////////////////////////////////////////////////

app.get('/health', util.prepareLayout, function(req, res) {
	util.redirect(req, res, "http://www.reddit.com/r/gonewild+nsfw+RealGirls+ass+BustyPetite+girlsinyogapants+rule34+dirtysmall+celebnsfw+AsianHotties+asstastic+60fpsporn+datgap+WtSSTaDaMiT+AmateurArchives+IndianBabes+assinthong+buttplug+nsfwCelebArchive+latinas+Exxxtras+KateeOwen+Anjelica_Ebbi+tight_shorts+celebsnaked+TheUnderbun+Ohlympics+leggingsgonewild+Sashagrey+tightsqueeze+CelebrityButts+SexyGirlsInBoots+nsfwcelebgifs+nsfwasmr+HighResASS+HungryButts+kpopfap+WoahPoon+twerking+MalenaMorgan+LatinasGW+GirlsInMessyRooms+AssOnTheGlass+asianbabes+StomachDownFeetUp+CarlottaChampagne+Maria_Ozawa+CarolSeleme+wacrover+girlsfinishingthejob", true);
});

// index
app.get('/', util.prepareLayout, routes.index);

app.get('/admin', auth.require, util.prepareLayout, routes.admin.front);
app.get('/admin/womp', auth.require, util.prepareLayout, routes.admin.womp);
app.post('/admin/womp/delete', auth.require, util.prepareLayout, routes.admin.wompdelete);
app.post('/admin/womp/add', auth.require, util.prepareLayout, routes.admin.wompadd);

// map of teamspeak usage by country
app.get('/map', util.prepareLayout, routes.map);

// church fund
app.get('/fund', util.prepareLayout, routes.fund);

// QPS
app.post('/qps_login', routes.qps);

// mail authentication HMAC
app.get('/mail', auth.build, util.prepareLayout, routes.mail);

// testimonials / quotes
app.get('/quotes', auth.build, util.prepareLayout, routes.quotes.show);
app.post('/quotes/delete', auth.require, util.prepareLayout, routes.quotes.delete);

// grants page
app.get('/grants/:type?/:page?', auth.build, util.prepareLayout, routes.grants.show);
app.post('/grants', auth.build, util.prepareLayout, routes.grants.submitgrant);
app.post('/grants/delete', auth.require, routes.grants.delete);
app.post('/grants/approve', auth.require, routes.grants.approve);
app.post('/grants/reject', auth.require, routes.grants.reject);

// club system
app.get('/clubs', util.prepareLayout, routes.clubs.list);
app.get('/club/:id', auth.build, util.prepareLayout, routes.clubs.view)
app.post('/club/:id/join', util.prepareLayout, auth.require, routes.clubs.join)
app.post('/club/:id/edit', util.prepareLayout, auth.require, routes.clubs.edit)
app.get('/club/:id/discussion', util.prepareLayout, auth.require, routes.clubs.discussion)
app.post('/club/:id/ban', util.prepareLayout, auth.require, routes.clubs.ban)

// blog system
app.post('/blog/:id/submitpost', auth.require, routes.blog.submitpost);
app.post('/blog/:id/setimage', auth.require, routes.blog.setimage);
app.get('/blog/:id/newpost', util.prepareLayout, auth.require, routes.blog.newpost);
app.get('/blog/:id/:page?', util.prepareLayout, auth.build, routes.blog.show);
app.get('/post/:id', util.prepareLayout, auth.build, routes.blogpost.show);
app.post('/post/:id/edit', auth.require, routes.blogpost.editpost);
app.post('/post/:id/delete', auth.require, routes.blogpost.deletepost);
app.get('/blogs', util.prepareLayout, routes.blog.list);

// comments system
app.post('/comment/:id/edit', auth.require, routes.comments.edit);
app.post('/comment/submit', auth.require, routes.comments.submit);
app.post('/comment/:id/delete', auth.require, routes.comments.delete);

// gallery system
app.get(/^\/gallery(\/([0-9]+)?)?$/, auth.build, util.prepareLayout, routes.gallery.show);
app.get('/viewimage/:id', auth.build, util.prepareLayout, routes.gallery.viewimage);
app.post('/gallery/upload', auth.require, util.prepareLayout, routes.gallery.upload);
app.post('/gallery/delete', auth.require, util.prepareLayout, routes.gallery.delete);

// inbox system
app.get('/inbox/:type', util.prepareLayout, auth.require, routes.notifications.inbox);

// user centric stuff
app.get('/register', util.prepareLayout, routes.user.register);
app.post('/register', util.prepareLayout, auth.build, routes.user.register_submit);
app.get('/logout', util.prepareLayout, routes.user.logout);
app.get('/login', util.prepareLayout, routes.user.login);
app.post('/login', util.prepareLayout, routes.user.login_submit)
app.get('/verify/:code', util.prepareLayout, routes.user.verify)
app.get('/verify', auth.require, util.prepareLayout, routes.user.verify_form)
app.post('/verify', auth.require, util.prepareLayout, routes.user.submit_verify_form)
app.get('/forgotpassword', util.prepareLayout, routes.user.forgot);
app.post('/forgotpassword', util.prepareLayout, routes.user.forgot_submit);
app.get('/reset/:code', util.prepareLayout, routes.user.reset);
app.post('/reset/:code', util.prepareLayout, routes.user.reset_submit);

app.get('/panel', util.prepareLayout, auth.require, routes.user.panel);
app.post('/panel/setavatar', auth.require, routes.user.setavatar);
app.post('/panel/changeemail', auth.require, routes.user.changeemail);
app.post('/panel/changepass', auth.require, routes.user.changepass);

app.get('/link-teamspeak', auth.require, util.prepareLayout, routes.user.link_teamspeak);
app.post('/link-teamspeak', auth.require, util.prepareLayout, routes.user.submit_link_teamspeak);

app.get(/\.(gif|jpg|jpeg|png|css|js)$/, function(req, res) {
	res.statusCode = 404;
	res.send("404 Not Found");
})

app.get("*", util.prepareLayout, function(req, res) {
	res.statusCode = 404;
	res.render("404", {title:"404"});
})

// TODO: refactor so that much of this logic is in separate components
http.createServer(app).listen(HTTP_PORT, "localhost", function(){
  console.log('Express server listening on port ' + HTTP_PORT + '...');

  var io = require('socket.io').listen(http.createServer().listen(WS_PORT, 'localhost'))

  var users = [];

  io.sockets.on('connection', function(socket) {
  	var ip = socket.request.headers['x-real-ip'];
  	var active = true;

  	console.log("WebSocket connection from IP " + ip)

  	var $COOKIE = (socket.handshake.headers.cookie || '').split(/;\s*/).reduce(function(re, c) {
	  var tmp = c.match(/([^=]+)=(.*)/);
	  if (tmp) re[tmp[1]] = unescape(tmp[2]);
	  return re;
	}, {});

	auth.verify(String($COOKIE.email), String($COOKIE.pass), function(err, userdata) {
		if (err) return; // TODO: ?

		if (!userdata) return; // TODO: ?

		function f(repeat) {
			if (!active) return;

			routes.notifications.getNum(userdata.id, function(err, result) {
				if (err) return; // TODO: ?

				db.query("SELECT u.teamspeak_uid,t.uid FROM teamspeak_users t LEFT JOIN users u on 1 WHERE t.ip=? AND u.id=?", [ip, userdata.id], function(err, _results) {
					if (err) return; // TODO: ?

					if (_results.length > 0) {
						match = _results[0];

						if (match.uid != match.teamspeak_uid) {
							result.push({type:"link_teamspeak"});
						}
					}

					socket.emit('newNotifications', result)
				})
			})

			if (repeat)
				setTimeout(function() {f(repeat);}, 10000);
		};
		f(true);

		socket.on('fetch', function() {
			f(false);
		})
	})

  	socket.on('disconnect', function() {
  		active = false;
  	})
  })

  // bitcoin fund manager
  fundmanager(io);
});
<commit_msg>Removed rule34 from health.<commit_after>var express = require('express')
  , http = require('http')
  , path = require('path')
  , routes = require('./routes')
  , db = require('./db')
  , auth = require('./auth')
  , util = require('./util')
  , async = require('async')
  , fundmanager = require('./fundmanager')
  , fs = require('fs')
  , resize = require('./resize')

var app = express();

var HTTP_PORT = 8080; // main webserver
var WS_PORT = 8081; // websockets for notifications

app.configure(function(){
	// all environments
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');

	app.disable('x-powered-by');
	app.use(express.cookieParser());
	app.use(express.logger('dev'));
	app.use(express.bodyParser({
		uploadDir: './tmp'
	}));
	app.use(function(req, res, next) {
		var discardOriginalFile = function() {
			if (!req.files) return;

			for (name in req.files) {
				fs.unlinkSync(req.files[name].path);
			}
		}

		if (req.url.match(/^\/uploadimage/)) {
			if (!req.files.file) {
				discardOriginalFile();
				res.statusCode = 500;
				res.send("500 Internal Server Error: No file submitted.");
				return;
			}

			var path = "/" + req.files.file.path;
			var newname = util.token();

			async.parallel({
				orig: function(cb) {
					resize(path, "/public/uploads/" + newname + "_orig", false, false, cb)
				},
				thumb32: function(cb) {
					resize(path, "/public/uploads/" + newname + "_32", 32, 32, cb)
				},
				thumb55: function(cb) {
					resize(path, "/public/uploads/" + newname + "_55", 55, 55, cb)
				},
				thumb64: function(cb) {
					resize(path, "/public/uploads/" + newname + "_64", 64, 64, cb)
				},
				thumb140: function(cb) {
					resize(path, "/public/uploads/" + newname + "_140", 140, 140, cb)
				}
			}, function(err, results) {
				if (err) {
					console.log(err);
					discardOriginalFile();
					res.statusCode = 500;
					res.send("500 Internal Server Error: Invalid file format.");
					return;
				}

				for (name in results) {
					results[name] = results[name].replace("/public", "")
				}

				db.query("INSERT INTO imageuploads (orig, thumb32, thumb55, thumb64, thumb140, ip) values (?, ?, ?, ?, ?, ?)",
					[results.orig, results.thumb32, results.thumb55, results.thumb64, results.thumb140, util.ip(req)],
					function(err, r) {
						if (err) {
							discardOriginalFile();
							res.statusCode = 500;
							res.send("500 Internal Server Error: Couldn't save attachment.");
							return;
						}

						results.id = r.insertId;

						discardOriginalFile();
						res.send(JSON.stringify(results));
					}
				);
			})
		} else {
			discardOriginalFile();
			next();
		}
	})
	app.use(express.methodOverride());
	app.use(function(req, res, next) {
		var method = req.method;

		if (method == "POST" && req.path != "/qps_login") {
			if ((!util.isValidToken(req.body.csrf)) || (req.body.csrf != req.cookies.csrf)) {
				res.statusCode = 403;
				res.send("403 Forbidden: CSRF validation failure.");
			} else {
				next();
			}
		} else {
			next();
		}
	})
	app.use(function(req, res, next) {
		if (!util.isValidToken(req.cookies.csrf)) {
			res.cookie('csrf', util.token(), {maxAge: 94636000000, httpOnly:false})
		}
		next();
	})
	app.use(util.verifyRecaptcha);
	app.use(function(req, res, next) {
		res.locals._nl2br_escape = util.nl2br_escape;
		res.locals._quote = util.quote;
		res.locals._isset = util.isset;
		res.locals._timeSince = util.timeSince;
		res.locals._timeUntil = util.timeUntil;
		res.locals._attachment = util.attachment;
		res.locals._slug = util.slug;
		res.locals._repeat = util.repeat;

		if (req.url.substring(0, 6) == '/ajax/') {
			req.url = req.url.substring(5);
			res.locals.__REQUEST_TYPE = 'ajax';
			res.locals.__REQUEST_URL = req.url;
		} else {
			res.locals.__REQUEST_TYPE = 'normal';
			res.locals.__REQUEST_URL = req.url;
		}

		next();
	});

	app.use(express.static(path.join(__dirname, 'public'), {
		maxAge: 86400000
	}));
	app.use(app.router);

	app.use(function(err, req, res, next) {
		if (!err) next();

		console.log(err);
		res.statusCode = 500;
		res.send("<script>notifybox(\"We're sorry, there was an error with your request. :(\");</script>");
	});
});

/// ROUTEWARE:
// auth.require - require authentication
// auth.build - build authentication
// util.prepareLayout - prepare layout (navbar, footer) if non-ajax request // todo consider placing this on everything
//////////////////////////////////////////////////////////////////////////////////////

app.get('/health', util.prepareLayout, function(req, res) {
	util.redirect(req, res, "http://www.reddit.com/r/gonewild+nsfw+RealGirls+ass+BustyPetite+girlsinyogapants+dirtysmall+celebnsfw+AsianHotties+asstastic+60fpsporn+datgap+WtSSTaDaMiT+AmateurArchives+IndianBabes+assinthong+buttplug+nsfwCelebArchive+latinas+Exxxtras+KateeOwen+Anjelica_Ebbi+tight_shorts+celebsnaked+TheUnderbun+Ohlympics+leggingsgonewild+Sashagrey+tightsqueeze+CelebrityButts+SexyGirlsInBoots+nsfwcelebgifs+nsfwasmr+HighResASS+HungryButts+kpopfap+WoahPoon+twerking+MalenaMorgan+LatinasGW+GirlsInMessyRooms+AssOnTheGlass+asianbabes+StomachDownFeetUp+CarlottaChampagne+Maria_Ozawa+CarolSeleme+wacrover+girlsfinishingthejob", true);
});

// index
app.get('/', util.prepareLayout, routes.index);

app.get('/admin', auth.require, util.prepareLayout, routes.admin.front);
app.get('/admin/womp', auth.require, util.prepareLayout, routes.admin.womp);
app.post('/admin/womp/delete', auth.require, util.prepareLayout, routes.admin.wompdelete);
app.post('/admin/womp/add', auth.require, util.prepareLayout, routes.admin.wompadd);

// map of teamspeak usage by country
app.get('/map', util.prepareLayout, routes.map);

// church fund
app.get('/fund', util.prepareLayout, routes.fund);

// QPS
app.post('/qps_login', routes.qps);

// mail authentication HMAC
app.get('/mail', auth.build, util.prepareLayout, routes.mail);

// testimonials / quotes
app.get('/quotes', auth.build, util.prepareLayout, routes.quotes.show);
app.post('/quotes/delete', auth.require, util.prepareLayout, routes.quotes.delete);

// grants page
app.get('/grants/:type?/:page?', auth.build, util.prepareLayout, routes.grants.show);
app.post('/grants', auth.build, util.prepareLayout, routes.grants.submitgrant);
app.post('/grants/delete', auth.require, routes.grants.delete);
app.post('/grants/approve', auth.require, routes.grants.approve);
app.post('/grants/reject', auth.require, routes.grants.reject);

// club system
app.get('/clubs', util.prepareLayout, routes.clubs.list);
app.get('/club/:id', auth.build, util.prepareLayout, routes.clubs.view)
app.post('/club/:id/join', util.prepareLayout, auth.require, routes.clubs.join)
app.post('/club/:id/edit', util.prepareLayout, auth.require, routes.clubs.edit)
app.get('/club/:id/discussion', util.prepareLayout, auth.require, routes.clubs.discussion)
app.post('/club/:id/ban', util.prepareLayout, auth.require, routes.clubs.ban)

// blog system
app.post('/blog/:id/submitpost', auth.require, routes.blog.submitpost);
app.post('/blog/:id/setimage', auth.require, routes.blog.setimage);
app.get('/blog/:id/newpost', util.prepareLayout, auth.require, routes.blog.newpost);
app.get('/blog/:id/:page?', util.prepareLayout, auth.build, routes.blog.show);
app.get('/post/:id', util.prepareLayout, auth.build, routes.blogpost.show);
app.post('/post/:id/edit', auth.require, routes.blogpost.editpost);
app.post('/post/:id/delete', auth.require, routes.blogpost.deletepost);
app.get('/blogs', util.prepareLayout, routes.blog.list);

// comments system
app.post('/comment/:id/edit', auth.require, routes.comments.edit);
app.post('/comment/submit', auth.require, routes.comments.submit);
app.post('/comment/:id/delete', auth.require, routes.comments.delete);

// gallery system
app.get(/^\/gallery(\/([0-9]+)?)?$/, auth.build, util.prepareLayout, routes.gallery.show);
app.get('/viewimage/:id', auth.build, util.prepareLayout, routes.gallery.viewimage);
app.post('/gallery/upload', auth.require, util.prepareLayout, routes.gallery.upload);
app.post('/gallery/delete', auth.require, util.prepareLayout, routes.gallery.delete);

// inbox system
app.get('/inbox/:type', util.prepareLayout, auth.require, routes.notifications.inbox);

// user centric stuff
app.get('/register', util.prepareLayout, routes.user.register);
app.post('/register', util.prepareLayout, auth.build, routes.user.register_submit);
app.get('/logout', util.prepareLayout, routes.user.logout);
app.get('/login', util.prepareLayout, routes.user.login);
app.post('/login', util.prepareLayout, routes.user.login_submit)
app.get('/verify/:code', util.prepareLayout, routes.user.verify)
app.get('/verify', auth.require, util.prepareLayout, routes.user.verify_form)
app.post('/verify', auth.require, util.prepareLayout, routes.user.submit_verify_form)
app.get('/forgotpassword', util.prepareLayout, routes.user.forgot);
app.post('/forgotpassword', util.prepareLayout, routes.user.forgot_submit);
app.get('/reset/:code', util.prepareLayout, routes.user.reset);
app.post('/reset/:code', util.prepareLayout, routes.user.reset_submit);

app.get('/panel', util.prepareLayout, auth.require, routes.user.panel);
app.post('/panel/setavatar', auth.require, routes.user.setavatar);
app.post('/panel/changeemail', auth.require, routes.user.changeemail);
app.post('/panel/changepass', auth.require, routes.user.changepass);

app.get('/link-teamspeak', auth.require, util.prepareLayout, routes.user.link_teamspeak);
app.post('/link-teamspeak', auth.require, util.prepareLayout, routes.user.submit_link_teamspeak);

app.get(/\.(gif|jpg|jpeg|png|css|js)$/, function(req, res) {
	res.statusCode = 404;
	res.send("404 Not Found");
})

app.get("*", util.prepareLayout, function(req, res) {
	res.statusCode = 404;
	res.render("404", {title:"404"});
})

// TODO: refactor so that much of this logic is in separate components
http.createServer(app).listen(HTTP_PORT, "localhost", function(){
  console.log('Express server listening on port ' + HTTP_PORT + '...');

  var io = require('socket.io').listen(http.createServer().listen(WS_PORT, 'localhost'))

  var users = [];

  io.sockets.on('connection', function(socket) {
  	var ip = socket.request.headers['x-real-ip'];
  	var active = true;

  	console.log("WebSocket connection from IP " + ip)

  	var $COOKIE = (socket.handshake.headers.cookie || '').split(/;\s*/).reduce(function(re, c) {
	  var tmp = c.match(/([^=]+)=(.*)/);
	  if (tmp) re[tmp[1]] = unescape(tmp[2]);
	  return re;
	}, {});

	auth.verify(String($COOKIE.email), String($COOKIE.pass), function(err, userdata) {
		if (err) return; // TODO: ?

		if (!userdata) return; // TODO: ?

		function f(repeat) {
			if (!active) return;

			routes.notifications.getNum(userdata.id, function(err, result) {
				if (err) return; // TODO: ?

				db.query("SELECT u.teamspeak_uid,t.uid FROM teamspeak_users t LEFT JOIN users u on 1 WHERE t.ip=? AND u.id=?", [ip, userdata.id], function(err, _results) {
					if (err) return; // TODO: ?

					if (_results.length > 0) {
						match = _results[0];

						if (match.uid != match.teamspeak_uid) {
							result.push({type:"link_teamspeak"});
						}
					}

					socket.emit('newNotifications', result)
				})
			})

			if (repeat)
				setTimeout(function() {f(repeat);}, 10000);
		};
		f(true);

		socket.on('fetch', function() {
			f(false);
		})
	})

  	socket.on('disconnect', function() {
  		active = false;
  	})
  })

  // bitcoin fund manager
  fundmanager(io);
});
<|endoftext|>


<commit_before>// Copyright 2016, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the 'License');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

process.env.DEBUG = 'actions-on-google:*';
let Assistant = require('actions-on-google').ApiAiAssistant;
let express = require('express');
let bodyParser = require('body-parser');

let app = express();
app.use(bodyParser.json({type: 'application/json'}));

// [START YourAction]
app.post('/', function (req, res) {
  const assistant = new Assistant({request: req, response: res});
  console.log('Request headers: ' + JSON.stringify(req.headers));
  console.log('Request body: ' + JSON.stringify(req.body));

  // Fulfill action business logic
  function responseHandler (assistant) {
    // Complete your fulfillment logic and send a response
    assistant.tell('Hello, World1!');
    getJsonEventsFromWikipedia(setpoint, temp, function (events) {
        var speechText = "";
        sessionAttributes.text = events;
        session.attributes = sessionAttributes;
        if (events.length == 0) {
         //   speechText = "There is a problem connecting to Aprilaire at this time. Please try again later.";
         //   response.tell(speechText);
        } else {

                speechText = speechText+ " "+ events + " ";

          //  speechText = speechText + " Wanna go deeper in history?";
            response.askWithCard(prefixContent + speechText, repromptText, cardTitle, speechText);
        }
    });
  }
function getJsonEventsFromWikipedia(setpoint, temp, eventCallback) {

 var jsonobj=JSON.stringify({"LocationId":5919,"Parameters":[{"ParameterName":"Hold Type","ParameterValue":"1"},{"ParameterName":"Hold Fan","ParameterValue":"2"},{"ParameterName":"Hold Heat Setpoint","ParameterValue":temp.value},{"ParameterName":"Hold Cool Setpoint","ParameterValue":"87"},{"ParameterName":"Hold End Minute","ParameterValue":"0"},{"ParameterName":"Hold End Hour","ParameterValue":"6"},{"ParameterName":"Hold End Date","ParameterValue":"29"},{"ParameterName":"Hold End Month","ParameterValue":"8"},{"ParameterName":"Hold End Year","ParameterValue":"16"},{"ParameterName":"Hold Dehumidification Setpoint","ParameterValue":"0"}],"ThermostatId":75503,"UserId":4,"AttributeName":"Hold"});
//var jsonobj=JSON.stringify({"LocationId":5919,"Parameters":[{"ParameterName":"Hold Type","ParameterValue":"1"},{"ParameterName":"Hold Fan","ParameterValue":"2"},{"ParameterName":"Hold Heat Setpoint","ParameterValue":"84"},{"ParameterName":"Hold Cool Setpoint","ParameterValue":"87"},{"ParameterName":"Hold End Minute","ParameterValue":"0"},{"ParameterName":"Hold End Hour","ParameterValue":"6"},{"ParameterName":"Hold End Date","ParameterValue":"29"},{"ParameterName":"Hold End Month","ParameterValue":"8"},{"ParameterName":"Hold End Year","ParameterValue":"16"},{"ParameterName":"Hold Dehumidification Setpoint","ParameterValue":"0"}],"ThermostatId":75503,"UserId":4,"AttributeName":"Hold"});
var post_options = {
      host: 'web.lntdemoprojects.com',
      port: '443',
      path: '/raswcfservice/RASWCFService.svc/SetThermostatParameters/0',
      method: 'POST',
      headers: {
          'Content-Type': 'application/json',
          'Content-Length': jsonobj.length
      }
  };
var callback=function(res) {
        var body = '';
res.setEncoding('utf8');
        res.on('data', function (chunk) {
            body += chunk;
        });

        res.on('end', function () {
			if(body=="{\"Message\":\"Settings saved successfully!\",\"Result\":true}")
				{
            var stringResult = "temperature is changed.";
            eventCallback(stringResult);
				}
        });
    }

    https.request(post_options, callback).write(jsonobj);
}
  assistant.handleRequest(responseHandler);
});
// [END YourAction]

if (module === require.main) {
  // [START server]
  // Start the server
  let server = app.listen(process.env.PORT || 8080, function () {
    let port = server.address().port;
    console.log('App listening on port %s', port);
  });
  // [END server]
}

module.exports = app;
<commit_msg>change<commit_after>// Copyright 2016, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the 'License');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

process.env.DEBUG = 'actions-on-google:*';
let Assistant = require('actions-on-google').ApiAiAssistant;
let express = require('express');
let bodyParser = require('body-parser');

let app = express();
app.use(bodyParser.json({type: 'application/json'}));

// [START YourAction]
app.post('/', function (req, res) {
  const assistant = new Assistant({request: req, response: res});
  console.log('Request headers: ' + JSON.stringify(req.headers));
  console.log('Request body: ' + JSON.stringify(req.body));

  // Fulfill action business logic
  function responseHandler (assistant) {
    // Complete your fulfillment logic and send a response

   getJsonEvents( function (events) {
	   assistant.tell('Hello, World1!');
     var prefixContent =""

	   var speechText = "";
        if (events.length == 0) {
            speechText = "There is a problem connecting to thermostat at this time. Please try again later.";
             assistant.tell(speechText);
        } else {
            for (i = 0; i < 1; i++) {
                speechText = speechText + events[i] + " ";
            }
           // speechText = speechText + " Wanna go deeper in history?";
             assistant.tell(prefixContent + speechText);
        }
    });
  }
function getJsonEvents(eventCallback) {
   var url = 'https://web.lntdemoprojects.com/RASWCFService/RASWCFService.svc/GetThermostatHome/6402/5967/76632';
var https = require('https');
    https.get(url, function(res) {
        var body = '';

        res.on('data', function (chunk) {
            body += chunk;
        });

        res.on('end', function () {
            var stringResult = body;
            eventCallback(stringResult);
        });
    }).on('error', function (e) {
        console.log("Got error: ", e);
    });
}
  assistant.handleRequest(responseHandler);
});
// [END YourAction]

if (module === require.main) {
  // [START server]
  // Start the server
  let server = app.listen(process.env.PORT || 8080, function () {
    let port = server.address().port;
    console.log('App listening on port %s', port);
  });
  // [END server]
}

module.exports = app;
<|endoftext|>


<commit_before>"use strict";

const numbersRegex = /-?\d+/g;

exports.sumAllNumbers = (document) => {
  return new Counter(false).countValue(JSON.parse(document));
};

exports.sumAllNonRedNumbers = (document) => {
  return new Counter(true).countValue(JSON.parse(document));
};

var Counter = class Counter {
  constructor(skipRedNumbers) {
    this.skipRedNumbers = skipRedNumbers;
  }

  countValue(valueToCount) {
    if (Array.isArray(valueToCount)) {
      return this.countNumbersInArray(valueToCount);
    } else if (typeof valueToCount === "object") {
      return this.countNumbersInObject(valueToCount);
    } else if (typeof valueToCount === "number") {
      return valueToCount;
    } else {
      return 0;
    }
  }

  countNumbersInObject(obj) {
    let sum = 0;
    for (let key in obj) {
      let value = obj[key];

      if (this.skipRedNumbers && value === "red") {
        return 0;
      }
      sum += this.countValue(value);
    }
    return sum;
  }

  countNumbersInArray(arr) {
    let sum = 0;
    for (let item of arr) {
      sum += this.countValue(item);
    }
    return sum;
  }
};
<commit_msg>removed unused regex in day12.<commit_after>"use strict";

exports.sumAllNumbers = (document) => {
  return new Counter(false).countValue(JSON.parse(document));
};

exports.sumAllNonRedNumbers = (document) => {
  return new Counter(true).countValue(JSON.parse(document));
};

var Counter = class Counter {
  constructor(skipRedNumbers) {
    this.skipRedNumbers = skipRedNumbers;
  }

  countValue(valueToCount) {
    if (Array.isArray(valueToCount)) {
      return this.countNumbersInArray(valueToCount);
    } else if (typeof valueToCount === "object") {
      return this.countNumbersInObject(valueToCount);
    } else if (typeof valueToCount === "number") {
      return valueToCount;
    } else {
      return 0;
    }
  }

  countNumbersInObject(obj) {
    let sum = 0;
    for (let key in obj) {
      let value = obj[key];

      if (this.skipRedNumbers && value === "red") {
        return 0;
      }
      sum += this.countValue(value);
    }
    return sum;
  }

  countNumbersInArray(arr) {
    let sum = 0;
    for (let item of arr) {
      sum += this.countValue(item);
    }
    return sum;
  }
};
<|endoftext|>


<commit_before>// https://codingrange.com/blog/steam-in-home-streaming-discovery-protocol

var protobuf = require("protocol-buffers"),
    dgram = require("dgram"),
    fs = require("fs");

var messageTypes = protobuf(fs.readFileSync("steamdiscover.proto"));

var server = dgram.createSocket("udp4");

server.on("message", (m, rinfo) => {
try {
  var offset = 0;
  console.log(`got message: ${m} from ${rinfo.address}:${rinfo.port}`);
  console.log(m.slice(0,8).toString('hex'));
  offset += 8;

  var headerLength = m.readUInt32LE(offset);
  offset += 4; // 32 bit

  console.log(`header length: ${headerLength}`);

  var header = m.slice(offset, headerLength);
  console.log(header.toString('hex'));
  var headerContent =  messageTypes.CMsgRemoteClientBroadcastHeader.decode(header);
  console.log(headerContent);

  offset += headerLength;

  var bodyLength = m.readUInt32LE(offset);
  offset += 4; // 32 bit

  } catch (e) { console.log("Error: " + e + "\n\n");}
});

server.bind(27036);

//messagesTypes["CMsgRemoteClientBroadcastStatus"].decode("");

<commit_msg>Parses broadcast packets correctly, yay<commit_after>// https://codingrange.com/blog/steam-in-home-streaming-discovery-protocol
// https://www.npmjs.com/package/protocol-buffers
// https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/steamclient/steammessages_remoteclient_discovery.proto

var protobuf = require("protocol-buffers"),
    dgram = require("dgram"),
    fs = require("fs");

var messageTypes = protobuf(fs.readFileSync("steamdiscover.proto"));

var server = dgram.createSocket("udp4");

server.on("message", (m, rinfo) => {
//try {
  var offset = 0;
  console.log(`got message: ${m} from ${rinfo.address}:${rinfo.port}`);
  console.log(m.slice(0,8).toString('hex'));
  offset += 8;

  var headerLength = m.readUInt32LE(offset);
  offset += 4; // 32 bit

  console.log(`header length: ${headerLength}`);

  var header = m.slice(offset, offset + headerLength);
  console.log(header.toString('hex'));
  var headerContent =  messageTypes.CMsgRemoteClientBroadcastHeader.decode(header);
  console.log(headerContent);

  offset += headerLength;

  var bodyLength = m.readUInt32LE(offset);
  offset += 4; // 32 bit

  if (headerContent.msg_type == 1 ) {   /* k)ERemoteClientBroadcastMsgStatus */
    var body_data = m.slice(offset, offset + bodyLength);

    var body_content = messageTypes.CMsgRemoteClientBroadcastStatus.decode(body_data);
    console.log(body_content);

  }
//  } catch (e) { console.log("Error: " + e + "\n\n");}
});

server.bind(27036);

//messagesTypes["CMsgRemoteClientBroadcastStatus"].decode("");

function broadcastDiscovery(server) {

}

<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  // imports

  var log = window.logFlags || {};
  var api = scope.api.instance.styles;
  var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;

  // magic words

  var STYLE_SELECTOR = 'style';
  var SHEET_SELECTOR = 'link[rel=stylesheet]';
  var STYLE_GLOBAL_SCOPE = 'global';
  var SCOPE_ATTR = 'polymer-scope';
  var STYLE_LOADABLE_MATCH = '@import';

  var styles = {
    // returns true if resources are loading
    preloadStyles: function(callback) {
      var styles = [];
      var t$ = this.querySelectorAll('template');
      for (var i=0, l=t$.length, t; (i<l) && (t=t$[i]); i++) {
        this.convertSheetsToStyles(t.content);
        styles = styles.concat(this.findLoadableStyles(t.content));
      }
      if (styles.length) {
        if (window.ShadowDOMPolyfill) {
          Platform.ShadowCSS.loadStyles(styles, callback);
        } else {
          var css = [];
          for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
            css.push(s.textContent);
          }
          preloadCssText(css.join('\n'), callback);
        }
        return true;
      }
    },
    convertSheetsToStyles: function(root) {
      var s$ = root.querySelectorAll(SHEET_SELECTOR);
      for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {
        c = createStyleElement(importRuleForSheet(s));
        var scope = s.getAttribute(SCOPE_ATTR);
        if (scope) {
          c.setAttribute(SCOPE_ATTR, scope);
        }
        s.parentNode.replaceChild(c, s);
      }
    },
    findLoadableStyles: function(root) {
      var loadables = [];
      var s$ = root.querySelectorAll(STYLE_SELECTOR);
      for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {
        if (s.textContent.match(STYLE_LOADABLE_MATCH)) {
          loadables.push(s);
        }
      }
      return loadables;
    },
    /**
     * Install external stylesheets loaded in <polymer-element> elements into the
     * element's template.
     * @param elementElement The <element> element to style.
     */
    // TODO(sorvell): wip... caching and styles handling can probably be removed
    // We need a scheme to ensure stylesheets are eagerly loaded without
    // the creation of an element instance. Here are 2 options for handling this:
    // 1. create a dummy element with ShadowDOM in dom that includes ALL styles
    // processed here.
    // 2. place stylesheets outside the element template. This will allow
    // imports to naturally load the sheets. Then at load time, we can remove
    // the stylesheet from dom.
    installSheets: function() {
      this.cacheSheets();
      this.cacheStyles();
      this.installLocalSheets();
      //this.installGlobalStyles();
    },
    /**
     * Remove all sheets from element and store for later use.
     */
    cacheSheets: function() {
      this.sheets = this.findNodes(SHEET_SELECTOR);
      this.sheets.forEach(function(s) {
        if (s.parentNode) {
          s.parentNode.removeChild(s);
        }
      });
    },
    cacheStyles: function() {
      this.styles = this.findNodes(STYLE_SELECTOR + '[' + SCOPE_ATTR + ']');
      this.styles.forEach(function(s) {
        if (s.parentNode) {
          s.parentNode.removeChild(s);
        }
      });
    },
    /**
     * Takes external stylesheets loaded in an <element> element and moves
     * their content into a <style> element inside the <element>'s template.
     * The sheet is then removed from the <element>. This is done only so
     * that if the element is loaded in the main document, the sheet does
     * not become active.
     * Note, ignores sheets with the attribute 'polymer-scope'.
     * @param elementElement The <element> element to style.
     */
    installLocalSheets: function () {
      var sheets = this.sheets.filter(function(s) {
        return !s.hasAttribute(SCOPE_ATTR);
      });
      var content = this.templateContent();
      if (content) {
        var cssText = '';
        sheets.forEach(function(sheet) {
          cssText += cssTextFromSheet(sheet) + '\n';
        });
        if (cssText) {
          var style = createStyleElement(cssText, this.ownerDocument);
          content.insertBefore(style, content.firstChild);
        }
      }
    },
    findNodes: function(selector, matcher) {
      var nodes = this.querySelectorAll(selector).array();
      var content = this.templateContent();
      if (content) {
        var templateNodes = content.querySelectorAll(selector).array();
        nodes = nodes.concat(templateNodes);
      }
      return matcher ? nodes.filter(matcher) : nodes;
    },
    templateContent: function() {
      var template = this.querySelector('template');
      return template && templateContent(template);
    },
    /**
     * Promotes external stylesheets and <style> elements with the attribute
     * polymer-scope='global' into global scope.
     * This is particularly useful for defining @keyframe rules which
     * currently do not function in scoped or shadow style elements.
     * (See wkb.ug/72462)
     * @param elementElement The <element> element to style.
    */
    // TODO(sorvell): remove when wkb.ug/72462 is addressed.
    installGlobalStyles: function() {
      var style = this.styleForScope(STYLE_GLOBAL_SCOPE);
      applyStyleToScope(style, document.head);
    },
    cssTextForScope: function(scopeDescriptor) {
      var cssText = '';
      // handle stylesheets
      var selector = '[' + SCOPE_ATTR + '=' + scopeDescriptor + ']';
      var matcher = function(s) {
        return matchesSelector(s, selector);
      };
      var sheets = this.sheets.filter(matcher);
      sheets.forEach(function(sheet) {
        cssText += cssTextFromSheet(sheet) + '\n\n';
      });
      // handle cached style elements
      var styles = this.styles.filter(matcher);
      styles.forEach(function(style) {
        cssText += style.textContent + '\n\n';
      });
      return cssText;
    },
    styleForScope: function(scopeDescriptor) {
      var cssText = this.cssTextForScope(scopeDescriptor);
      return this.cssTextToScopeStyle(cssText, scopeDescriptor);
    },
    cssTextToScopeStyle: function(cssText, scopeDescriptor) {
      if (cssText) {
        var style = createStyleElement(cssText);
        style.setAttribute(STYLE_SCOPE_ATTRIBUTE, this.getAttribute('name') +
            '-' + scopeDescriptor);
        return style;
      }
    }
  };

  var preloader = document.createElement('preloader');
  preloader.style.display = 'none';
  var preloaderRoot = preloader.createShadowRoot();
  document.head.appendChild(preloader);

  function preloadCssText(cssText, callback) {
    var style = createStyleElement(cssText);
    if (callback) {
      style.addEventListener('load', callback);
    }
    preloaderRoot.appendChild(style);
  }

  function importRuleForSheet(sheet) {
    return '@import \'' + sheet.href + '\';';
  }

  function applyStyleToScope(style, scope) {
    if (style) {
      // TODO(sorvell): necessary for IE
      // see https://connect.microsoft.com/IE/feedback/details/790212/
      // cloning-a-style-element-and-adding-to-document-produces
      // -unexpected-result#details
      // var clone = style.cloneNode(true);
      var clone = createStyleElement(style.textContent);
      var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE);
      if (attr) {
        clone.setAttribute(STYLE_SCOPE_ATTRIBUTE, attr);
      }
      scope.appendChild(clone);
    }
  }

  function createStyleElement(cssText, scope) {
    scope = scope || document;
    scope = scope.createElement ? scope : scope.ownerDocument;
    var style = scope.createElement('style');
    style.textContent = cssText;
    return style;
  }

  function cssTextFromSheet(sheet) {
    return (sheet && sheet.__resource) || '';
  }

  function matchesSelector(node, inSelector) {
    if (matches) {
      return matches.call(node, inSelector);
    }
  }
  var p = HTMLElement.prototype;
  var matches = p.matches || p.matchesSelector || p.webkitMatchesSelector
      || p.mozMatchesSelector;

  // exports

  scope.api.declaration.styles = styles;
  scope.applyStyleToScope = applyStyleToScope;

})(Polymer);
<commit_msg>rely on platform to preload styles.<commit_after>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */
(function(scope) {

  // imports

  var log = window.logFlags || {};
  var api = scope.api.instance.styles;
  var STYLE_SCOPE_ATTRIBUTE = api.STYLE_SCOPE_ATTRIBUTE;

  // magic words

  var STYLE_SELECTOR = 'style';
  var SHEET_SELECTOR = 'link[rel=stylesheet]';
  var STYLE_GLOBAL_SCOPE = 'global';
  var SCOPE_ATTR = 'polymer-scope';

  var styles = {
    // returns true if resources are loading
    preloadStyles: function(callback) {
      var content = this.templateContent();
      if (content) {
        this.convertSheetsToStyles(content);
        return Platform.loader.loadStyles(content, callback);
      }
    },
    convertSheetsToStyles: function(root) {
      var s$ = root.querySelectorAll(SHEET_SELECTOR);
      for (var i=0, l=s$.length, s, c; (i<l) && (s=s$[i]); i++) {
        c = createStyleElement(importRuleForSheet(s));
        var scope = s.getAttribute(SCOPE_ATTR);
        if (scope) {
          c.setAttribute(SCOPE_ATTR, scope);
        }
        s.parentNode.replaceChild(c, s);
      }
    },
    /**
     * Install external stylesheets loaded in <polymer-element> elements into the
     * element's template.
     * @param elementElement The <element> element to style.
     */
    // TODO(sorvell): wip... caching and styles handling can probably be removed
    // We need a scheme to ensure stylesheets are eagerly loaded without
    // the creation of an element instance. Here are 2 options for handling this:
    // 1. create a dummy element with ShadowDOM in dom that includes ALL styles
    // processed here.
    // 2. place stylesheets outside the element template. This will allow
    // imports to naturally load the sheets. Then at load time, we can remove
    // the stylesheet from dom.
    installSheets: function() {
      this.cacheSheets();
      this.cacheStyles();
      this.installLocalSheets();
      this.installGlobalStyles();
    },
    /**
     * Remove all sheets from element and store for later use.
     */
    cacheSheets: function() {
      this.sheets = this.findNodes(SHEET_SELECTOR);
      this.sheets.forEach(function(s) {
        if (s.parentNode) {
          s.parentNode.removeChild(s);
        }
      });
    },
    cacheStyles: function() {
      this.styles = this.findNodes(STYLE_SELECTOR + '[' + SCOPE_ATTR + ']');
      this.styles.forEach(function(s) {
        if (s.parentNode) {
          s.parentNode.removeChild(s);
        }
      });
    },
    /**
     * Takes external stylesheets loaded in an <element> element and moves
     * their content into a <style> element inside the <element>'s template.
     * The sheet is then removed from the <element>. This is done only so
     * that if the element is loaded in the main document, the sheet does
     * not become active.
     * Note, ignores sheets with the attribute 'polymer-scope'.
     * @param elementElement The <element> element to style.
     */
    installLocalSheets: function () {
      var sheets = this.sheets.filter(function(s) {
        return !s.hasAttribute(SCOPE_ATTR);
      });
      var content = this.templateContent();
      if (content) {
        var cssText = '';
        sheets.forEach(function(sheet) {
          cssText += cssTextFromSheet(sheet) + '\n';
        });
        if (cssText) {
          var style = createStyleElement(cssText, this.ownerDocument);
          content.insertBefore(style, content.firstChild);
        }
      }
    },
    findNodes: function(selector, matcher) {
      var nodes = this.querySelectorAll(selector).array();
      var content = this.templateContent();
      if (content) {
        var templateNodes = content.querySelectorAll(selector).array();
        nodes = nodes.concat(templateNodes);
      }
      return matcher ? nodes.filter(matcher) : nodes;
    },
    templateContent: function() {
      var template = this.querySelector('template');
      return template && templateContent(template);
    },
    /**
     * Promotes external stylesheets and <style> elements with the attribute
     * polymer-scope='global' into global scope.
     * This is particularly useful for defining @keyframe rules which
     * currently do not function in scoped or shadow style elements.
     * (See wkb.ug/72462)
     * @param elementElement The <element> element to style.
    */
    // TODO(sorvell): remove when wkb.ug/72462 is addressed.
    installGlobalStyles: function() {
      var style = this.styleForScope(STYLE_GLOBAL_SCOPE);
      applyStyleToScope(style, document.head);
    },
    cssTextForScope: function(scopeDescriptor) {
      var cssText = '';
      // handle stylesheets
      var selector = '[' + SCOPE_ATTR + '=' + scopeDescriptor + ']';
      var matcher = function(s) {
        return matchesSelector(s, selector);
      };
      var sheets = this.sheets.filter(matcher);
      sheets.forEach(function(sheet) {
        cssText += cssTextFromSheet(sheet) + '\n\n';
      });
      // handle cached style elements
      var styles = this.styles.filter(matcher);
      styles.forEach(function(style) {
        cssText += style.textContent + '\n\n';
      });
      return cssText;
    },
    styleForScope: function(scopeDescriptor) {
      var cssText = this.cssTextForScope(scopeDescriptor);
      return this.cssTextToScopeStyle(cssText, scopeDescriptor);
    },
    cssTextToScopeStyle: function(cssText, scopeDescriptor) {
      if (cssText) {
        var style = createStyleElement(cssText);
        style.setAttribute(STYLE_SCOPE_ATTRIBUTE, this.getAttribute('name') +
            '-' + scopeDescriptor);
        return style;
      }
    }
  };

  function importRuleForSheet(sheet) {
    return '@import \'' + sheet.href + '\';';
  }

  function applyStyleToScope(style, scope) {
    if (style) {
      // TODO(sorvell): necessary for IE
      // see https://connect.microsoft.com/IE/feedback/details/790212/
      // cloning-a-style-element-and-adding-to-document-produces
      // -unexpected-result#details
      // var clone = style.cloneNode(true);
      var clone = createStyleElement(style.textContent);
      var attr = style.getAttribute(STYLE_SCOPE_ATTRIBUTE);
      if (attr) {
        clone.setAttribute(STYLE_SCOPE_ATTRIBUTE, attr);
      }
      scope.appendChild(clone);
    }
  }

  function createStyleElement(cssText, scope) {
    scope = scope || document;
    scope = scope.createElement ? scope : scope.ownerDocument;
    var style = scope.createElement('style');
    style.textContent = cssText;
    return style;
  }

  function cssTextFromSheet(sheet) {
    return (sheet && sheet.__resource) || '';
  }

  function matchesSelector(node, inSelector) {
    if (matches) {
      return matches.call(node, inSelector);
    }
  }
  var p = HTMLElement.prototype;
  var matches = p.matches || p.matchesSelector || p.webkitMatchesSelector
      || p.mozMatchesSelector;

  // exports

  scope.api.declaration.styles = styles;
  scope.applyStyleToScope = applyStyleToScope;

})(Polymer);
<|endoftext|>


<commit_before>require('sugar');

fs = require('fs');
path = require('path');

request = require('request');

// Synchronously copy config-example.js over to config.js if it doesn't exist
if (!path.existsSync('./config/config.js')) {
	console.log("config.js doesn't exist - creating one with default settings...");
	var BUF_LENGTH, buff, bytesRead, fdr, fdw, pos;
	BUF_LENGTH = 64 * 1024;
	buff = new Buffer(BUF_LENGTH);
	fdr = fs.openSync('./config/config-example.js', 'r');
	fdw = fs.openSync('./config/config.js', 'w');
	bytesRead = 1;
	pos = 0;
	while (bytesRead > 0) {
		bytesRead = fs.readSync(fdr, buff, 0, BUF_LENGTH, pos);
		fs.writeSync(fdw, buff, 0, bytesRead);
		pos += bytesRead;
	}
	fs.closeSync(fdr);
}

config = require('./config/config.js');

/*
var app = require('http').createServer()
  , io = require('socket.io').listen(app)
  , fs = require('fs');

function handler (req, res) {
	fs.readFile(__dirname + '/index.html',
	function (err, data) {
		if (err) {
			res.writeHead(500);
			return res.end('Error loading index.html');
		}

		res.writeHead(200);
		res.end(data);
	});
}

app.listen(8000); */

if (process.argv[2] && parseInt(process.argv[2])) {
	config.port = parseInt(process.argv[2]);
}

if (config.protocol !== 'io') config.protocol = 'ws';

var app;
var server;
if (config.protocol === 'ws') {
	app = require('http').createServer();
	server = require('sockjs').createServer({sockjs_url: "http://cdn.sockjs.org/sockjs-0.3.min.js", log: function(severity, message) {
		if (severity === 'error') console.log('ERROR: '+message);
	}});
} else {
	server = require('socket.io').listen(config.port).set('log level', 1);
	server.set('transports', ['websocket', 'htmlfile', 'xhr-polling']); // temporary hack until https://github.com/LearnBoost/socket.io/issues/609 is fixed
}

/**
 * Converts anything to an ID. An ID must have only lowercase alphanumeric
 * characters.
 * If a string is passed, it will be converted to lowercase and
 * non-alphanumeric characters will be stripped.
 * If an object with an ID is passed, its ID will be returned.
 * Otherwise, an empty string will be returned.
 */
toId = function(text) {
	text = (''+(text||''));
	if (typeof text === 'number') text = ''+text;
	if (text && text.id) text = text.id;
	if (typeof text !== 'string') return ''; //???
	return text.toLowerCase().replace(/[^a-z0-9]+/g, '');
};
toUserid = toId;

/**
 * Escapes a string for HTML
 * If strEscape is true, escapes it for JavaScript, too
 */
sanitize = function(str, strEscape) {
	str = (''+(str||''));
	str = str.escapeHTML();
	if (strEscape) str = str.replace(/'/g, '\\\'');
	return str;
};

/**
 * Converts any variable to an integer (numbers get floored, non-numbers
 * become 0). Then clamps it between min and (optionally) max.
 */
clampIntRange = function(num, min, max) {
	if (typeof num !== 'number') num = 0;
	num = Math.floor(num);
	if (num < min) num = min;
	if (typeof max !== 'undefined' && num > max) num = max;
	return num;
};

Data = {};
Tools = require('./tools.js');

Users = require('./users.js');

Rooms = require('./rooms.js');

parseCommand = require('./chat-commands.js').parseCommand;

var sim = require('./simulator.js');
BattlePokemon = sim.BattlePokemon;
BattleSide = sim.BattleSide;
Battle = sim.Battle;

lockdown = false;

mutedIps = {};
bannedIps = {};
nameLockedIps = {};

function resolveUser(you, socket) {
	if (!you) {
		emit(socket, 'connectionError', 'There has been a connection error. Please refresh the page.');
		return false;
	}
	return you.user;
}

emit = function(socket, type, data) {
	if (config.protocol === 'io') {
		console.log('emitting '+type);
		socket.emit(type, data);
	} else {
		if (typeof data === 'object') data.type = type;
		else data = {type: type, message: data};
		socket.write(JSON.stringify(data));
	}
};

function randomString(length) {
	var strArr = [];
	var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
	for (var i=0;i<length;i++) {
		strArr[i] = chars[Math.floor(Math.random()*chars.length)];
	}
	return strArr.join('');
}

if (config.crashguard) {
	// graceful crash - allow current battles to finish before restarting
	process.on('uncaughtException', function (err) {
		console.log("\n"+err.stack+"\n");
		fs.createWriteStream('logs/errors.txt', {'flags': 'a'}).on("open", function(fd) {
			this.write("\n"+err.stack+"\n");
			this.end();
		});
		var stack = (""+err.stack).split("\n").slice(0,2).join("
");
		Rooms.lobby.addRaw('
THE SERVER HAS CRASHED: '+stack+'
Please restart the server.
');
		Rooms.lobby.addRaw('
You will not be able to talk in the lobby or start new battles until the server restarts.
');
		config.modchat = 'crash';
		lockdown = true;
	});
}

// event functions
var events = {
	join: function(data, socket, you) {
		if (!data || typeof data.room !== 'string' || typeof data.name !== 'string') return;
		if (!you) {
			you = Users.connectUser(data.name, socket, data.token, data.room);
			console.log('JOIN: '+data.name+' => '+you.name+' ['+data.token+']');
			return you;
		} else {
			var youUser = resolveUser(you, socket);
			if (!youUser) return;
			youUser.joinRoom(data.room, socket);
		}
	},
	rename: function(data, socket, you) {
		if (!data) return;
		data.name = ''+data.name;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.rename(data.name, data.token, data.auth);
	},
	chat: function(message, socket, you) {
		if (!message || typeof message.room !== 'string' || typeof message.message !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(message.room);
		youUser.chat(message.message, room, socket);
	},
	leave: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.leaveRoom(Rooms.get(data.room), socket);
	},
	leaveBattle: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		if (room.leaveBattle) room.leaveBattle(youUser);
	},
	joinBattle: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		if (room.joinBattle) room.joinBattle(youUser);
	},
	command: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		parseCommand(youUser, 'command', data, Rooms.get(data.room), socket);
	},
	disconnect: function(socket, you) {
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.disconnect(socket);
	},
	challenge: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		console.log('CHALLENGE: '+youUser.name+' => '+data.userid+' ('+data.act+')');
		switch (data.act) {
		case 'make':
			if (typeof data.format !== 'string') data.format = 'debugmode';
			if (typeof data.userid !== 'string') return;
			var problems = Tools.validateTeam(youUser.team, data.format);
			if (problems) {
				emit(socket, 'message', "Your team was rejected for the following reasons:\n\n- "+problems.join("\n- "));
				return;
			}
			if (!Users.get(data.userid) || !Users.get(data.userid).connected) {
				emit(socket, 'message', "The user '"+data.userid+"' was not found.");
			}
			youUser.makeChallenge(data.userid, data.format);
			break;
		case 'cancel':
			youUser.cancelChallengeTo(data.userid);
			break;
		case 'accept':
			if (typeof data.userid !== 'string') return;
			var format = 'debugmode';
			if (youUser.challengesFrom[data.userid]) format = youUser.challengesFrom[data.userid].format;
			var problems = Tools.validateTeam(youUser.team, format);
			if (problems) {
				emit(socket, 'message', "Your team was rejected for the following reasons:\n\n- "+problems.join("\n- "));
				return;
			}
			youUser.acceptChallengeFrom(data.userid);
			break;
		case 'reject':
			if (typeof data.userid !== 'string') return;
			youUser.rejectChallengeFrom(data.userid);
			break;
		}
	},
	decision: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		switch (data.choice) {
		case 'move':
		case 'switch':
		case 'undo':
		case 'team':
			if (room.decision) room.decision(youUser,data.choice,data.move);
			break;
		case 'search':
			if (data.search) {
				if (typeof data.format !== 'string') return;
				if (room.searchBattle) room.searchBattle(youUser, data.format);
			} else {
				if (room.cancelSearch) room.cancelSearch(youUser);
			}
			break;
		}
	},
	saveTeam: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.team = data.team;
		youUser.emit('update', {team: 'saved', room: 'teambuilder'});
	}
};

if (config.protocol === 'io') { // Socket.IO
	server.sockets.on('connection', function (socket) {
		var you = null;
		console.log('INIT SOCKET: '+socket.id);

		if (socket.handshake && socket.handshake.address && socket.handshake.address.address) {
			if (bannedIps[socket.handshake.address.address]) {
				console.log('IP BANNED: '+socket.handshake.address.address);
				return;
			}
			socket.remoteAddress = socket.handshake.address.address; // for compatibility with SockJS semantics
		}
		var generator = function(type) {
			return function(data) {
				console.log('received '+type);
				console.log(you);
				events[type](data, socket, you);
			};
		};
		for (var e in events) {
			socket.on(e, (function(type) {
				return function(data) {
					console.log('received '+type);
					you = events[type](data, socket, you) || you;
				};
			})(e));
		}
	});
} else { // SockJS
	server.on('connection', function (socket) {
		var you = null;
		socket.id = randomString(16); // this sucks
		console.log('INIT SOCKET: '+socket.id);

		if (bannedIps[socket.remoteAddress]) {
			console.log('IP BANNED: '+socket.remoteAddress);
			return;
		}
		socket.on('data', function(message) {
			var data = JSON.parse(message);
			if (!data) return;
			if (events[data.type]) you = events[data.type](data, socket, you) || you;
		});
		socket.on('close', function() {
			youUser = resolveUser(you, socket);
			if (!youUser) return;
			youUser.disconnect(socket);
		});
	});
	server.installHandlers(app, {});
	app.listen(config.port);
}

console.log("Server started on port "+config.port);
console.log("Test your server at http://psim.tk/~~localhost:"+config.port);
<commit_msg>Guard against the mysterious and seemingly impossible situation where someone successfully connects with a null socket.<commit_after>require('sugar');

fs = require('fs');
path = require('path');

request = require('request');

// Synchronously copy config-example.js over to config.js if it doesn't exist
if (!path.existsSync('./config/config.js')) {
	console.log("config.js doesn't exist - creating one with default settings...");
	var BUF_LENGTH, buff, bytesRead, fdr, fdw, pos;
	BUF_LENGTH = 64 * 1024;
	buff = new Buffer(BUF_LENGTH);
	fdr = fs.openSync('./config/config-example.js', 'r');
	fdw = fs.openSync('./config/config.js', 'w');
	bytesRead = 1;
	pos = 0;
	while (bytesRead > 0) {
		bytesRead = fs.readSync(fdr, buff, 0, BUF_LENGTH, pos);
		fs.writeSync(fdw, buff, 0, bytesRead);
		pos += bytesRead;
	}
	fs.closeSync(fdr);
}

config = require('./config/config.js');

/*
var app = require('http').createServer()
  , io = require('socket.io').listen(app)
  , fs = require('fs');

function handler (req, res) {
	fs.readFile(__dirname + '/index.html',
	function (err, data) {
		if (err) {
			res.writeHead(500);
			return res.end('Error loading index.html');
		}

		res.writeHead(200);
		res.end(data);
	});
}

app.listen(8000); */

if (process.argv[2] && parseInt(process.argv[2])) {
	config.port = parseInt(process.argv[2]);
}

if (config.protocol !== 'io') config.protocol = 'ws';

var app;
var server;
if (config.protocol === 'ws') {
	app = require('http').createServer();
	server = require('sockjs').createServer({sockjs_url: "http://cdn.sockjs.org/sockjs-0.3.min.js", log: function(severity, message) {
		if (severity === 'error') console.log('ERROR: '+message);
	}});
} else {
	server = require('socket.io').listen(config.port).set('log level', 1);
	server.set('transports', ['websocket', 'htmlfile', 'xhr-polling']); // temporary hack until https://github.com/LearnBoost/socket.io/issues/609 is fixed
}

/**
 * Converts anything to an ID. An ID must have only lowercase alphanumeric
 * characters.
 * If a string is passed, it will be converted to lowercase and
 * non-alphanumeric characters will be stripped.
 * If an object with an ID is passed, its ID will be returned.
 * Otherwise, an empty string will be returned.
 */
toId = function(text) {
	text = (''+(text||''));
	if (typeof text === 'number') text = ''+text;
	if (text && text.id) text = text.id;
	if (typeof text !== 'string') return ''; //???
	return text.toLowerCase().replace(/[^a-z0-9]+/g, '');
};
toUserid = toId;

/**
 * Escapes a string for HTML
 * If strEscape is true, escapes it for JavaScript, too
 */
sanitize = function(str, strEscape) {
	str = (''+(str||''));
	str = str.escapeHTML();
	if (strEscape) str = str.replace(/'/g, '\\\'');
	return str;
};

/**
 * Converts any variable to an integer (numbers get floored, non-numbers
 * become 0). Then clamps it between min and (optionally) max.
 */
clampIntRange = function(num, min, max) {
	if (typeof num !== 'number') num = 0;
	num = Math.floor(num);
	if (num < min) num = min;
	if (typeof max !== 'undefined' && num > max) num = max;
	return num;
};

Data = {};
Tools = require('./tools.js');

Users = require('./users.js');

Rooms = require('./rooms.js');

parseCommand = require('./chat-commands.js').parseCommand;

var sim = require('./simulator.js');
BattlePokemon = sim.BattlePokemon;
BattleSide = sim.BattleSide;
Battle = sim.Battle;

lockdown = false;

mutedIps = {};
bannedIps = {};
nameLockedIps = {};

function resolveUser(you, socket) {
	if (!you) {
		emit(socket, 'connectionError', 'There has been a connection error. Please refresh the page.');
		return false;
	}
	return you.user;
}

emit = function(socket, type, data) {
	if (config.protocol === 'io') {
		console.log('emitting '+type);
		socket.emit(type, data);
	} else {
		if (typeof data === 'object') data.type = type;
		else data = {type: type, message: data};
		socket.write(JSON.stringify(data));
	}
};

function randomString(length) {
	var strArr = [];
	var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
	for (var i=0;i<length;i++) {
		strArr[i] = chars[Math.floor(Math.random()*chars.length)];
	}
	return strArr.join('');
}

if (config.crashguard) {
	// graceful crash - allow current battles to finish before restarting
	process.on('uncaughtException', function (err) {
		console.log("\n"+err.stack+"\n");
		fs.createWriteStream('logs/errors.txt', {'flags': 'a'}).on("open", function(fd) {
			this.write("\n"+err.stack+"\n");
			this.end();
		});
		var stack = (""+err.stack).split("\n").slice(0,2).join("
");
		Rooms.lobby.addRaw('
THE SERVER HAS CRASHED: '+stack+'
Please restart the server.
');
		Rooms.lobby.addRaw('
You will not be able to talk in the lobby or start new battles until the server restarts.
');
		config.modchat = 'crash';
		lockdown = true;
	});
}

// event functions
var events = {
	join: function(data, socket, you) {
		if (!data || typeof data.room !== 'string' || typeof data.name !== 'string') return;
		if (!you) {
			you = Users.connectUser(data.name, socket, data.token, data.room);
			console.log('JOIN: '+data.name+' => '+you.name+' ['+data.token+']');
			return you;
		} else {
			var youUser = resolveUser(you, socket);
			if (!youUser) return;
			youUser.joinRoom(data.room, socket);
		}
	},
	rename: function(data, socket, you) {
		if (!data) return;
		data.name = ''+data.name;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.rename(data.name, data.token, data.auth);
	},
	chat: function(message, socket, you) {
		if (!message || typeof message.room !== 'string' || typeof message.message !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(message.room);
		youUser.chat(message.message, room, socket);
	},
	leave: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.leaveRoom(Rooms.get(data.room), socket);
	},
	leaveBattle: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		if (room.leaveBattle) room.leaveBattle(youUser);
	},
	joinBattle: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		if (room.joinBattle) room.joinBattle(youUser);
	},
	command: function(data, socket, you) {
		if (!data || typeof data.room !== 'string') return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		parseCommand(youUser, 'command', data, Rooms.get(data.room), socket);
	},
	disconnect: function(socket, you) {
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.disconnect(socket);
	},
	challenge: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		console.log('CHALLENGE: '+youUser.name+' => '+data.userid+' ('+data.act+')');
		switch (data.act) {
		case 'make':
			if (typeof data.format !== 'string') data.format = 'debugmode';
			if (typeof data.userid !== 'string') return;
			var problems = Tools.validateTeam(youUser.team, data.format);
			if (problems) {
				emit(socket, 'message', "Your team was rejected for the following reasons:\n\n- "+problems.join("\n- "));
				return;
			}
			if (!Users.get(data.userid) || !Users.get(data.userid).connected) {
				emit(socket, 'message', "The user '"+data.userid+"' was not found.");
			}
			youUser.makeChallenge(data.userid, data.format);
			break;
		case 'cancel':
			youUser.cancelChallengeTo(data.userid);
			break;
		case 'accept':
			if (typeof data.userid !== 'string') return;
			var format = 'debugmode';
			if (youUser.challengesFrom[data.userid]) format = youUser.challengesFrom[data.userid].format;
			var problems = Tools.validateTeam(youUser.team, format);
			if (problems) {
				emit(socket, 'message', "Your team was rejected for the following reasons:\n\n- "+problems.join("\n- "));
				return;
			}
			youUser.acceptChallengeFrom(data.userid);
			break;
		case 'reject':
			if (typeof data.userid !== 'string') return;
			youUser.rejectChallengeFrom(data.userid);
			break;
		}
	},
	decision: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		var room = Rooms.get(data.room);
		switch (data.choice) {
		case 'move':
		case 'switch':
		case 'undo':
		case 'team':
			if (room.decision) room.decision(youUser,data.choice,data.move);
			break;
		case 'search':
			if (data.search) {
				if (typeof data.format !== 'string') return;
				if (room.searchBattle) room.searchBattle(youUser, data.format);
			} else {
				if (room.cancelSearch) room.cancelSearch(youUser);
			}
			break;
		}
	},
	saveTeam: function(data, socket, you) {
		if (!data) return;
		var youUser = resolveUser(you, socket);
		if (!youUser) return;
		youUser.team = data.team;
		youUser.emit('update', {team: 'saved', room: 'teambuilder'});
	}
};

if (config.protocol === 'io') { // Socket.IO
	server.sockets.on('connection', function (socket) {
		var you = null;
		console.log('INIT SOCKET: '+socket.id);

		if (socket.handshake && socket.handshake.address && socket.handshake.address.address) {
			if (bannedIps[socket.handshake.address.address]) {
				console.log('IP BANNED: '+socket.handshake.address.address);
				return;
			}
			socket.remoteAddress = socket.handshake.address.address; // for compatibility with SockJS semantics
		}
		var generator = function(type) {
			return function(data) {
				console.log('received '+type);
				console.log(you);
				events[type](data, socket, you);
			};
		};
		for (var e in events) {
			socket.on(e, (function(type) {
				return function(data) {
					console.log('received '+type);
					you = events[type](data, socket, you) || you;
				};
			})(e));
		}
	});
} else { // SockJS
	server.on('connection', function (socket) {
		var you = null;
		if (!socket) { // WTF
			return;
		}
		socket.id = randomString(16); // this sucks
		console.log('INIT SOCKET: '+socket.id);

		if (bannedIps[socket.remoteAddress]) {
			console.log('IP BANNED: '+socket.remoteAddress);
			return;
		}
		socket.on('data', function(message) {
			var data = JSON.parse(message);
			if (!data) return;
			if (events[data.type]) you = events[data.type](data, socket, you) || you;
		});
		socket.on('close', function() {
			youUser = resolveUser(you, socket);
			if (!youUser) return;
			youUser.disconnect(socket);
		});
	});
	server.installHandlers(app, {});
	app.listen(config.port);
}

console.log("Server started on port "+config.port);
console.log("Test your server at http://psim.tk/~~localhost:"+config.port);
<|endoftext|>


<commit_before>// ==UserScript==
// @name         RohBot Currency Converter
// @version      1.26
// @description  Allows the user to select their currency and then converts any found currencies to the one the user selected
// @author       Spans
// @match        https://rohbot.net
// @grant        none
// @updateURL	 https://raw.githubusercontent.com/Spanfile/RohBot-Currency-Converter/master/converter.js
// @require		 http://openexchangerates.github.io/money.js/money.min.js
// ==/UserScript==

var cacheKey = "spans-currency-cache";
var storeKey = "spans-currency";
var enabled = false;
var user = "eur";

var prefixes = {
	"k": 1000,
	"m": 1000000,
	"b": 1000000000
}

var currencies = {
	usd: { name: "USD", symbol: "$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?\$(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?: dollars?)(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? penn(?:y|ies)(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.01 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? nickels?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.05 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? dimes?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.1 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? quarters?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.25 }
	]},
	eur: { name: "EUR", symbol: "€", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?:€|e| eur(?:o|os)?)(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)€([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }
	]},
	gbp: { name: "GBP", symbol: "£", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?£(?=\s|$|,|\.|!|\?|\*|\/)/ig }, // the £ is for £
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)£([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?:p| pence)(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.01}
	]},
	cad: { name: "CAD", symbol: "CA$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)CA\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	aud: { name: "AUD", symbol: "A$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)A\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	nzd: { name: "NZD", symbol: "NZ$", pos :"pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)NZ\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	sek: { name: "SEK", symbol: " kr", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?kr(?=\s|$|,|\.|!|\?|\*|\/)/ig }, // kr defaults to swedish kronor
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?sek(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	nok: { name: "NOK", symbol: " nok", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?nok(?=\s|$|,|\.|!|\?|\*|\/)/ig }]}, // special cases for norwegian and danish kronor whatevers
	dkk: { name: "DKK", symbol: " dkk", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?dkk(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	zar: { name: "ZAR", symbol: "R", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)R([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]}
};

// first of all, setup the currency conversion
var cached = RohStore.get(cacheKey);
if (cached) {
	var cachedObj = JSON.parse(cached);
	fx.base = cachedObj.base;
	fx.rates = cachedObj.rates;
	enabled = true;
}

$.getJSON("https://api.fixer.io/latest", function(data) {
	if (typeof fx !== "undefined" && fx.rates) {
		fx.base = data.base;
		fx.rates = data.rates;
		enabled = true;
		cacheRates();
	}

	//console.log("Currency test: €1 = $" + fx(1).from("EUR").to("USD"));
});

function cacheRates() {
	RohStore.set(cacheKey, JSON.stringify({
		base: fx.base,
		rates: fx.rates
	}));
}

function load() {
	user = RohStore.get(storeKey) || "eur"; // haha fuck you americans
}

function save() {
	RohStore.set(storeKey, user);
}

chatMgr.lineFilter.add(function(line, prepend, e) {
	if (!enabled)
		return;

	line.Content = applyConversions(line.Content);
});

cmd.register("currency", "-", function(chat, args) {
	if (args.length != 1 || args[0].length === 0 || !currencies.hasOwnProperty(args[0])) {
		chat.statusMessage("Usage: /currency (" + Object.keys(currencies).join("|") + ")");
	}

	user = args[0];
	chat.statusMessage("Your preferred currency has been set to " + currencies[user].name);
	save();
});

function applyConversions(message) {
	var results = [];
	var userCurrency = currencies[user.toLowerCase()]; // toLowerCase() in case it's in upper case

	// try to find and convert any currencies except the users currency found in the message to the users currency
	for (var key in currencies) {
		if (currencies.hasOwnProperty(key)) { // hasOwnProperty() makes sure we don't loop over stuff inherited from the object's prototype
			var currency = currencies[key];

			if (currency.name != userCurrency.name) {
				var result = commonConversion(message, currency, userCurrency);

				if (result.length > 0) {
					results.push(result);
				}
			}
		}
	}

	// since the converters can return multiple conversions, flatten the results
	// the result looks like [[{stuff here}, {stuff here}], [{stuff here}, {stuff here}]]
	// flattening it turns it into [{stuff here}, {stuff here}, {stuff here}, {stuff here}]
	var flattened = [].concat.apply([], results);

	// sort them
	flattened.sort(function(a, b) {
		if (a.index > b.index) {
			return 1;
		}

		if (a.index < b.index) {
			return -1;
		}

		return 0;
	});

	var newMsg = message;
	var inserted = 0;
	// combine them all
	flattened.forEach(function(result) {
		var title = formatCurrency(result.conversion, result.currency);
		var original = result.original;
		var begin = "";

		// because the js regex engine doesn't support positive lookbehinds, the regexes return the whitespace before every match
		// most of the time they do it unless the match is at the start of the message
		// in case there is a whitespace, remove it and have one added before the  tag
		if (original.substring(0, 1) == " ") {
			original = original.substring(1);
			begin = " ";
		}

		var toInsert = begin + "" + original + "";
		newMsg = newMsg.splice(result.index + inserted, result.original.length, toInsert);
		inserted += toInsert.length - result.original.length;
	});

	return newMsg;
}

function commonConversion(message, from, to) {
	var m;
	var results = [];

	from.regexes.forEach(function(regexModifierPair) {
		while ((m = regexModifierPair.regex.exec(message)) !== null) {
			if (m.index === regexModifierPair.regex.lastIndex) {
				regex.lastIndex++;
			}

			var offset = 0;
			var amountStr = m[1];
			var prefix = m[2];

			if (amountStr.substring(0, 1) == ",") {
				amountStr = amountStr.substring(1);
				m[0] = m[0].substring(1);
				offset = 1;
			}

			var amount = Number(amountStr.replace(",", "")) * (regexModifierPair.modifier || 1);

			if (prefix) {
				amount *= prefixes[prefix];
			}

			var converted = Math.round(fx(amount).from(from.name).to(to.name) * 100) / 100; // two decimals is enough for currencies

			results[results.length] = {original: m[0], index: m.index + offset, conversion: converted, currency: to};
		}
	});

	return results;
}

function formatCurrency(value, currency) {
	var locale = value.toLocaleString();
	return currency.pos === "pre" ? currency.symbol + locale : locale + currency.symbol;
}

String.prototype.splice = function(idx, rem, s) {
	return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};

load();
<commit_msg>Fixed slight issue with prefixes<commit_after>// ==UserScript==
// @name         RohBot Currency Converter
// @version      1.27
// @description  Allows the user to select their currency and then converts any found currencies to the one the user selected
// @author       Spans
// @match        https://rohbot.net
// @grant        none
// @updateURL	 https://raw.githubusercontent.com/Spanfile/RohBot-Currency-Converter/master/converter.js
// @require		 http://openexchangerates.github.io/money.js/money.min.js
// ==/UserScript==

var cacheKey = "spans-currency-cache";
var storeKey = "spans-currency";
var enabled = false;
var user = "eur";

var prefixes = {
	"k": 1000,
	"m": 1000000,
	"b": 1000000000
}

var currencies = {
	usd: { name: "USD", symbol: "$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?\$(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?: dollars?)(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? penn(?:y|ies)(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.01 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? nickels?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.05 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? dimes?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.1 },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? quarters?(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.25 }
	]},
	eur: { name: "EUR", symbol: "€", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?:€|e| eur(?:o|os)?)(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)€([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }
	]},
	gbp: { name: "GBP", symbol: "£", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?£(?=\s|$|,|\.|!|\?|\*|\/)/ig }, // the £ is for £
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)£([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig },
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])?(?:p| pence)(?=\s|$|,|\.|!|\?|\*|\/)/ig, modifier: 0.01}
	]},
	cad: { name: "CAD", symbol: "CA$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)CA\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	aud: { name: "AUD", symbol: "A$", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)A\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	nzd: { name: "NZD", symbol: "NZ$", pos :"pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)NZ\$([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	sek: { name: "SEK", symbol: " kr", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?kr(?=\s|$|,|\.|!|\?|\*|\/)/ig }, // kr defaults to swedish kronor
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?sek(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	nok: { name: "NOK", symbol: " nok", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?nok(?=\s|$|,|\.|!|\?|\*|\/)/ig }]}, // special cases for norwegian and danish kronor whatevers
	dkk: { name: "DKK", symbol: " dkk", pos: "post", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)([\d,]+(?:\.\d+)?)([kmb])? ?dkk(?=\s|$|,|\.|!|\?|\*|\/)/ig }]},
	zar: { name: "ZAR", symbol: "R", pos: "pre", regexes: [
		{ regex: /(?:\s|^|,|\.|!|\?|\*|\/)R([\d,]+(?:\.\d+)?)([kmb])?(?=\s|$|,|\.|!|\?|\*|\/)/ig }]}
};

// first of all, setup the currency conversion
var cached = RohStore.get(cacheKey);
if (cached) {
	var cachedObj = JSON.parse(cached);
	fx.base = cachedObj.base;
	fx.rates = cachedObj.rates;
	enabled = true;
}

$.getJSON("https://api.fixer.io/latest", function(data) {
	if (typeof fx !== "undefined" && fx.rates) {
		fx.base = data.base;
		fx.rates = data.rates;
		enabled = true;
		cacheRates();
	}

	//console.log("Currency test: €1 = $" + fx(1).from("EUR").to("USD"));
});

function cacheRates() {
	RohStore.set(cacheKey, JSON.stringify({
		base: fx.base,
		rates: fx.rates
	}));
}

function load() {
	user = RohStore.get(storeKey) || "eur"; // haha fuck you americans
}

function save() {
	RohStore.set(storeKey, user);
}

chatMgr.lineFilter.add(function(line, prepend, e) {
	if (!enabled)
		return;

	line.Content = applyConversions(line.Content);
});

cmd.register("currency", "-", function(chat, args) {
	if (args.length != 1 || args[0].length === 0 || !currencies.hasOwnProperty(args[0])) {
		chat.statusMessage("Usage: /currency (" + Object.keys(currencies).join("|") + ")");
	}

	user = args[0];
	chat.statusMessage("Your preferred currency has been set to " + currencies[user].name);
	save();
});

function applyConversions(message) {
	var results = [];
	var userCurrency = currencies[user.toLowerCase()]; // toLowerCase() in case it's in upper case

	// try to find and convert any currencies except the users currency found in the message to the users currency
	for (var key in currencies) {
		if (currencies.hasOwnProperty(key)) { // hasOwnProperty() makes sure we don't loop over stuff inherited from the object's prototype
			var currency = currencies[key];

			if (currency.name != userCurrency.name) {
				var result = commonConversion(message, currency, userCurrency);

				if (result.length > 0) {
					results.push(result);
				}
			}
		}
	}

	// since the converters can return multiple conversions, flatten the results
	// the result looks like [[{stuff here}, {stuff here}], [{stuff here}, {stuff here}]]
	// flattening it turns it into [{stuff here}, {stuff here}, {stuff here}, {stuff here}]
	var flattened = [].concat.apply([], results);

	// sort them
	flattened.sort(function(a, b) {
		if (a.index > b.index) {
			return 1;
		}

		if (a.index < b.index) {
			return -1;
		}

		return 0;
	});

	var newMsg = message;
	var inserted = 0;
	// combine them all
	flattened.forEach(function(result) {
		var title = formatCurrency(result.conversion, result.currency);
		var original = result.original;
		var begin = "";

		// because the js regex engine doesn't support positive lookbehinds, the regexes return the whitespace before every match
		// most of the time they do it unless the match is at the start of the message
		// in case there is a whitespace, remove it and have one added before the  tag
		if (original.substring(0, 1) == " ") {
			original = original.substring(1);
			begin = " ";
		}

		var toInsert = begin + "" + original + "";
		newMsg = newMsg.splice(result.index + inserted, result.original.length, toInsert);
		inserted += toInsert.length - result.original.length;
	});

	return newMsg;
}

function commonConversion(message, from, to) {
	var m;
	var results = [];

	from.regexes.forEach(function(regexModifierPair) {
		while ((m = regexModifierPair.regex.exec(message)) !== null) {
			if (m.index === regexModifierPair.regex.lastIndex) {
				regex.lastIndex++;
			}

			var offset = 0;
			var amountStr = m[1];
			var prefix = m[2];

			if (amountStr.substring(0, 1) == ",") {
				amountStr = amountStr.substring(1);
				m[0] = m[0].substring(1);
				offset = 1;
			}

			var amount = Number(amountStr.replace(",", "")) * (regexModifierPair.modifier || 1);

			if (prefix) {
				amount *= prefixes[prefix.toLowerCase()];
			}

			var converted = Math.round(fx(amount).from(from.name).to(to.name) * 100) / 100; // two decimals is enough for currencies

			results[results.length] = {original: m[0], index: m.index + offset, conversion: converted, currency: to};
		}
	});

	return results;
}

function formatCurrency(value, currency) {
	var locale = value.toLocaleString();
	return currency.pos === "pre" ? currency.symbol + locale : locale + currency.symbol;
}

String.prototype.splice = function(idx, rem, s) {
	return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};

load();
<|endoftext|>


<commit_before>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-03-11
 * @author Liang <liang@maichong.it>
 */

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }

const service = __service;
const alaska = service.alaska;
const _ = require('lodash');

exports.default = (() => {
  var ref = _asyncToGenerator(function* (ctx, next) {
    yield ctx.checkAbility('admin');
    let serviceId = ctx.query.service;
    let modelName = ctx.query.model;
    let keyword = ctx.query.search || '';
    let page = parseInt(ctx.query.page) || 1;
    let perPage = parseInt(ctx.query.perPage) || 100;

    if (!serviceId || !modelName) {
      alaska.error('Invalid parameters');
    }
    let s = alaska.services[serviceId];
    if (!s) {
      alaska.error('Invalid parameters');
    }
    let Model = s.model(modelName);

    let ability = `admin.${ Model.key }.read`;
    yield ctx.checkAbility(ability);

    let titleField = Model.title || 'title';

    let filters = Model.createFilters(keyword, ctx.query.filters);

    let results = yield Model.paginate({
      page,
      perPage,
      filters
    }).select(titleField);

    ctx.body = {
      service: serviceId,
      model: modelName,
      next: results.next,
      total: results.total,
      results: _.map(results.results, function (record) {
        let tmp = {
          value: record.id
        };
        tmp.label = record[titleField] || tmp.id;
        return tmp;
      })
    };
  });

  return function (_x, _x2) {
    return ref.apply(this, arguments);
  };
})();<commit_msg>relation api<commit_after>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-03-11
 * @author Liang <liang@maichong.it>
 */

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

function _asyncToGenerator(fn) {
  return function () {
    var gen = fn.apply(this, arguments);
    return new Promise(function (resolve, reject) {
      function step(key, arg) {
        try {
          var info = gen[key](arg);
          var value = info.value;
        } catch (error) {
          reject(error);
          return;
        }
        if (info.done) {
          resolve(value);
        } else {
          return Promise.resolve(value).then(function (value) {
            return step("next", value);
          }, function (err) {
            return step("throw", err);
          });
        }
      }

      return step("next");
    });
  };
}

const service = __service;
const alaska = service.alaska;
const _ = require('lodash');

exports.default = (() => {
  var ref = _asyncToGenerator(function* (ctx, next) {
    yield ctx.checkAbility('admin');
    let serviceId = ctx.query.service;
    let modelName = ctx.query.model;
    let keyword = ctx.query.search || '';
    let page = parseInt(ctx.query.page) || 1;
    let perPage = parseInt(ctx.query.perPage) || 100;

    if (!serviceId || !modelName) {
      alaska.error('Invalid parameters');
    }
    let s = alaska.services[serviceId];
    if (!s) {
      alaska.error('Invalid parameters');
    }
    let Model = s.model(modelName);

    let ability = `admin.${ Model.key }.read`;
    yield ctx.checkAbility(ability);

    let titleField = Model.title || 'title';

    let filters = Model.createFilters(keyword, ctx.query.filters);

    let query = Model.paginate({
      page,
      perPage,
      filters
    }).select(titleField);

    let sort = ctx.query.sort || Model.defaultSort;
    if (sort) {
      query.sort(sort);
    }

    let results = yield query;

    ctx.body = {
      service: serviceId,
      model: modelName,
      next: results.next,
      total: results.total,
      results: _.map(results.results, function (record) {
        let tmp = {
          value: record.id
        };
        tmp.label = record[titleField] || tmp.id;
        return tmp;
      })
    };
  });

  return function (_x, _x2) {
    return ref.apply(this, arguments);
  };
})();
<|endoftext|>


<commit_before>var agent = require('./agent'),
    nats = require('nats').connect(),
    fs = require('fs'),
    log = require('logule').init(module, 'App'),
    config = require('./config')

var modules = {};

process.on('SIGTERM', function() {
    if (agent.getState() === 'RUNNING') {
        agent.stop();
    }
});

var senseId = process.argv[2] || undefined;
if (!senseId) {
    senseId = config.senseId || 'default';
}

try {
    agent.init(config.thinkURL, senseId, {autoreconnect: true});
    agent.start();

} catch (e) {
    log.error('Error: '+e);
}

agent.events.on('module.command', function(data) {

    log.info('Command: '+JSON.stringify(data));

    var module = data.commandType;
    var command = data.commandName;
    var topic = 'humix.sense.'+module+'.command.'+command;

    log.info('topic:'+topic);
    log.info('data:'+JSON.stringify(data.commandData));

    if(modules.hasOwnProperty(module) &&  modules[module].commands.indexOf(command) != -1 ){

        nats.publish(topic,JSON.stringify(data.commandData));
        log.info(' publish command');

    }else{

        log.info('skip command');
    }

});

// handle module events

nats.subscribe('humix.sense.*.event.*', function(data){

    log.info('receive module event:'+JSON.stringify(data));

})

// handle module registration
nats.subscribe('humix.sense.mgmt.register', function(request, replyto){
    log.info("Receive registration :"+ request);

    var requestModule = JSON.parse(request);

    modules[requestModule.moduleName] = requestModule;
    // TODO : propagate registration information to cloud

    var eventPrefix = 'humix.sense.'+requestModule.moduleName+".event";

    for ( var i in requestModule.events){

        var event = requestModule.events[i];
        var module = requestModule.moduleName;
        var topic = eventPrefix + "." + event;

        log.info("subscribing topic:"+ topic);

        (function(topic,module,event){

            nats.subscribe(topic, function(data){
                log.info('about to publish topic:'+topic+", data:"+data);
                agent.publish(module, event, data);
            });
        })(topic,module,event);

    }

    // register the module to humix-think

    agent.publish('humix-think', 'registerModule', requestModule);

    console.log('current modules:'+JSON.stringify(modules));
    nats.publish(replyto,'got you');

});

// for testing
/*
setInterval(function() {
    if (agent.getState() === 'CONNECTED') {
        agent.publish('temp', 'currentTemp', 25);
    }
}, 3000);
*/
setTimeout(function() {
    if (agent.getState() === 'CONNECTED') {
        console.log('connected....');
        agent.publish('humix-think', 'registerModule', {
            moduleName: 'neopixel',
            commands: ['feel', 'mode', 'color'],
            events: ['event1']
        });
        agent.publish('humix-think', 'registerModule', {
            moduleName: 'tts',
            commands: ['command1', 'command2'],
            events: ['event1', 'event2']
        });
    }
}, 2000);

<commit_msg>avoid duplicated registration<commit_after>var agent = require('./agent'),
    nats = require('nats').connect(),
    fs = require('fs'),
    log = require('logule').init(module, 'App'),
    config = require('./config')

var modules = {};

process.on('SIGTERM', function() {
    if (agent.getState() === 'RUNNING') {
        agent.stop();
    }
});

var senseId = process.argv[2] || undefined;
if (!senseId) {
    senseId = config.senseId || 'default';
}

try {
    agent.init(config.thinkURL, senseId, {autoreconnect: true});
    agent.start();

} catch (e) {
    log.error('Error: '+e);
}

agent.events.on('module.command', function(data) {

    log.info('Command: '+JSON.stringify(data));

    var module = data.commandType;
    var command = data.commandName;
    var topic = 'humix.sense.'+module+'.command.'+command;

    log.info('topic:'+topic);
    log.info('data:'+JSON.stringify(data.commandData));

    if(modules.hasOwnProperty(module) &&  modules[module].commands.indexOf(command) != -1 ){

        nats.publish(topic,JSON.stringify(data.commandData));
        log.info(' publish command');

    }else{

        log.info('skip command');
    }

});

// handle module events

nats.subscribe('humix.sense.*.event.*', function(data){

    log.info('receive module event:'+JSON.stringify(data));

})

// handle module registration
nats.subscribe('humix.sense.mgmt.register', function(request, replyto){
    log.info("Receive registration :"+ request);

    var requestModule = JSON.parse(request);

    if(modules.hasOwnProperty(requestModule.moduleName)){
        console.log('Module [' + requestModule.moduleName + '] already register. Skip');
        nats.publish(replyto,'module already registered');
        return;
    }

    modules[requestModule.moduleName] = requestModule;

    var eventPrefix = 'humix.sense.'+requestModule.moduleName+".event";

    for ( var i in requestModule.events){

        var event = requestModule.events[i];
        var module = requestModule.moduleName;
        var topic = eventPrefix + "." + event;

        log.info("subscribing topic:"+ topic);

        (function(topic,module,event){

            nats.subscribe(topic, function(data){
                log.info('about to publish topic:'+topic+", data:"+data);
                agent.publish(module, event, data);
            });
        })(topic,module,event);

    }

    // register the module to humix-think

    agent.publish('humix-think', 'registerModule', requestModule);

    console.log('current modules:'+JSON.stringify(modules));
    nats.publish(replyto,'module registration succeed');

});

// for testing
/*
setInterval(function() {
    if (agent.getState() === 'CONNECTED') {
        agent.publish('temp', 'currentTemp', 25);
    }
}, 3000);
*/
setTimeout(function() {
    if (agent.getState() === 'CONNECTED') {
        console.log('connected....');
        agent.publish('humix-think', 'registerModule', {
            moduleName: 'neopixel',
            commands: ['feel', 'mode', 'color'],
            events: ['event1']
        });
        agent.publish('humix-think', 'registerModule', {
            moduleName: 'tts',
            commands: ['command1', 'command2'],
            events: ['event1', 'event2']
        });
    }
}, 2000);

<|endoftext|>