// Generated by CoffeeScript 1.10.0 (function() { var Mandate, Promise, UserHandler, auth, authentication, baseRoute, compressible, config, database, developmentLogging, errors, express, fs, geoip, log, logging, path, perfmon, productionLogging, request, routes, setupCountryRedirectMiddleware, setupErrorMiddleware, setupExpressMiddleware, setupFacebookCrossDomainCommunicationRoute, setupFallbackRouteToIndex, setupJavascript404s, setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly, setupOneSecondDelayMiddleware, setupPassportMiddleware, setupPerfMonMiddleware, setupRedirectMiddleware, slack, user, useragent; express = require('express'); path = require('path'); authentication = require('passport'); useragent = require('express-useragent'); fs = require('graceful-fs'); log = require('winston'); compressible = require('compressible'); geoip = require('geoip-lite'); database = require('./server/commons/database'); perfmon = require('./server/commons/perfmon'); baseRoute = require('./server/routes/base'); user = require('./server/users/user_handler'); logging = require('./server/commons/logging'); config = require('./server_config'); auth = require('./server/routes/auth'); routes = require('./server/routes'); UserHandler = require('./server/users/user_handler'); slack = require('./server/slack'); Mandate = require('./server/models/Mandate'); global.tv4 = require('tv4'); global.jsondiffpatch = require('jsondiffpatch'); global.stripe = require('stripe')(config.stripe.secretKey); errors = require('./server/commons/errors'); request = require('request'); Promise = require('bluebird'); Promise.promisifyAll(request, { multiArgs: true }); productionLogging = function(tokens, req, res) { var color, elapsed, elapsedColor, status; status = res.statusCode; color = 32; if (status >= 500) { color = 31; } else if (status >= 400) { color = 33; } else if (status >= 300) { color = 36; } elapsed = (new Date()) - req._startTime; elapsedColor = elapsed < 500 ? 90 : 31; if (status === 404 && /\/feedback/.test(req.originalUrl)) { return null; } if ((status !== 200 && status !== 201 && status !== 204 && status !== 304 && status !== 302) || elapsed > 500) { return "\x1b[90m" + req.method + " " + req.originalUrl + " \x1b[" + color + "m" + res.statusCode + " \x1b[" + elapsedColor + "m" + elapsed + "ms\x1b[0m"; } return null; }; developmentLogging = function(tokens, req, res) { var color, elapsed, elapsedColor, status; status = res.statusCode; color = 32; if (status >= 500) { color = 31; } else if (status >= 400) { color = 33; } else if (status >= 300) { color = 36; } elapsed = (new Date()) - req._startTime; elapsedColor = elapsed < 500 ? 90 : 31; return "\x1b[90m" + req.method + " " + req.originalUrl + " \x1b[" + color + "m" + res.statusCode + " \x1b[" + elapsedColor + "m" + elapsed + "ms\x1b[0m"; }; setupErrorMiddleware = function(app) { return app.use(function(err, req, res, next) { var message, ref, ref1; if (err) { if (err.name === 'MongoError' && err.code === 11000) { err = new errors.Conflict('MongoDB conflict error.'); } if (err.code === 422 && err.response) { err = new errors.UnprocessableEntity(err.response); } if (err.code === 409 && err.response) { err = new errors.Conflict(err.response); } if (err instanceof errors.NetworkError) { return res.status(err.code).send(err.toJSON()); } if (err.status && (400 <= (ref = err.status) && ref < 500)) { res.status(err.status).send("Error " + err.status); return; } res.status((ref1 = err.status) != null ? ref1 : 500).send({ error: "Something went wrong!" }); message = "Express error: " + req.method + " " + req.path + ": " + err.message; log.error(message + ", stack: " + err.stack); return slack.sendSlackMessage(message, ['ops'], { papertrail: true }); } else { return next(err); } }); }; setupExpressMiddleware = function(app) { if (config.isProduction) { express.logger.format('prod', productionLogging); app.use(express.logger('prod')); app.use(express.compress({ filter: function(req, res) { if (req.headers.host === 'codecombat.com') { return false; } return compressible(res.getHeader('Content-Type')); } })); } else { express.logger.format('dev', developmentLogging); app.use(express.logger('dev')); } app.use(express["static"](path.join(__dirname, 'public'), { maxAge: 0 })); app.use(useragent.express()); app.use(express.favicon()); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.methodOverride()); return app.use(express.cookieSession({ key: 'codecombat.sess', secret: config.cookie_secret })); }; setupPassportMiddleware = function(app) { app.use(authentication.initialize()); if (config.picoCTF) { app.use(authentication.authenticate('local', { failureRedirect: config.picoCTF_login_URL })); return require('./server/lib/picoctf').init(app); } else { return app.use(authentication.session()); } }; setupCountryRedirectMiddleware = function(app, country, countryCode, languageCode, serverID) { var shouldRedirectToCountryServer; if (country == null) { country = "china"; } if (countryCode == null) { countryCode = "CN"; } if (languageCode == null) { languageCode = "zh"; } if (serverID == null) { serverID = "tokyo"; } shouldRedirectToCountryServer = function(req) { var geo, ip, speaksLanguage; speaksLanguage = _.any(req.acceptedLanguages, function(language) { return language.indexOf(languageCode !== -1); }); if (!config[serverID]) { ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; ip = ip != null ? ip.split(/,? /)[0] : void 0; geo = geoip.lookup(ip); return (geo != null ? geo.country : void 0) === countryCode && speaksLanguage; } else { if (speaksLanguage) { req.country = country; } return false; } }; return app.use(function(req, res, next) { if (shouldRedirectToCountryServer(req)) { res.writeHead(302, { "Location": config[country + 'Domain'] + req.url }); return res.end(); } else { return next(); } }); }; setupOneSecondDelayMiddleware = function(app) { if (config.slow_down) { return app.use(function(req, res, next) { return setTimeout((function() { return next(); }), 1000); }); } }; setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly = function(app) { var isOldBrowser; isOldBrowser = function(req) { var b, ref, ua, v; if (!(ua = req.useragent)) { return false; } if (ua.isiPad || ua.isiPod || ua.isiPhone || ua.isOpera) { return true; } if (!(ua && ((ref = ua.Browser) === 'Chrome' || ref === 'Safari' || ref === 'Firefox' || ref === 'IE') && ua.Version)) { return false; } b = ua.Browser; v = parseInt(ua.Version.split('.')[0], 10); if (b === 'Chrome' && v < 17) { return true; } if (b === 'Safari' && v < 6) { return true; } if (b === 'Firefox' && v < 21) { return true; } if (b === 'IE' && v < 10) { return true; } return false; }; return app.use('/play/', function(req, res, next) { if (req.query['try-old-browser-anyway'] || !isOldBrowser(req)) { return next(); } return res.sendfile(path.join(__dirname, 'public', 'index_old_browser.html')); }); }; setupRedirectMiddleware = function(app) { return app.all('/account/profile/*', function(req, res, next) { var nameOrID; nameOrID = req.path.split('/')[3]; return res.redirect(301, "/user/" + nameOrID + "/profile"); }); }; setupPerfMonMiddleware = function(app) { return app.use(perfmon.middleware); }; exports.setupMiddleware = function(app) { setupPerfMonMiddleware(app); setupCountryRedirectMiddleware(app, "china", "CN", "zh", "tokyo"); setupCountryRedirectMiddleware(app, "brazil", "BR", "pt-BR", "saoPaulo"); setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly(app); setupExpressMiddleware(app); setupPassportMiddleware(app); setupOneSecondDelayMiddleware(app); setupRedirectMiddleware(app); setupErrorMiddleware(app); return setupJavascript404s(app); }; /*Routing function implementations */ setupJavascript404s = function(app) { return app.get('/javascripts/*', function(req, res) { return res.status(404).send('Not found'); }); }; setupFallbackRouteToIndex = function(app) { return app.all('*', function(req, res) { return fs.readFile(path.join(__dirname, 'public', 'main.html'), 'utf8', function(err, data) { if (err) { log.error("Error modifying main.html: " + err); } user = req.user ? JSON.stringify(UserHandler.formatEntity(req, req.user)).replace(/\//g, '\\/') : '{}'; return Mandate.findOne({}).cache(5 * 60 * 1000).exec(function(err, mandate) { var configData; if (err) { log.error("Error getting mandate config: " + err); configData = {}; } else { configData = _.omit((mandate != null ? mandate.toObject() : void 0) || {}, '_id'); } configData.picoCTF = config.picoCTF; configData.production = config.isProduction; data = data.replace('"serverConfigTag"', JSON.stringify(configData)); data = data.replace('"userObjectTag"', user); data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually)); res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); res.header('Pragma', 'no-cache'); res.header('Expires', 0); return res.send(200, data); }); }); }); }; setupFacebookCrossDomainCommunicationRoute = function(app) { return app.get('/channel.html', function(req, res) { return res.sendfile(path.join(__dirname, 'public', 'channel.html')); }); }; exports.setupRoutes = function(app) { routes.setup(app); app.use(app.router); baseRoute.setup(app); setupFacebookCrossDomainCommunicationRoute(app); return setupFallbackRouteToIndex(app); }; /*Miscellaneous configuration functions */ exports.setupLogging = function() { return logging.setup(); }; exports.connectToDatabase = function() { return database.connect(); }; exports.setupMailchimp = function() { var mc, mcapi; mcapi = require('mailchimp-api'); mc = new mcapi.Mailchimp(config.mail.mailchimpAPIKey); return GLOBAL.mc = mc; }; exports.setExpressConfigurationOptions = function(app) { app.set('port', config.port); app.set('views', __dirname + '/app/views'); app.set('view engine', 'jade'); app.set('view options', { layout: false }); app.set('env', config.isProduction ? 'production' : 'development'); if (config.isProduction) { return app.set('json spaces', 0); } }; }).call(this);