<commit_before>const cookieParser = require('cookie-parser');
const logger = require('../logging');
const socketio = require('socket.io');
const cookieParserIO = require('socket.io-cookie');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const passportSocketIo = require('passport.socketio');

const auth = require('./auth');
const permissions = require('../../common/auth/permissions');
const connection = require('./connection');
const { listener: issueListener } = require('./issue');
const { listener: meetingListener } = require('./admin/meeting');
const { listener: userListListener } = require('./admin/user/userlist');
const { listener: toggleCanVoteListener } = require('./admin/user/toggle_vote');
const { listener: voteListener } = require('./vote');

const authorizeSuccess = (data, accept) => {
  logger.silly('Authorized socket connection');
  accept();
};

const authorizeFailure = (data, message, error, accept) => {
  logger.silly(`Authorization failed for socket connection: ${message}`);
  if (error) {
    logger.error(`Error occured: ${message}`, error);
    accept(new Error(message));
  }
};

const applyMiddlewares = (io, mongooseConnection) => {
  io.use(passportSocketIo.authorize({
    cookieParser,
    key: 'connect.sid',
    secret: 'super secret',
    store: new MongoStore({ mongooseConnection }),
    success: authorizeSuccess,
    fail: authorizeFailure,
  }));
  io.use(cookieParserIO);
};

const listen = (server, mongooseConnection) => {
  const io = socketio(server);
  applyMiddlewares(io, mongooseConnection);
  io.on('connection', (socket) => {
    connection(socket);
    auth(socket);
    voteListener(socket);

    // Admin
    if (socket.request.user.permissions >= permissions.IS_MANAGER) {
      const user = socket.request.user;
      logger.debug(`${user.name} ('${user.onlinewebId}') has manager status, ` +
        'authorized for admin sockets.');
      issueListener(socket);
      userListListener(socket);
      toggleCanVoteListener(socket);
      meetingListener(socket);
    }
  });
};

module.exports = {
  applyMiddlewares,
  listen,
};
<commit_msg>Fix auth channel<commit_after>const cookieParser = require('cookie-parser');
const logger = require('../logging');
const socketio = require('socket.io');
const cookieParserIO = require('socket.io-cookie');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const passportSocketIo = require('passport.socketio');

const permissions = require('../../common/auth/permissions');
const connection = require('./connection');
const { listener: authListener } = require('./auth');
const { listener: issueListener } = require('./issue');
const { listener: meetingListener } = require('./admin/meeting');
const { listener: userListListener } = require('./admin/user/userlist');
const { listener: toggleCanVoteListener } = require('./admin/user/toggle_vote');
const { listener: voteListener } = require('./vote');

const authorizeSuccess = (data, accept) => {
  logger.silly('Authorized socket connection');
  accept();
};

const authorizeFailure = (data, message, error, accept) => {
  logger.silly(`Authorization failed for socket connection: ${message}`);
  if (error) {
    logger.error(`Error occured: ${message}`, error);
    accept(new Error(message));
  }
};

const applyMiddlewares = (io, mongooseConnection) => {
  io.use(passportSocketIo.authorize({
    cookieParser,
    key: 'connect.sid',
    secret: 'super secret',
    store: new MongoStore({ mongooseConnection }),
    success: authorizeSuccess,
    fail: authorizeFailure,
  }));
  io.use(cookieParserIO);
};

const listen = (server, mongooseConnection) => {
  const io = socketio(server);
  applyMiddlewares(io, mongooseConnection);
  io.on('connection', (socket) => {
    connection(socket);
    authListener(socket);
    voteListener(socket);

    // Admin
    if (socket.request.user.permissions >= permissions.IS_MANAGER) {
      const user = socket.request.user;
      logger.debug(`${user.name} ('${user.onlinewebId}') has manager status, ` +
        'authorized for admin sockets.');
      issueListener(socket);
      userListListener(socket);
      toggleCanVoteListener(socket);
      meetingListener(socket);
    }
  });
};

module.exports = {
  applyMiddlewares,
  listen,
};
<|endoftext|>


<commit_before>import express from 'express';
import passport from 'passport';
import session from 'express-session';
import bodyParser from 'body-parser';
import path from 'path';
import flash from 'express-flash';
import methodOverride from 'method-override';
import unsupportedMessage from '../db/unsupportedMessage';
import { sessionSecret } from './secrets';
import { DB_TYPE, ENV } from './appConfig';
import { session as dbSession } from '../db';

export default (app) => {
  app.set('port', (process.env.PORT || 3000));

  // X-Powered-By header has no functional value.
  // Keeping it makes it easier for an attacker to build the site's profile
  // It can be removed safely
  app.disable('x-powered-by');
  app.set('views', path.join(__dirname, '..', 'views'));

  app.set('view cache', false);

  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
  app.use(methodOverride());
  app.use(express.static(path.join(__dirname, '../..', 'public')));

  // I am adding this here so that the Heroku deploy will work
  // Indicates the app is behind a front-facing proxy,
  // and to use the X-Forwarded-* headers to determine the connection and the IP address of the client.
  // NOTE: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
  // trust proxy is disabled by default.
  // When enabled, Express attempts to determine the IP address of the client connected through the front-facing proxy, or series of proxies.
  // The req.ips property, then, contains an array of IP addresses the client is connected through.
  // To enable it, use the values described in the trust proxy options table.
  // The trust proxy setting is implemented using the proxy-addr package. For more information, see its documentation.
  // loopback - 127.0.0.1/8, ::1/128
  app.set('trust proxy', 'loopback');
  // Create a session middleware with the given options
  // Note session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
  // Options: resave: forces the session to be saved back to the session store, even if the session was never
  //                  modified during the request. Depending on your store this may be necessary, but it can also
  //                  create race conditions where a client has two parallel requests to your server and changes made
  //                  to the session in one request may get overwritten when the other request ends, even if it made no
  //                  changes(this behavior also depends on what store you're using).
  //          saveUnitialized: Forces a session that is uninitialized to be saved to the store. A session is uninitialized when
  //                  it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage
  //                  usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with
  //                  race conditions where a client makes multiple parallel requests without a session
  //          secret: This is the secret used to sign the session ID cookie.
  //          name: The name of the session ID cookie to set in the response (and read from in the request).
  //          cookie: Please note that secure: true is a recommended option.
  //                  However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies.
  //                  If secure is set, and you access your site over HTTP, the cookie will not be set.
  let sessionStore = null;
  if (!dbSession) {
    console.warn(unsupportedMessage('session'));
  } else {
    sessionStore = dbSession();
  }

  const sess = {
    resave: false,
    saveUninitialized: false,
    secret: sessionSecret,
    proxy: true, // The "X-Forwarded-Proto" header will be used.
    name: 'sessionId',
    // Add HTTPOnly, Secure attributes on Session Cookie
    // If secure is set, and you access your site over HTTP, the cookie will not be set
    cookie: {
      httpOnly: true,
      secure: false,
    },
    store: sessionStore
  };

  console.log('--------------------------');
  console.log('===> 😊  Starting Server . . .');
  console.log(`===>  Environment: ${ENV}`);
  console.log(`===>  Listening on port: ${app.get('port')}`);
  console.log(`===>  Using DB TYPE: ${DB_TYPE}`);
  if (ENV === 'production') {
    console.log('===> 🚦  Note: In order for authentication to work in production');
    console.log('===>           you will need a secure HTTPS connection');
    sess.cookie.secure = true; // Serve secure cookies
  }
  console.log('--------------------------');

  app.use(session(sess));

  app.use(passport.initialize());
  app.use(passport.session());

  app.use(flash());
};
<commit_msg>Remove legacy Express views config<commit_after>import express from 'express';
import passport from 'passport';
import session from 'express-session';
import bodyParser from 'body-parser';
import path from 'path';
import flash from 'express-flash';
import methodOverride from 'method-override';
import unsupportedMessage from '../db/unsupportedMessage';
import { sessionSecret } from './secrets';
import { DB_TYPE, ENV } from './appConfig';
import { session as dbSession } from '../db';

export default (app) => {
  app.set('port', (process.env.PORT || 3000));

  // X-Powered-By header has no functional value.
  // Keeping it makes it easier for an attacker to build the site's profile
  // It can be removed safely
  app.disable('x-powered-by');

  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
  app.use(methodOverride());
  app.use(express.static(path.join(__dirname, '../..', 'public')));

  // I am adding this here so that the Heroku deploy will work
  // Indicates the app is behind a front-facing proxy,
  // and to use the X-Forwarded-* headers to determine the connection and the IP address of the client.
  // NOTE: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
  // trust proxy is disabled by default.
  // When enabled, Express attempts to determine the IP address of the client connected through the front-facing proxy, or series of proxies.
  // The req.ips property, then, contains an array of IP addresses the client is connected through.
  // To enable it, use the values described in the trust proxy options table.
  // The trust proxy setting is implemented using the proxy-addr package. For more information, see its documentation.
  // loopback - 127.0.0.1/8, ::1/128
  app.set('trust proxy', 'loopback');
  // Create a session middleware with the given options
  // Note session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
  // Options: resave: forces the session to be saved back to the session store, even if the session was never
  //                  modified during the request. Depending on your store this may be necessary, but it can also
  //                  create race conditions where a client has two parallel requests to your server and changes made
  //                  to the session in one request may get overwritten when the other request ends, even if it made no
  //                  changes(this behavior also depends on what store you're using).
  //          saveUnitialized: Forces a session that is uninitialized to be saved to the store. A session is uninitialized when
  //                  it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage
  //                  usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with
  //                  race conditions where a client makes multiple parallel requests without a session
  //          secret: This is the secret used to sign the session ID cookie.
  //          name: The name of the session ID cookie to set in the response (and read from in the request).
  //          cookie: Please note that secure: true is a recommended option.
  //                  However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies.
  //                  If secure is set, and you access your site over HTTP, the cookie will not be set.
  let sessionStore = null;
  if (!dbSession) {
    console.warn(unsupportedMessage('session'));
  } else {
    sessionStore = dbSession();
  }

  const sess = {
    resave: false,
    saveUninitialized: false,
    secret: sessionSecret,
    proxy: true, // The "X-Forwarded-Proto" header will be used.
    name: 'sessionId',
    // Add HTTPOnly, Secure attributes on Session Cookie
    // If secure is set, and you access your site over HTTP, the cookie will not be set
    cookie: {
      httpOnly: true,
      secure: false,
    },
    store: sessionStore
  };

  console.log('--------------------------');
  console.log('===> 😊  Starting Server . . .');
  console.log(`===>  Environment: ${ENV}`);
  console.log(`===>  Listening on port: ${app.get('port')}`);
  console.log(`===>  Using DB TYPE: ${DB_TYPE}`);
  if (ENV === 'production') {
    console.log('===> 🚦  Note: In order for authentication to work in production');
    console.log('===>           you will need a secure HTTPS connection');
    sess.cookie.secure = true; // Serve secure cookies
  }
  console.log('--------------------------');

  app.use(session(sess));

  app.use(passport.initialize());
  app.use(passport.session());

  app.use(flash());
};
<|endoftext|>


<commit_before>// mode: js2

startMonitoringContainer = function(hostId, containerId){
  if (! ensureApi(hostId,"1.17"))
    return;
  if (! _.isUndefined(containerStats[containerId]))
    return;
  if (docker[hostId] === undefined)
    return;
  if (modules.stats === undefined || modules.stats.active === undefined || ! modules.stats.active)
    return;

  var container = docker[hostId].getContainer(containerId);
  if (!container)
    return;
  containerStats[containerId] = {status: 2};
  container.stats(Meteor.bindEnvironment(
    function (err, stream) {
      if (err){
        delete containerStats[containerId];
        console.log(err);
        return;
      }

      containerStats[containerId] = {stream: stream, status:1};
      stream.on('data', Meteor.bindEnvironment(
        function(chunk){
          try{
            var stat = JSON.parse(chunk);
            stat.Id = containerId;
            stat._host = hostId;
            stat.read = moment(stat.read).millisecond(0).toDate();
            ContainersStats.upsert({Id:stat.Id, _host: stat._host, read: stat.read}, stat);
          } catch(err){
            console.log('error during stats: ', err, chunk.toString());
          }
        })).
        on('end', Meteor.bindEnvironment(function(){
                    delete containerStats[containerId];
                  })).
        on('close', Meteor.bindEnvironment(function(){
                      delete containerStats[containerId];
                    })).
        on('error', Meteor.bindEnvironment(function(){
                      delete containerStats[containerId];
                    }));
    }));
};

startMonitoringContainers = function(){
  Containers.find().forEach(function(container){
    startMonitoringContainer(container._host,container.Id);
  });
};

// Clean old stats
SyncedCron.add({
  name: 'Clean old stats',
  schedule: function(parser) {
    return parser.text('every 2 hours');
  },
  job: function() {
    var query = {read: {$lt: moment().subtract(4, 'hours').toDate()}};
    var stats = ContainersStats.find(query);
    ContainersStats.remove(query);
    return stats.count();
  }
});

SyncedCron.config({
  log:false
});

Meteor.startup(function(){
  SyncedCron.start();
});<commit_msg>clean docker log headers<commit_after>// mode: js2

startMonitoringContainer = function(hostId, containerId){
  if (! ensureApi(hostId,"1.17"))
    return;
  if (! _.isUndefined(containerStats[containerId]))
    return;
  if (docker[hostId] === undefined)
    return;
  if (modules.stats === undefined || modules.stats.active === undefined || ! modules.stats.active)
    return;

  var container = docker[hostId].getContainer(containerId);
  if (!container)
    return;
  containerStats[containerId] = {status: 2};
  container.stats(Meteor.bindEnvironment(
    function (err, stream) {
      if (err){
        delete containerStats[containerId];
        console.log(err);
        return;
      }

      var buffer='';
      containerStats[containerId] = {stream: stream, status:1};
      stream.on('data', Meteor.bindEnvironment(
        function(chunk){
          try{
            buffer += chunk;
            var stat = JSON.parse(buffer);
            stat.Id = containerId;
            stat._host = hostId;
            stat.read = moment(stat.read).millisecond(0).toDate();
            ContainersStats.upsert({Id:stat.Id, _host: stat._host, read: stat.read}, stat);
            buffer ='';
          } catch(err){
            //console.log('error during stats: ', err, chunk.toString());
          }
        })).
        on('end', Meteor.bindEnvironment(function(){
                    delete containerStats[containerId];
                  })).
        on('close', Meteor.bindEnvironment(function(){
                      delete containerStats[containerId];
                    })).
        on('error', Meteor.bindEnvironment(function(){
                      delete containerStats[containerId];
                    }));
    }));
};

startMonitoringContainers = function(){
  Containers.find().forEach(function(container){
    startMonitoringContainer(container._host,container.Id);
  });
};

// Clean old stats
SyncedCron.add({
  name: 'Clean old stats',
  schedule: function(parser) {
    return parser.text('every 2 hours');
  },
  job: function() {
    var query = {read: {$lt: moment().subtract(4, 'hours').toDate()}};
    var stats = ContainersStats.find(query);
    ContainersStats.remove(query);
    return stats.count();
  }
});

SyncedCron.config({
  log:false
});

Meteor.startup(function(){
  SyncedCron.start();
});<|endoftext|>


<commit_before>var moment = require('moment');
var geolib = require('geolib');
var shortid = require('shortid');
var fs = require('fs');
var themes = require('./themes');

// Use moment.js to calculate how much time has elapsed since some prior time
exports.getTimeElapsedSince = function(time) {
  return moment(time).fromNow();
};

// Use geolib.js to calculate distance from the mark to the user
exports.getDistanceFrom = function(mark, user) {
  var dist = geolib.getDistance(
      {latitude: user.x, longitude: user.y},
      {latitude: mark.x, longitude: mark.y}
      );
  return dist + 'm';
};

exports.decorateMarksWithVoteStatus = function(marks, votes) {
  var voted = {};
  for (var k = 0;k < votes.length;k++) {
    voted[votes[k].messageId] = true;
  }
  for (var i = 0;i < marks.length;i++) {
    var markMessageId = marks[i].messageId;
    if (voted[markMessageId]) {
      marks[i].voted = true;
    } else {
      marks[i].voted = false;
    }
  }
  return marks;
};

exports.decorateCommentsWithVoteStatus = function(comments, votes) {
  var voted = {};
  for (var k = 0;k < votes.length;k++) {
    voted[votes[k].commentId] = true;
  }
  for (var i = 0;i < comments.length;i++) {
    var commentId = comments[i].commentId;
    if (voted[commentId]) {
      comments[i].voted = true;
    } else {
      comments[i].voted = false;
    }
  }
  return comments;
};

// The object we pull from the database has specific data (time/location)
// Here we create a new object that has data that is relevant to the user
exports.createMessageResponseObjects = function(marks, user) {
  var responseObjects = [];
  var responseObject;

  marks.forEach(function(mark) {
    responseObject = {
      timestamp: exports.getTimeElapsedSince(mark.timestamp),
      distance: exports.getDistanceFrom(mark, user),
      messageId: mark.messageId,
      messageString: mark.messageString,
      image: mark.image,
      imageH: mark.imageH,
      imageW: mark.imageW,
      score: mark.score,
      votes: mark['COUNT(distinct votes.id)'],
      comments: mark['COUNT(distinct comments.id)']
    };
    responseObjects.push(responseObject);
  });
  return responseObjects;
};

exports.createCommentResponseObjects = function(marks, user) {
  var responseObjects = [];
  var responseObject;

  marks.forEach(function(mark) {
    if (mark.id !== null) {
      responseObject = {
        timestamp: exports.getTimeElapsedSince(mark.timestamp),
        distance: exports.getDistanceFrom(mark, user),
        commentId: mark.commentId,
        commentString: mark.commentString,
        name: createIdentity(mark.userToken, user.messageId),
        votes: mark['COUNT(votes.id)']
      };
      responseObjects.push(responseObject);
    }
  });

  return responseObjects;
};

var hashCode = function(string) {
  var hash = 0;
  if (string.length == 0) return hash;
  for (i = 0; i < string.length; i++) {
    char = string.charCodeAt(i);
    hash = ((hash<<5)-hash)+char;
    hash = hash & hash;
  }
  return hash;
};

var createIdentity = function(userToken, messageId) {
  var identities = themes[0];
  var i = Math.abs(hashCode(userToken + messageId)) % (identities.length-1);
  return identities[i];
};

exports.saveImage = function(img64, callback) {
  if (img64) {
    var base64Data = img64.replace(/^data:image\/jpg;base64,/, '');
    var imgName = shortid.generate();
    var filename = 'server/images/' + imgName + '.jpg';

    fs.writeFile(filename, base64Data, 'base64', function(err) {
      if (err) console.log(err);
      if (callback) callback(imgName);
    });

    return imgName;
  } else {
    return null;
  }
};

exports.getImage = function(imgName) {
  return new Promise(function(resolve, reject) {
    var filename = 'server/images/' + imgName + '.jpg';
    fs.readFile(filename, function(err, img) {
      if (err) {
        reject(err);
      } else {
        resolve(img);
      }
    });
  });
};

exports.getLogStream = function() {
  console.log(__dirname);
  var accessLogStream = fs.createWriteStream(__dirname + '/../log/access.log', {flags: 'a'});
  return {stream: accessLogStream};
};

exports.createQueryParams = function(obj) {
  var params = [];

  for (var k in obj) {
    params.push(k);
    params.push(obj[k]);
  }

  return params;
};

exports.rejectPOST = exports.rejectGET = function(req, res, err) {
  res.sendStatus(400);
};

exports.resolveGET = function(req, res, success) {
  res.status(200);
  res.send(success);
};

exports.resolvePOST = function(req, res, success) {
  res.sendStatus(201);
};
<commit_msg>Remove unncessary console log<commit_after>var moment = require('moment');
var geolib = require('geolib');
var shortid = require('shortid');
var fs = require('fs');
var themes = require('./themes');

// Use moment.js to calculate how much time has elapsed since some prior time
exports.getTimeElapsedSince = function(time) {
  return moment(time).fromNow();
};

// Use geolib.js to calculate distance from the mark to the user
exports.getDistanceFrom = function(mark, user) {
  var dist = geolib.getDistance(
      {latitude: user.x, longitude: user.y},
      {latitude: mark.x, longitude: mark.y}
      );
  return dist + 'm';
};

exports.decorateMarksWithVoteStatus = function(marks, votes) {
  var voted = {};
  for (var k = 0;k < votes.length;k++) {
    voted[votes[k].messageId] = true;
  }
  for (var i = 0;i < marks.length;i++) {
    var markMessageId = marks[i].messageId;
    if (voted[markMessageId]) {
      marks[i].voted = true;
    } else {
      marks[i].voted = false;
    }
  }
  return marks;
};

exports.decorateCommentsWithVoteStatus = function(comments, votes) {
  var voted = {};
  for (var k = 0;k < votes.length;k++) {
    voted[votes[k].commentId] = true;
  }
  for (var i = 0;i < comments.length;i++) {
    var commentId = comments[i].commentId;
    if (voted[commentId]) {
      comments[i].voted = true;
    } else {
      comments[i].voted = false;
    }
  }
  return comments;
};

// The object we pull from the database has specific data (time/location)
// Here we create a new object that has data that is relevant to the user
exports.createMessageResponseObjects = function(marks, user) {
  var responseObjects = [];
  var responseObject;

  marks.forEach(function(mark) {
    responseObject = {
      timestamp: exports.getTimeElapsedSince(mark.timestamp),
      distance: exports.getDistanceFrom(mark, user),
      messageId: mark.messageId,
      messageString: mark.messageString,
      image: mark.image,
      imageH: mark.imageH,
      imageW: mark.imageW,
      score: mark.score,
      votes: mark['COUNT(distinct votes.id)'],
      comments: mark['COUNT(distinct comments.id)']
    };
    responseObjects.push(responseObject);
  });
  return responseObjects;
};

exports.createCommentResponseObjects = function(marks, user) {
  var responseObjects = [];
  var responseObject;

  marks.forEach(function(mark) {
    if (mark.id !== null) {
      responseObject = {
        timestamp: exports.getTimeElapsedSince(mark.timestamp),
        distance: exports.getDistanceFrom(mark, user),
        commentId: mark.commentId,
        commentString: mark.commentString,
        name: createIdentity(mark.userToken, user.messageId),
        votes: mark['COUNT(votes.id)']
      };
      responseObjects.push(responseObject);
    }
  });

  return responseObjects;
};

var hashCode = function(string) {
  var hash = 0;
  if (string.length == 0) return hash;
  for (i = 0; i < string.length; i++) {
    char = string.charCodeAt(i);
    hash = ((hash<<5)-hash)+char;
    hash = hash & hash;
  }
  return hash;
};

var createIdentity = function(userToken, messageId) {
  var identities = themes[0];
  var i = Math.abs(hashCode(userToken + messageId)) % (identities.length-1);
  return identities[i];
};

exports.saveImage = function(img64, callback) {
  if (img64) {
    var base64Data = img64.replace(/^data:image\/jpg;base64,/, '');
    var imgName = shortid.generate();
    var filename = 'server/images/' + imgName + '.jpg';

    fs.writeFile(filename, base64Data, 'base64', function(err) {
      if (err) console.log(err);
      if (callback) callback(imgName);
    });

    return imgName;
  } else {
    return null;
  }
};

exports.getImage = function(imgName) {
  return new Promise(function(resolve, reject) {
    var filename = 'server/images/' + imgName + '.jpg';
    fs.readFile(filename, function(err, img) {
      if (err) {
        reject(err);
      } else {
        resolve(img);
      }
    });
  });
};

exports.getLogStream = function() {
  var accessLogStream = fs.createWriteStream(__dirname + '/../log/access.log', {flags: 'a'});
  return {stream: accessLogStream};
};

exports.createQueryParams = function(obj) {
  var params = [];

  for (var k in obj) {
    params.push(k);
    params.push(obj[k]);
  }

  return params;
};

exports.rejectPOST = exports.rejectGET = function(req, res, err) {
  res.sendStatus(400);
};

exports.resolveGET = function(req, res, success) {
  res.status(200);
  res.send(success);
};

exports.resolvePOST = function(req, res, success) {
  res.sendStatus(201);
};
<|endoftext|>


<commit_before>var EYT = { // Functions Object.
    d: document,

    // Page scroll function.
    scroll: function (i, wrpr) {
        "use strict";
        var html = EYT.d.querySelectorAll("html")[0],
            b_ody = EYT.d.body,
            b_od = b_ody.getBoundingClientRect(),
            e_lm,
            top;

        if (!isNaN(i) && wrpr) {
            e_lm = wrpr[i].getBoundingClientRect();
            top = e_lm.top - b_od.top;
        } else {
            top = 0;
        }
        html.scrollTop = top;
        b_ody.scrollTop = top;
    },

    // Main functions here.
    init: function (container, object, dimensions, HF) {
        "use strict";
        var videos = object, // The video object input.
            ids = Object.keys(videos),
            aspect_ratio = dimensions.aspectRatio,
            header_content = HF.header || "
HULK
",
            footer_content = HF.footer || "
FOOTEY
",

            // ========================================================
            // YouTube
            url_base = "https://youtu.be/", // Short YT URL base link.
            url_embed_base = "https://www.youtube.com/embed/", // YT embed URL base
            url_image_base = "https://i.ytimg.com/vi/", // YT image URL base (front)
            url_image_base_end = "/0.jpg", // YT image URL base (back)
            // ========================================================

            iframes,
            btn_on,
            btn_off,
            wrpr,
            array = [],
            yt_url,
            ctnr = EYT.d.getElementById(container), // Container element.
            timmy_outer,
            UA = navigator.userAgent,

            // ========================================
            // CONTENT (iframe, buttons, and textarea).
            half_0 = '
' +
                        '
',
            half_1 = '
' +
                        '' +
                            '
' +
                                '
' +
                                    '<button type="button" class="player_on">PLAY</button>' +
                                    '<button type="button" class="player_off" disabled="1">' +
                                    'CLEAR</button>' +
                                    '<textarea style="display:none; opacity:0" ' +
                                        'rows="1" readonly="readonly" ' +
                                        'wrap="off" title="YouTube URL" ' +
                                        'onclick="this.select()" class="yt_url"></textarea>' +
                                '
' +
                            '
' +
                        '
',
            // ========================================

            // Nodelist to Array (function).
            t_a = function (a) {
                if (EYT.d.querySelectorAll(a).length > 0) {
                    return Array.prototype.slice.call(EYT.d.querySelectorAll(a));
                }
            },

            // Video *PLAY* (function).
            player_on = function (v, i) {
                iframes[i].src = url_embed_base +
                                    videos[ids[i]] +
                                    "?wmode=transparent" +
                                    "&modestbranding=1" +
                                    "&rel=0" +
                                    "&showinfo=0" +
                                    "&fs=0" +
                                    "&autoplay=1";
                /* ======================================================== |
                |   To learn the embedded YT player PARAMETERS, go to:      |
                |       developers.google.com/youtube/player_parameters     |
                | ======================================================== */

                iframes[i].style.backgroundImage = "";
                iframes[i].style.opacity = 1;

                wrpr[i].style.background = "#000";
                wrpr[i].style.color = "#fff";

                v.disabled = 1;

                if (timmy_outer) {
                    window.clearTimeout(timmy_outer);
                }

                btn_on.forEach(function (v, ii) {
                    if (ii !== i) {
                        v.disabled = 1;
                    }
                });
            },

            // Video *CLEAR* (function).
            player_off = function (v, i, enable_btn_off) {
                var interval,
                    counter = 0,
                    limit,
                    check_btn = function () {
                        counter += 1;

                        limit = UA.match(/firefox/gi)
                            ? 25
                            : 6;

                        if (counter < limit) {
                            if (!v.disabled) {
                                v.disabled = 1;
                            }

                            // ========================================================
                            // These get buggy on Firefox, therefore I re-declare them.
                            // The removing *EventListener* part.
                            if (iframes.src) { // Making sure.
                                iframes[i].src = "";
                            }
                            // Making sure.
                            iframes[i].removeEventListener("load", enable_btn_off, 0);
                            iframes[i].removeEventListener("error", enable_btn_off, 0);
                            // ========================================================

                            if (!iframes[i].style.backgroundImage) {
                                iframes[i].style
                                    .backgroundImage = "url(" +
                                                        url_image_base +
                                                        videos[ids[i]] +
                                                        url_image_base_end +
                                                        ")";
                            }

                            if (yt_url[i].style.opacity === 1) {
                                yt_url[i].style.opacity = 0;
                            }

                            if (yt_url[i].style.display === "block") {
                                yt_url[i].style.display = "none";
                            }

                            if (!UA.match(/firefox/gi)) {
                                if (iframes[i].style.opacity === 1) {
                                    iframes[i].style.opacity = 0.5;
                                }
                                if (wrpr[i].style.background && wrpr[i].style.color) {
                                    wrpr[i].style.background = "";
                                    wrpr[i].style.color = "";
                                }
                            }
                        } else {
                            if (UA.match(/firefox/gi)) {
                                if (iframes[i].style.opacity === 1) {
                                    iframes[i].style.opacity = 0.5;
                                }

                                if (wrpr[i].style.background && wrpr[i].style.color) {
                                    wrpr[i].style.background = "";
                                    wrpr[i].style.color = "";
                                }

                                if (btn_on[i].disabled) {
                                    btn_on.forEach(function (v) {
                                        v.disabled = 0;
                                    });
                                }
                            }
                            if (btn_on[i].disabled) {
                                btn_on.forEach(function (v) {
                                    v.disabled = 0;
                                });
                            }
                            window.clearInterval(interval);
                        }
                    };

                iframes[i].src = "";
                iframes[i].removeEventListener("load", enable_btn_off, 0);
                iframes[i].removeEventListener("error", enable_btn_off, 0);

                // Forcing button thing.
                interval = window.setInterval(check_btn, 100);
            },

            // Button click handler (function).
            clck = function (v, i) {
                var enable_btn_off = function () {
                    yt_url[i].style.display = "block";

                    timmy_outer = window.setTimeout(function () {
                        yt_url[i].style.opacity = 1;
                    }, 500);

                    btn_off[i].disabled = 0;
                };

                EYT.scroll(i, wrpr); // Page scroll.

                if (v.className === "player_on") { // *PLAY*.
                    iframes[i].addEventListener("load", enable_btn_off, 0);
                    iframes[i].addEventListener("error", enable_btn_off, 0);

                    player_on(v, i); // Go to *player_on* function.
                } else { // *CLEAR*.
                    player_off(v, i, enable_btn_off); // Go to *player_off* function.
                }
            },

            // Responsive iframes (function).
            rv = {
                w: window,
                css: function (a) {
                    return rv.w.getComputedStyle(a, null);
                },
                re_size: function (a) {
                    var all_properties,
                        height,
                        width,
                        default_height = dimensions.height + "px",
                        default_width = dimensions.width + "px",
                        window_width = rv.w.innerWidth,
                        add_30px = a.src
                            ? 30
                            : 0;

                    if (window_width < dimensions.width) {
                        a.forEach(function (v) {
                            v.style.width = "100%";
                        });

                        all_properties = rv.css(a[0]);
                        width = parseInt(all_properties.getPropertyValue("width"), 10);

                        height = Math.floor(width * (aspect_ratio)) + add_30px;
                        // The extra 30px is for the player control,
                        // only when the iframe has non-empty source attribute.

                        a.forEach(function (v) {
                            v.style.height = height + "px";
                        });
                    } else {
                        a.forEach(function (v) {
                            v.style.cssText += "height:" + default_height +
                                                ";width:" + default_width;
                        });
                    }
                }
            };

        /*|============= |*|
        |*|  INJECTION.  |*|
        |*| ============ |*/
        // [1] Header content definition.
        array.push(header_content);

        // [2] Body content (titles, iframes, buttons, and URL links) definition.
        ids.forEach(function (v) {
            array.push(half_0 + v + half_1);
        });

        // [3] Footer content definition.
        array.push(footer_content);

        // [4] Inject Header-Body-Footer into the container element.
        ctnr.innerHTML = array.join("");

        // [5] Define iframes, buttons, wrappers, and YT url containers.
        iframes = t_a(".yt_embed");
        btn_on = t_a(".player_on");
        btn_off = t_a(".player_off");
        wrpr = t_a(".yt_embed_wrap");
        yt_url = t_a(".yt_url");

        // [6] Loop using *iframes* reference.
        // The length of all 5 variables defined above are the same.
        iframes.forEach(function (v, i) {
            btn_on[i].onclick = function () { // Button *PLAY* click handler.
                clck(btn_on[i], i);
            };

            btn_off[i].onclick = function () { // Button *CLEAR* click handler.
                clck(btn_off[i], i);
            };

            // Set initial *background-image* on iframes.
            v.style.backgroundImage = 'url(https://i.ytimg.com/vi/' + videos[ids[i]] + '/0.jpg)';

            // Set value to YouTube URL textareas.
            yt_url[i].value = url_base + videos[ids[i]];
        });

        // ==============================================
        // RESPONSIVE IFRAMES MODULE INVOCATION (*rv* variable).
        rv.re_size(iframes);
        rv.w.addEventListener("resize", function () {
            rv.re_size(iframes);
        });
    }
};

/*|=========================|**
**| INITIALIZE THE FUNCTION |**
**|=========================|*/
// #[I] Initialize the main function.
EYT.init(
    // ======================= //
    // List of input arguments //
    // ======================= //

     /*| #[I.1] The container element's ID |*/
    "yt_embed_container",

    /*| #[I.2] Object                   |**
    **|    {"title": "video ID"} pairs. |**
    **|    Put as many as you want.     |*/
    {
        "Expressions": "arJtsvv6akc",
        "Dancing Zoidberg along with Minuet (Luigi Boccherini)": "ikl3hGEfSLc",
        "Knock Knock Joke": "rLwDNwkJqjY",
        "Babba's tribute to mainstream music": "8DTgMZP6f8U"
    },

    /*| #[I.3] Default dimensions and aspect ratio |*/
    {
        /*| #[I.3.a] Dimensions in pixels |*/
        "height": 360,
        "width": 640,

        /*| #[I.3.b] Aspect ratio |*/
        "aspectRatio": 9/16

        // It can be 3/4, or 1/2, up to you.
        // The largest number is the width ratio.
        // Put the smallest value in front: *small_number/big_number*.

        // This feature will work on screen which has narrower width than you define above.
    },

    /*| #[1.4] HEADER and FOOTER CONTENT |*/
    // Customize the HEADER and FOOTER CSS from the [style] tag above.
    // Header class: .header
    // Footer class: .footer
    {
        "header": "
" +
                "Multiple YouTube Embedded Videos
" +
                "Without YouTube JS API
" +
                "" +
                "For mobile player (flv), the " +
                "autoplay parameter (currently) doesn't work" +
                "" +
                "
",

        "footer": "
" +
                "
Template by Monkey Raptor
" +
                "
See page source | See source on GitHub
" +
                "
Updated May 28, 2015
" +
                "
<button type='button' class='scroller' onclick='EYT.scroll()'>" +
                "TOP</button>
" +
                "
"
    }
);

// #[II] Initialize scrolling to the top of the page.
/*| ============================================== |*|
|*|   Scroll to the top of the page on DOM load.   |*|
|*| ============================================== |*/
EYT.scroll();

// These lines below can be omitted (demo purpose only).
/*| ========================== |*|
|*|   EXTRA FUNC:              |*|
|*|     - Check if in iframe.  |*|
|*| ========================== |*/
var extra = {
        in_iframe: function () { // stackoverflow.com/a/326076
            "use strict";
            try {
                return window.self !== window.top;
            } catch (e) {
                if (e) {
                    return 1;
                }
            }
        },
        rmv_node: function (a, b) {
            "use strict";
            a.removeChild(b);
        }
    },
    footer = document.querySelectorAll(".footer")[0],
    h3_elm = footer.childNodes[0],
    vsource_elm = footer.childNodes[1];

if (extra.in_iframe()) {
    extra.rmv_node(footer, h3_elm);
    extra.rmv_node(footer, vsource_elm);
}
<commit_msg>Added line 194<commit_after>var EYT = { // Functions Object.
    d: document,

    // Page scroll function.
    scroll: function (i, wrpr) {
        "use strict";
        var html = EYT.d.querySelectorAll("html")[0],
            b_ody = EYT.d.body,
            b_od = b_ody.getBoundingClientRect(),
            e_lm,
            top;

        if (!isNaN(i) && wrpr) {
            e_lm = wrpr[i].getBoundingClientRect();
            top = e_lm.top - b_od.top;
        } else {
            top = 0;
        }
        html.scrollTop = top;
        b_ody.scrollTop = top;
    },

    // Main functions here.
    init: function (container, object, dimensions, HF) {
        "use strict";
        var videos = object, // The video object input.
            ids = Object.keys(videos),
            aspect_ratio = dimensions.aspectRatio,
            header_content = HF.header || "
HULK
",
            footer_content = HF.footer || "
FOOTEY
",

            // ========================================================
            // YouTube
            url_base = "https://youtu.be/", // Short YT URL base link.
            url_embed_base = "https://www.youtube.com/embed/", // YT embed URL base
            url_image_base = "https://i.ytimg.com/vi/", // YT image URL base (front)
            url_image_base_end = "/0.jpg", // YT image URL base (back)
            // ========================================================

            iframes,
            btn_on,
            btn_off,
            wrpr,
            array = [],
            yt_url,
            ctnr = EYT.d.getElementById(container), // Container element.
            timmy_outer,
            UA = navigator.userAgent,

            // ========================================
            // CONTENT (iframe, buttons, and textarea).
            half_0 = '
' +
                        '
',
            half_1 = '
' +
                        '' +
                            '
' +
                                '
' +
                                    '<button type="button" class="player_on">PLAY</button>' +
                                    '<button type="button" class="player_off" disabled="1">' +
                                    'CLEAR</button>' +
                                    '<textarea style="display:none; opacity:0" ' +
                                        'rows="1" readonly="readonly" ' +
                                        'wrap="off" title="YouTube URL" ' +
                                        'onclick="this.select()" class="yt_url"></textarea>' +
                                '
' +
                            '
' +
                        '
',
            // ========================================

            // Nodelist to Array (function).
            t_a = function (a) {
                if (EYT.d.querySelectorAll(a).length > 0) {
                    return Array.prototype.slice.call(EYT.d.querySelectorAll(a));
                }
            },

            // Video *PLAY* (function).
            player_on = function (v, i) {
                iframes[i].src = url_embed_base +
                                    videos[ids[i]] +
                                    "?wmode=transparent" +
                                    "&modestbranding=1" +
                                    "&rel=0" +
                                    "&showinfo=0" +
                                    "&fs=0" +
                                    "&autoplay=1";
                /* ======================================================== |
                |   To learn the embedded YT player PARAMETERS, go to:      |
                |       developers.google.com/youtube/player_parameters     |
                | ======================================================== */

                iframes[i].style.backgroundImage = "";
                iframes[i].style.opacity = 1;

                wrpr[i].style.background = "#000";
                wrpr[i].style.color = "#fff";

                v.disabled = 1;

                if (timmy_outer) {
                    window.clearTimeout(timmy_outer);
                }

                btn_on.forEach(function (v, ii) {
                    if (ii !== i) {
                        v.disabled = 1;
                    }
                });
            },

            // Video *CLEAR* (function).
            player_off = function (v, i, enable_btn_off) {
                var interval,
                    counter = 0,
                    limit,
                    check_btn = function () {
                        counter += 1;

                        limit = UA.match(/firefox/gi)
                            ? 25
                            : 6;

                        if (counter < limit) {
                            if (!v.disabled) {
                                v.disabled = 1;
                            }

                            // ========================================================
                            // These get buggy on Firefox, therefore I re-declare them.
                            // The removing *EventListener* part.
                            if (iframes.src) { // Making sure.
                                iframes[i].src = "";
                            }
                            // Making sure.
                            iframes[i].removeEventListener("load", enable_btn_off, 0);
                            iframes[i].removeEventListener("error", enable_btn_off, 0);
                            // ========================================================

                            if (!iframes[i].style.backgroundImage) {
                                iframes[i].style
                                    .backgroundImage = "url(" +
                                                        url_image_base +
                                                        videos[ids[i]] +
                                                        url_image_base_end +
                                                        ")";
                            }

                            if (yt_url[i].style.opacity === 1) {
                                yt_url[i].style.opacity = 0;
                            }

                            if (yt_url[i].style.display === "block") {
                                yt_url[i].style.display = "none";
                            }

                            if (!UA.match(/firefox/gi)) {
                                if (iframes[i].style.opacity === 1) {
                                    iframes[i].style.opacity = 0.5;
                                }
                                if (wrpr[i].style.background && wrpr[i].style.color) {
                                    wrpr[i].style.background = "";
                                    wrpr[i].style.color = "";
                                }
                            }
                        } else {
                            if (UA.match(/firefox/gi)) {
                                if (iframes[i].style.opacity === 1) {
                                    iframes[i].style.opacity = 0.5;
                                }

                                if (wrpr[i].style.background && wrpr[i].style.color) {
                                    wrpr[i].style.background = "";
                                    wrpr[i].style.color = "";
                                }

                                if (btn_on[i].disabled) {
                                    btn_on.forEach(function (v) {
                                        v.disabled = 0;
                                    });
                                }
                            }
                            if (btn_on[i].disabled) {
                                btn_on.forEach(function (v) {
                                    v.disabled = 0;
                                });
                            }
                            window.clearInterval(interval);
                        }
                    };

                iframes[i].src = "";
                iframes[i].removeEventListener("load", enable_btn_off, 0);
                iframes[i].removeEventListener("error", enable_btn_off, 0);
                iframes[i].style.opacity = 0.5;

                // Forcing button thing.
                interval = window.setInterval(check_btn, 100);
            },

            // Button click handler (function).
            clck = function (v, i) {
                var enable_btn_off = function () {
                    yt_url[i].style.display = "block";

                    timmy_outer = window.setTimeout(function () {
                        yt_url[i].style.opacity = 1;
                    }, 500);

                    btn_off[i].disabled = 0;
                };

                EYT.scroll(i, wrpr); // Page scroll.

                if (v.className === "player_on") { // *PLAY*.
                    iframes[i].addEventListener("load", enable_btn_off, 0);
                    iframes[i].addEventListener("error", enable_btn_off, 0);

                    player_on(v, i); // Go to *player_on* function.
                } else { // *CLEAR*.
                    player_off(v, i, enable_btn_off); // Go to *player_off* function.
                }
            },

            // Responsive iframes (function).
            rv = {
                w: window,
                css: function (a) {
                    return rv.w.getComputedStyle(a, null);
                },
                re_size: function (a) {
                    var all_properties,
                        height,
                        width,
                        default_height = dimensions.height + "px",
                        default_width = dimensions.width + "px",
                        window_width = rv.w.innerWidth,
                        add_30px = a.src
                            ? 30
                            : 0;

                    if (window_width < dimensions.width) {
                        a.forEach(function (v) {
                            v.style.width = "100%";
                        });

                        all_properties = rv.css(a[0]);
                        width = parseInt(all_properties.getPropertyValue("width"), 10);

                        height = Math.floor(width * (aspect_ratio)) + add_30px;
                        // The extra 30px is for the player control,
                        // only when the iframe has non-empty source attribute.

                        a.forEach(function (v) {
                            v.style.height = height + "px";
                        });
                    } else {
                        a.forEach(function (v) {
                            v.style.cssText += "height:" + default_height +
                                                ";width:" + default_width;
                        });
                    }
                }
            };

        /*|============= |*|
        |*|  INJECTION.  |*|
        |*| ============ |*/
        // [1] Header content definition.
        array.push(header_content);

        // [2] Body content (titles, iframes, buttons, and URL links) definition.
        ids.forEach(function (v) {
            array.push(half_0 + v + half_1);
        });

        // [3] Footer content definition.
        array.push(footer_content);

        // [4] Inject Header-Body-Footer into the container element.
        ctnr.innerHTML = array.join("");

        // [5] Define iframes, buttons, wrappers, and YT url containers.
        iframes = t_a(".yt_embed");
        btn_on = t_a(".player_on");
        btn_off = t_a(".player_off");
        wrpr = t_a(".yt_embed_wrap");
        yt_url = t_a(".yt_url");

        // [6] Loop using *iframes* reference.
        // The length of all 5 variables defined above are the same.
        iframes.forEach(function (v, i) {
            btn_on[i].onclick = function () { // Button *PLAY* click handler.
                clck(btn_on[i], i);
            };

            btn_off[i].onclick = function () { // Button *CLEAR* click handler.
                clck(btn_off[i], i);
            };

            // Set initial *background-image* on iframes.
            v.style.backgroundImage = 'url(https://i.ytimg.com/vi/' + videos[ids[i]] + '/0.jpg)';

            // Set value to YouTube URL textareas.
            yt_url[i].value = url_base + videos[ids[i]];
        });

        // ==============================================
        // RESPONSIVE IFRAMES MODULE INVOCATION (*rv* variable).
        rv.re_size(iframes);
        rv.w.addEventListener("resize", function () {
            rv.re_size(iframes);
        });
    }
};

/*|=========================|**
**| INITIALIZE THE FUNCTION |**
**|=========================|*/
// #[I] Initialize the main function.
EYT.init(
    // ======================= //
    // List of input arguments //
    // ======================= //

     /*| #[I.1] The container element's ID |*/
    "yt_embed_container",

    /*| #[I.2] Object                   |**
    **|    {"title": "video ID"} pairs. |**
    **|    Put as many as you want.     |*/
    {
        "Expressions": "arJtsvv6akc",
        "Dancing Zoidberg along with Minuet (Luigi Boccherini)": "ikl3hGEfSLc",
        "Knock Knock Joke": "rLwDNwkJqjY",
        "Babba's tribute to mainstream music": "8DTgMZP6f8U"
    },

    /*| #[I.3] Default dimensions and aspect ratio |*/
    {
        /*| #[I.3.a] Dimensions in pixels |*/
        "height": 360,
        "width": 640,

        /*| #[I.3.b] Aspect ratio |*/
        "aspectRatio": 9/16

        // It can be 3/4, or 1/2, up to you.
        // The largest number is the width ratio.
        // Put the smallest value in front: *small_number/big_number*.

        // This feature will work on screen which has narrower width than you define above.
    },

    /*| #[1.4] HEADER and FOOTER CONTENT |*/
    // Customize the HEADER and FOOTER CSS from the [style] tag above.
    // Header class: .header
    // Footer class: .footer
    {
        "header": "
" +
                "Multiple YouTube Embedded Videos
" +
                "Without YouTube JS API
" +
                "" +
                "For mobile player (flv), the " +
                "autoplay parameter (currently) doesn't work" +
                "" +
                "
",

        "footer": "
" +
                "
Template by Monkey Raptor
" +
                "
See page source | See source on GitHub
" +
                "
Updated May 28, 2015
" +
                "
<button type='button' class='scroller' onclick='EYT.scroll()'>" +
                "TOP</button>
" +
                "
"
    }
);

// #[II] Initialize scrolling to the top of the page.
/*| ============================================== |*|
|*|   Scroll to the top of the page on DOM load.   |*|
|*| ============================================== |*/
EYT.scroll();

// These lines below can be omitted (demo purpose only).
/*| ========================== |*|
|*|   EXTRA FUNC:              |*|
|*|     - Check if in iframe.  |*|
|*| ========================== |*/
var extra = {
        in_iframe: function () { // stackoverflow.com/a/326076
            "use strict";
            try {
                return window.self !== window.top;
            } catch (e) {
                if (e) {
                    return 1;
                }
            }
        },
        rmv_node: function (a, b) {
            "use strict";
            a.removeChild(b);
        }
    },
    footer = document.querySelectorAll(".footer")[0],
    h3_elm = footer.childNodes[0],
    vsource_elm = footer.childNodes[1];

if (extra.in_iframe()) {
    extra.rmv_node(footer, h3_elm);
    extra.rmv_node(footer, vsource_elm);
}
<|endoftext|>


<commit_before><commit_msg>FIX Provisioning handler raising errors<commit_after><|endoftext|>


<commit_before>var MongoClient = require('mongodb').MongoClient;

var config = require('../../config.json');

/**
 * Get latest talks
 * @param quantity  Number of talks to get
 * @param callback  Callback to execute, receives a list of talk json objects
 */
exports.latest = function (quantity, callback) {
    MongoClient.connect(config.mongodb, function(err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.find({}).sort({id: -1}).limit(quantity).toArray(function(err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Get popular talks
 * @param callback  Callback to execute, receives a list of talk json objects
 */
exports.popular = function (quantity, callback) {
    MongoClient.connect(config.mongodb, function(err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.find({}).sort({views: -1}).limit(quantity).toArray(function(err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Create a talk
 * @param talk      Talk json object
 * @param callback  Callback to execute, receives talk json object
 */
exports.create = function (talk, callback) {
    MongoClient.connect(config.mongodb, function(err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.insert(talk, function (err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Get a talk by its ID
 * @param id        Talk id
 * @param callback  Callback to execute, receives talk json object
 */
exports.get = function (id, callback) {
    MongoClient.connect(config.mongodb, function(err, db) {
        var talks = db.collection('talks');
        talks.findOne({"id": id}, function (err, talk) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, talk);
        });
    });
};

/**
 * Play a talk
 * Updates views field by 1.
 * @param id        Talk id
 * @param callback  Callback to execute, receives talk json object
 */
exports.play = function (id, callback) {
    MongoClient.connect(config.mongodb, function(err, db) {
        var talks = db.collection('talks');
        talks.findOne({"id": id}, function (err, talk) {
            if (err) {
                return callback(err, null);
            }
            talk.views = talk.views+1;
            talks.update({"id": id}, talk, function (err) {
                if (err) {
                    return callback(err, null);
                }
                db.close();
                callback(null, talk);
            });
        });
    });
};<commit_msg>Reformat code<commit_after>var MongoClient = require('mongodb').MongoClient;

var config = require('../../config.json');

/**
 * Get latest talks
 * @param quantity  Number of talks to get
 * @param callback  Callback to execute, receives a list of talk json objects
 */
exports.latest = function (quantity, callback) {
    MongoClient.connect(config.mongodb, function (err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.find({}).sort({id: -1}).limit(quantity).toArray(function (err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Get popular talks
 * @param callback  Callback to execute, receives a list of talk json objects
 */
exports.popular = function (quantity, callback) {
    MongoClient.connect(config.mongodb, function (err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.find({}).sort({views: -1}).limit(quantity).toArray(function (err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Create a talk
 * @param talk      Talk json object
 * @param callback  Callback to execute, receives talk json object
 */
exports.create = function (talk, callback) {
    MongoClient.connect(config.mongodb, function (err, db) {
        if (err) {
            return callback(err, null);
        }
        var talks = db.collection('talks');
        talks.insert(talk, function (err, docs) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, docs);
        });
    });
};

/**
 * Get a talk by its ID
 * @param id        Talk id
 * @param callback  Callback to execute, receives talk json object
 */
exports.get = function (id, callback) {
    MongoClient.connect(config.mongodb, function (err, db) {
        var talks = db.collection('talks');
        talks.findOne({"id": id}, function (err, talk) {
            if (err) {
                return callback(err, null);
            }
            db.close();
            callback(null, talk);
        });
    });
};

/**
 * Play a talk
 * Updates views field by 1.
 * @param id        Talk id
 * @param callback  Callback to execute, receives talk json object
 */
exports.play = function (id, callback) {
    MongoClient.connect(config.mongodb, function (err, db) {
        var talks = db.collection('talks');
        talks.findOne({"id": id}, function (err, talk) {
            if (err) {
                return callback(err, null);
            }
            talk.views = talk.views + 1;
            talks.update({"id": id}, talk, function (err) {
                if (err) {
                    return callback(err, null);
                }
                db.close();
                callback(null, talk);
            });
        });
    });
};<|endoftext|>


<commit_before>var Discord = require("discord.js");
var config = require("./config");

var client = new Discord.Client();
var botUser;

client.on("message", function(message) {
	if(message.content.toLowerCase().indexOf("hello") > -1 && message.isMentioned(botUser)) {
		var msg =  "Hello " + message.author;
		client.sendMessage(message.channel, 'Hello ' + message.author);
	}

	if(message.content.charAt(0) == config.cmdprefix) {
		switch(message.content.substring(1)){
			case 'ping':
				client.reply(message, "pong");
				break;
			case 'help':
				client.sendMessage(message.channel, "You need help " + message.author);
				break;
			case 'bh':
				playBennyHill(message.author.voiceChannel);
				break;
		}
	}
});

//Hilarity ensues
function playBennyHill(voiceChannel) {
	if(voiceChannel != null) {
		client.joinVoiceChannel(voiceChannel, function(error, voiceConnection){
			if(error) {
				return console.error(error);
			}
			voiceConnection.playFile("sound.mp3", function(error, intent) {
				if(error) {
					return console.error(error);
				}
				intent.on("error", function(error) {
					return console.error(error);
				});
				intent.once("end", function() {
					client.leaveVoiceChannel(voiceConnection);
				});
			});
		});
	}
}

//Called once the bot is logged in and ready to use.
client.on("ready", function() {
	client.setPlayingGame("with your emotions");
	botUser = client.users.get("username", "DeixBot");
	for (var i = 0; i < client.servers.length; i++) {
		var server = client.servers[i];
		var msg = "S'up " + server.name + "!";
		client.sendMessage(server.defaultChannel, msg);
	}
});

//Handle a CTRL+C to actually shutdown somewhat cleanly
process.on("SIGINT", function() {
	for (var i = 0; i < client.servers.length; i++){
		var server = client.servers[i];
		client.sendMessage(server.defaultChannel, "Peace out!", function(i){
			if(i + 1 == client.servers.length){
				client.logout();
			}
		});
	}
});

client.loginWithToken(config.discord.key);
<commit_msg>Added humming and blaming Yury<commit_after>var Discord = require("discord.js");
var config = require("./config");

var client = new Discord.Client();
var botUser;

client.on("message", function(message) {
	if(message.content.toLowerCase().indexOf("hello") > -1 && message.isMentioned(botUser)) {
		return client.sendMessage(message.channel, 'Hello ' + message.author);
	}
	else if(message.content.toLowerCase().indexOf("who gta") > -1) {
		return message.reply("oooh oooh me! I'll play!")
	}

	else if(message.content.charAt(0) == config.cmdprefix) {
		switch(message.content.substring(1)){
			case 'ping':
				client.reply(message, "pong");
				break;
			case 'help':
				client.sendMessage(message.channel, "You need help " + message.author);
				break;
			case 'bh':
				playBennyHill(message);
				break;
			case 'blame':
				client.sendMessage(message.channel("I blame Yury"));
				break;
		}
	}
});

//Hilarity ensues
function playBennyHill(message) {
	var voiceChannel = message.author.voiceChannel;
	if(voiceChannel != null) {
		client.joinVoiceChannel(voiceChannel, function(error, voiceConnection){
			if(error) {
				return console.error(error);
			}
			voiceConnection.playFile("sound.mp3", function(error, intent) {
				if(error) {
					return console.error(error);
				}
				intent.on("error", function(error) {
					return console.error(error);
				});
				intent.once("end", function() {
					client.leaveVoiceChannel(voiceConnection);
				});
			});
		});
	}
	else {
		client.sendMessage(message.channel, "*starts humming*");
	}
}

//Called once the bot is logged in and ready to use.
client.on("ready", function() {
	client.setPlayingGame("with your emotions");
	botUser = client.users.get("username", "DeixBot");
	for (var i = 0; i < client.servers.length; i++) {
		var server = client.servers[i];
		var msg = "S'up " + server.name + "!";
		client.sendMessage(server.defaultChannel, msg);
	}
});

//Handle a CTRL+C to actually shutdown somewhat cleanly
process.on("SIGINT", function() {
	for (var i = 0; i < client.servers.length; i++){
		var server = client.servers[i];
		client.sendMessage(server.defaultChannel, "Peace out!", function(i){
			if(i + 1 == client.servers.length){
				client.logout();
			}
		});
	}
});

client.loginWithToken(config.discord.key);
<|endoftext|>


<commit_before>// @flow
import type { Action } from '../types';
import type { AppError } from '../lib/appError';

// Can't be exact type yet. Flow will fix it soon.
export type AppState = {
  +baselineShown: boolean,
  +darkEnabled: boolean,
  +defaultLocale: string,
  +error: ?AppError,
  +locale: string,
  +name: string,
  +supportedLocales: Array<string>,
  +version: string,
};

// This is defined by server in app.js
const initialState = {
  error: null,
  baselineShown: false,
  darkEnabled: false,
  defaultLocale: 'en',
  locale: 'en',
  name: '',
  supportedLocales: ['en'],
  version: '',
};

const reducer = (state: AppState = initialState, action: Action): AppState => {
  switch (action.type) {
    case 'APP_ERROR':
      return { ...state, error: action };
    case 'TOGGLE_BASELINE':
      return { ...state, baselineShown: !state.baselineShown };
    case 'TOGGLE_DARK':
      return { ...state, darkEnabled: !state.darkEnabled };
    default:
      return state;
  }
};

export default reducer;
<commit_msg>Close #1386<commit_after>// @flow
import type { Action } from '../types';
import type { AppError } from '../lib/appError';

export type AppState = {
  +baselineShown: boolean,
  +darkEnabled: boolean,
  +defaultLocale: string,
  +error: ?AppError,
  +locale: string,
  +name: string,
  +supportedLocales: Array<string>,
  +version: string,
};

// This is defined by server in app.js
const initialState = {
  error: null,
  baselineShown: false,
  darkEnabled: false,
  defaultLocale: 'en',
  locale: 'en',
  name: '',
  supportedLocales: ['en'],
  version: '',
};

const reducer = (state: AppState = initialState, action: Action): AppState => {
  switch (action.type) {
    case 'APP_ERROR':
      return { ...state, error: action };
    case 'TOGGLE_BASELINE':
      return { ...state, baselineShown: !state.baselineShown };
    case 'TOGGLE_DARK':
      return { ...state, darkEnabled: !state.darkEnabled };
    default:
      return state;
  }
};

export default reducer;
<|endoftext|>


<commit_before>/**
 * Tests descriptions are written using the following pattern:
 *
 *  describe(label, function () {
 *
 *      it(testLabel, function () {
 *          // Test code, use assert function to validate a boolean condition
 *          assert(true);
 *      });
 *
 *  });
 */

describe("sinon", function () {
    "use strict";

    describe("US1", function () {

        it("is accessible through sinon.spy", function () {
            assert("function" === typeof sinon.spy);
        });

        it("accepts no parameter", function () {
            sinon.spy();
        });

        it("accepts a function parameter", function () {
            sinon.spy(function () {});
        });

        [
            true,
            42,
            "Hello World!",
            new Date()
        ].forEach(function (value) {
            it("rejects any other parameter - " + typeof value + " (" + value.toString() + ")", function () {
                var exceptionCaught;
                try {
                    sinon.spy(value);
                } catch (e) {
                    exceptionCaught = e;
                }
                assert(undefined !== exceptionCaught);
            });

        });

        it("returns a function", function () {
            assert("function" === typeof sinon.spy(function () {}));
        });

        it("returns a function - no parameter", function () {
            assert("function" === typeof sinon.spy());
        });

        it("returns a function that behaves like the parameter", function () {
            function test () {
                return 1;
            }
            var spiedTest = sinon.spy(test);
            assert(spiedTest() === test());
        });

        it("returns a function that behaves like the parameter - parameters passing", function () {
            function test () {
                var sum = 0,
                    len = arguments.length,
                    idx;
                for (idx = 0; idx < len; ++idx) {
                    sum += arguments[idx];
                }
                return sum;
            }
            var spiedTest = sinon.spy(test);
            assert(spiedTest(1, 2, 3) === test(1, 2, 3));
        });

        it("returns a function that does nothing when no parameter was specified", function () {
            var spiedTest = sinon.spy();
            assert(undefined === spiedTest());
            assert(undefined === spiedTest(1));
            assert(undefined === spiedTest(1, 2));
            assert(undefined === spiedTest(1, 2, 3));
        });

        it("forwards this", function () {
            var obj = {
                method: function () {
                    assert(this === obj);
                }
            };
            obj.method = sinon.spy(obj.method);
            obj.method();
        });

    });

    describe("US2", function () {

        // function verify (spiedTest, expectedCallCount)
        function generateTests (verify) {
            it("was never called", function () {
                var spiedTest = sinon.spy();
                assert(verify(spiedTest, 0));
            });

            it("was called once", function () {
                var spiedTest = sinon.spy();
                spiedTest();
                assert(verify(spiedTest, 1));
            });

            var COUNT = 10;

            it("was called " + COUNT + " times - synchronously", function () {
                var spiedTest = sinon.spy(),
                    count = COUNT;
                while (count--) {
                    spiedTest();
                }
                assert(verify(spiedTest, COUNT));
            });

            it("was called " + COUNT + " times - asynchronously", function (done) {
                var spiedTest = sinon.spy(),
                    count = COUNT,
                    promises = [];
                function getPromise () {
                    return new Promise(function (resolve/*, reject*/) {
                        setTimeout(function () {
                            spiedTest();
                            resolve();
                        }, 10);
                    });
                }
                while (count--) {
                    promises.push(getPromise());
                }
                Promise.all(promises).then(function () {
                    Promise.all(promises).then(function () {
                        try {
                            assert(verify(spiedTest, COUNT));
                            done();
                        } catch (e) {
                            done(e);
                        }
                    });
                });
            });
        }

        describe("it exposes the property \"called\" the indicates if the function was called", function () {

            generateTests(function (spiedTest, expectedCallCount) {
                return 0 !== expectedCallCount === spiedTest.called;
            });

        });

        describe("it exposes the property \"callCount\" that indicates how often the function was called", function () {

            generateTests(function (spiedTest, expectedCallCount) {
                return expectedCallCount === spiedTest.callCount;
            });

        });

    });

});
<commit_msg>Renamed this test<commit_after>/**
 * Tests descriptions are written using the following pattern:
 *
 *  describe(label, function () {
 *
 *      it(testLabel, function () {
 *          // Test code, use assert function to validate a boolean condition
 *          assert(true);
 *      });
 *
 *  });
 */

describe("sinon.spy", function () {
    "use strict";

    describe("US1", function () {

        it("is accessible through sinon.spy", function () {
            assert("function" === typeof sinon.spy);
        });

        it("accepts no parameter", function () {
            sinon.spy();
        });

        it("accepts a function parameter", function () {
            sinon.spy(function () {});
        });

        [
            true,
            42,
            "Hello World!",
            new Date()
        ].forEach(function (value) {
            it("rejects any other parameter - " + typeof value + " (" + value.toString() + ")", function () {
                var exceptionCaught;
                try {
                    sinon.spy(value);
                } catch (e) {
                    exceptionCaught = e;
                }
                assert(undefined !== exceptionCaught);
            });

        });

        it("returns a function", function () {
            assert("function" === typeof sinon.spy(function () {}));
        });

        it("returns a function - no parameter", function () {
            assert("function" === typeof sinon.spy());
        });

        it("returns a function that behaves like the parameter", function () {
            function test () {
                return 1;
            }
            var spiedTest = sinon.spy(test);
            assert(spiedTest() === test());
        });

        it("returns a function that behaves like the parameter - parameters passing", function () {
            function test () {
                var sum = 0,
                    len = arguments.length,
                    idx;
                for (idx = 0; idx < len; ++idx) {
                    sum += arguments[idx];
                }
                return sum;
            }
            var spiedTest = sinon.spy(test);
            assert(spiedTest(1, 2, 3) === test(1, 2, 3));
        });

        it("returns a function that behaves like the parameter - forwards this", function () {
            var obj = {
                method: function () {
                    assert(this === obj);
                }
            };
            obj.method = sinon.spy(obj.method);
            obj.method();
        });

        it("returns a function that does nothing when no parameter was specified", function () {
            var spiedTest = sinon.spy();
            assert(undefined === spiedTest());
            assert(undefined === spiedTest(1));
            assert(undefined === spiedTest(1, 2));
            assert(undefined === spiedTest(1, 2, 3));
        });

    });

    describe("US2", function () {

        // function verify (spiedTest, expectedCallCount)
        function generateTests (verify) {
            it("was never called", function () {
                var spiedTest = sinon.spy();
                assert(verify(spiedTest, 0));
            });

            it("was called once", function () {
                var spiedTest = sinon.spy();
                spiedTest();
                assert(verify(spiedTest, 1));
            });

            var COUNT = 10;

            it("was called " + COUNT + " times - synchronously", function () {
                var spiedTest = sinon.spy(),
                    count = COUNT;
                while (count--) {
                    spiedTest();
                }
                assert(verify(spiedTest, COUNT));
            });

            it("was called " + COUNT + " times - asynchronously", function (done) {
                var spiedTest = sinon.spy(),
                    count = COUNT,
                    promises = [];
                function getPromise () {
                    return new Promise(function (resolve/*, reject*/) {
                        setTimeout(function () {
                            spiedTest();
                            resolve();
                        }, 10);
                    });
                }
                while (count--) {
                    promises.push(getPromise());
                }
                Promise.all(promises).then(function () {
                    Promise.all(promises).then(function () {
                        try {
                            assert(verify(spiedTest, COUNT));
                            done();
                        } catch (e) {
                            done(e);
                        }
                    });
                });
            });
        }

        describe("it exposes the property \"called\" the indicates if the function was called", function () {

            generateTests(function (spiedTest, expectedCallCount) {
                return 0 !== expectedCallCount === spiedTest.called;
            });

        });

        describe("it exposes the property \"callCount\" that indicates how often the function was called", function () {

            generateTests(function (spiedTest, expectedCallCount) {
                return expectedCallCount === spiedTest.callCount;
            });

        });

    });

});
<|endoftext|>


<commit_before><commit_msg>chore(auth) rm Util<commit_after><|endoftext|>


<commit_before>'use strict';
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { dbLog } from '../db/dbLog';
import { dbInstantMessage } from '../db/dbInstantMessage';
import { dbResourceLock } from '../db/dbResourceLock';
import { threadId } from './thread';

Meteor.startup(function() {
  Meteor.setInterval(handleInstantMessage, 5000);
});

function handleInstantMessage() {
  try {
    const instantMessageBulk = dbInstantMessage.rawCollection().initializeUnorderedBulkOp();
    let needExecute = false;
    dbResourceLock.insert({
      _id: 'instantMessage',
      threadId: threadId,
      task: 'handleInstantMessage',
      time: new Date()
    });
    const logIdList = [];
    dbLog
      .find(
        {
          resolve: false
        },
        {
          disableOplog: true
        }
      )
      .forEach((log) => {
        logIdList.push(log._id);
        needExecute = true;
        const instantMessage = {
          type: log.logType,
          createdAt: log.createdAt,
          onlyForUsers: [],
          source: '!'
        };
        switch (log.logType) {
          case '驗證通過': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = log.username[0] + '的帳號驗證通過，領取起始資金$' + log.price + '。';
            break;
          }
          case '發薪紀錄': {
            instantMessage.message = '系統向所有已驗證通過的使用者發給了' + log.price + '的薪水！';
            break;
          }
          case '創立公司': {
            instantMessage.message = log.username[0] + '發起了「' + log.companyName + '」的新公司創立計劃，誠意邀請有意者投資！';
            break;
          }
          case '參與投資': {
            instantMessage.message = log.username[0] + '向「' + log.companyName + '公司創立計劃」投資了$' + log.amount + '！';
            break;
          }
          case '創立失敗': {
            instantMessage.message = log.username.join('、') + '等人投資的「' + log.companyName + '公司創立計劃」由於投資人數不足失敗了，投資金額將全數返回！';
            break;
          }
          case '創立成功': {
            instantMessage.message = log.username.join('、') + '等人投資的「' + log.companyName + '公司創立計劃」成功了，該公司正式上市，初始股價為$' + log.price + '！';
            break;
          }
          case '創立得股': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '對「' + log.companyName + '公司創立計劃」的投資為你帶來了' + log.amount + '數量的公司股票！';
            break;
          }
          case '購買下單': {
            instantMessage.message = log.username[0] + '想要用每股$' + log.price + '的單價購買' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '販賣下單': {
            instantMessage.message = log.username[0] + '想要用每股$' + log.price + '的單價販賣' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '取消下單': {
            instantMessage.message = log.username[0] + '取消了以每股$' + log.price + '的單價' + log.message + log.amount + '數量的「' + log.companyName + '」公司股票的訂單！';
            break;
          }
          case '訂單完成': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '您以每股$' + log.price + '的單價' + log.message + log.amount + '數量的「' + log.companyName + '」公司股票的訂單已經全數交易完畢！';
            break;
          }
          case '公司釋股': {
            instantMessage.message = '由於股價持續高漲，「' + log.companyName + '」公司以$' + log.price + '的價格釋出了' + log.amount + '數量的股票到市場上以套取利潤！';
            break;
          }
          case '交易紀錄': {
            instantMessage.message = log.username[0] + '以$' + log.price + '的單價向' + (log.username[1] || '「companyName」公司') + '購買了' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '辭職紀錄': {
            instantMessage.message = log.username[0] + '辭去了「' + log.companyName + '」公司的經理人職務！';
            break;
          }
          case '參選紀錄': {
            instantMessage.message = log.username[0] + '開始競選「' + log.companyName + '」公司的經理人職務！';
            break;
          }
          case '經理管理': {
            instantMessage.message = log.username[0] + '修改了「' + log.companyName + '」公司的資訊！';
            break;
          }
          case '推薦產品': {
            instantMessage.message = log.username[0] + '向「' + log.companyName + '」公司的一項產品投了一張推薦票，使其獲得了$' + log.price + '的營利額！';
            break;
          }
          //支持紀錄不進即時訊息
          case '支持紀錄': {
            return false;
          }
          case '就任經理': {
            instantMessage.message = log.username[0] + '在' + log.message + '商業季度' + (log.amount ? '以' + log.amount + '數量的支持股份' : '') + '擊敗了所有競爭對手，' + (log.username[1] === '!none' ? '' : '取代' + log.username[1]) + '成為「' + log.companyName + '」公司的經理人！';
            break;
          }
          case '公司營利': {
            instantMessage.message = '「' + log.companyName + '」公司在本商業季度一共獲利$' + log.amount + '！';
            break;
          }
          case '營利分紅': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '你得到了「' + log.companyName + '」公司的分紅$' + log.amount + '！';
            break;
          }
          case '舉報公司': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由舉報了「' + log.companyName + '」公司！';
            break;
          }
          case '舉報產品': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由舉報了「' + log.companyName + '」公司的#' + log.productId + '產品！';
            break;
          }
          case '公司撤銷': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由撤銷了「' + log.companyName + '」公司！';
            break;
          }
          case '取消資格': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由取消了' + log.username[1] + '擔任經理人的資格！';
            break;
          }
          //免費得石不進即時訊息
          case '免費得石': {
            return false;
          }
        }
        instantMessageBulk.insert(instantMessage);
      })
    //清除一分鐘前的即時訊息
    dbInstantMessage.remove({
      createdAt: {
        $lt: new Date( Date.now() - 60000)
      }
    });
    if (needExecute) {
      dbLog.update(
        {
          _id: {
            $in: logIdList
          }
        },
        {
          $set: {
            resolve: true
          }
        },
        {
          multi: true
        }
      );
      instantMessageBulk.execute();
    }
  }
  catch (e) {
    throw e;
  }
  finally {
    dbResourceLock.remove('instantMessage');
  }
}
<commit_msg>eslint<commit_after>'use strict';
import { Meteor } from 'meteor/meteor';
import { dbLog } from '../db/dbLog';
import { dbInstantMessage } from '../db/dbInstantMessage';
import { dbResourceLock } from '../db/dbResourceLock';
import { threadId } from './thread';

Meteor.startup(function() {
  Meteor.setInterval(handleInstantMessage, 5000);
});

function handleInstantMessage() {
  try {
    const instantMessageBulk = dbInstantMessage.rawCollection().initializeUnorderedBulkOp();
    let needExecute = false;
    dbResourceLock.insert({
      _id: 'instantMessage',
      threadId: threadId,
      task: 'handleInstantMessage',
      time: new Date()
    });
    const logIdList = [];
    dbLog
      .find(
        {
          resolve: false
        },
        {
          disableOplog: true
        }
      )
      .forEach((log) => {
        logIdList.push(log._id);
        needExecute = true;
        const instantMessage = {
          type: log.logType,
          createdAt: log.createdAt,
          onlyForUsers: [],
          source: '!'
        };
        switch (log.logType) {
          case '驗證通過': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = log.username[0] + '的帳號驗證通過，領取起始資金$' + log.price + '。';
            break;
          }
          case '發薪紀錄': {
            instantMessage.message = '系統向所有已驗證通過的使用者發給了' + log.price + '的薪水！';
            break;
          }
          case '創立公司': {
            instantMessage.message = log.username[0] + '發起了「' + log.companyName + '」的新公司創立計劃，誠意邀請有意者投資！';
            break;
          }
          case '參與投資': {
            instantMessage.message = log.username[0] + '向「' + log.companyName + '公司創立計劃」投資了$' + log.amount + '！';
            break;
          }
          case '創立失敗': {
            instantMessage.message = log.username.join('、') + '等人投資的「' + log.companyName + '公司創立計劃」由於投資人數不足失敗了，投資金額將全數返回！';
            break;
          }
          case '創立成功': {
            instantMessage.message = log.username.join('、') + '等人投資的「' + log.companyName + '公司創立計劃」成功了，該公司正式上市，初始股價為$' + log.price + '！';
            break;
          }
          case '創立得股': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '對「' + log.companyName + '公司創立計劃」的投資為你帶來了' + log.amount + '數量的公司股票！';
            break;
          }
          case '購買下單': {
            instantMessage.message = log.username[0] + '想要用每股$' + log.price + '的單價購買' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '販賣下單': {
            instantMessage.message = log.username[0] + '想要用每股$' + log.price + '的單價販賣' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '取消下單': {
            instantMessage.message = log.username[0] + '取消了以每股$' + log.price + '的單價' + log.message + log.amount + '數量的「' + log.companyName + '」公司股票的訂單！';
            break;
          }
          case '訂單完成': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '您以每股$' + log.price + '的單價' + log.message + log.amount + '數量的「' + log.companyName + '」公司股票的訂單已經全數交易完畢！';
            break;
          }
          case '公司釋股': {
            instantMessage.message = '由於股價持續高漲，「' + log.companyName + '」公司以$' + log.price + '的價格釋出了' + log.amount + '數量的股票到市場上以套取利潤！';
            break;
          }
          case '交易紀錄': {
            instantMessage.message = log.username[0] + '以$' + log.price + '的單價向' + (log.username[1] || '「companyName」公司') + '購買了' + log.amount + '數量的「' + log.companyName + '」公司股票！';
            break;
          }
          case '辭職紀錄': {
            instantMessage.message = log.username[0] + '辭去了「' + log.companyName + '」公司的經理人職務！';
            break;
          }
          case '參選紀錄': {
            instantMessage.message = log.username[0] + '開始競選「' + log.companyName + '」公司的經理人職務！';
            break;
          }
          case '經理管理': {
            instantMessage.message = log.username[0] + '修改了「' + log.companyName + '」公司的資訊！';
            break;
          }
          case '推薦產品': {
            instantMessage.message = log.username[0] + '向「' + log.companyName + '」公司的一項產品投了一張推薦票，使其獲得了$' + log.price + '的營利額！';
            break;
          }
          //支持紀錄不進即時訊息
          case '支持紀錄': {
            return false;
          }
          case '就任經理': {
            instantMessage.message = log.username[0] + '在' + log.message + '商業季度' + (log.amount ? '以' + log.amount + '數量的支持股份' : '') + '擊敗了所有競爭對手，' + (log.username[1] === '!none' ? '' : '取代' + log.username[1]) + '成為「' + log.companyName + '」公司的經理人！';
            break;
          }
          case '公司營利': {
            instantMessage.message = '「' + log.companyName + '」公司在本商業季度一共獲利$' + log.amount + '！';
            break;
          }
          case '營利分紅': {
            instantMessage.onlyForUsers = log.username;
            instantMessage.message = '你得到了「' + log.companyName + '」公司的分紅$' + log.amount + '！';
            break;
          }
          case '舉報公司': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由舉報了「' + log.companyName + '」公司！';
            break;
          }
          case '舉報產品': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由舉報了「' + log.companyName + '」公司的#' + log.productId + '產品！';
            break;
          }
          case '公司撤銷': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由撤銷了「' + log.companyName + '」公司！';
            break;
          }
          case '取消資格': {
            instantMessage.message = log.username[0] + '以「' + log.message + '」理由取消了' + log.username[1] + '擔任經理人的資格！';
            break;
          }
          //免費得石不進即時訊息
          case '免費得石': {
            return false;
          }
        }
        instantMessageBulk.insert(instantMessage);
      })
    //清除一分鐘前的即時訊息
    dbInstantMessage.remove({
      createdAt: {
        $lt: new Date( Date.now() - 60000)
      }
    });
    if (needExecute) {
      dbLog.update(
        {
          _id: {
            $in: logIdList
          }
        },
        {
          $set: {
            resolve: true
          }
        },
        {
          multi: true
        }
      );
      instantMessageBulk.execute();
    }
  }
  catch (e) {
    throw e;
  }
  finally {
    dbResourceLock.remove('instantMessage');
  }
}
<|endoftext|>