<commit_before>// ingredient count minimum
const INGR_MIN_CNT = 2;
let ingredients; //ingredients = [egg, potato]

$(init);

function init() {
    initIngredients();

}

function initIngredients(){
    let request = new XMLHttpRequest();
    request.open("GET", "/ingredients");
    request.onreadystatechange = function () {
        if(request.readyState==4 && request.status == 200)
            ingredients = JSON.parse(request.responseText);
        initIngreMenu();

    };
    request.send(null);
    initIngreBar();
}

function initIngreMenu(){
    for(let catId in ingredients){
        let category = ingredients[catId];
        $("

").html(catId).appendTo("#ingreMenu");
        let div = $("

").appendTo("#ingreMenu");
        div = $("

").css("display","flex").attr("id",catId).addClass("ingreBar rounded-div").appendTo(div);
        for(let i in category) {
            let ingre = category[i];
            $("

").attr("id", `${catId}--${ingre.name}`)
                .html(ingre.name)
                .addClass("ingreBut")
                .appendTo(`#${catId}`)
                .addClass("rounded-div")
                .draggable({
                    scope: "ingre",
                    helper: "clone"
                });
        }
    }
    $("#ingreMenu").accordion();
    // $("#accordion").accordion();
}

function initIngreBar(){
    $("#ingreBar").droppable({
        activeClass: "ui-state-highlight",
        scope: "ingre",
        over: function (event, ui) {
            console.log(ui.draggable);
            if(!$(this).find("#" + ui.draggable.attr("id")).length)
                ui.draggable.appendTo(this);
        },
        out: function (event, ui) {
            let catId = ui.draggable.attr("id");
            console.log(catId);
            catId = catId.slice(0, catId.indexOf("--"));
            ui.draggable.appendTo(`#${catId}`);
        }
    });
}

function searches3(){
    let ingres = $("#ingreBar").find(".ingreBut");
    if(ingres.length < INGR_MIN_CNT){
        alert(`minimum ${INGR_MIN_CNT} ingredients are required`);
        return
    }
    let params = [];
    $.each(ingres, i => {params.push($(ingres[i]).attr("id"))});
    let request = new XMLHttpRequest();
    request.open("GET", `/search?ingredients=${JSON.stringify(params)}`);
    request.onreadystatechange = loadRecipes;
    request.send(null);
}

/**
 * display recipes when request is ready
 */
function loadRecipes() {
    if (this.readyState == 4 && this.status == 200) {
        let recipes = JSON.parse(this.responseText);
        //reload
        $("#searchResult").load("recipes/search_result.html", () => {
            //enable tab widget
            $("#recipe_tabs").tabs();
            // update message
            $("#notification").html(`${recipes.length} recipes have been found.`);
            // create recipe shortcut
            for (let i = 0; i < recipes.length; i++) {
                let recipe = recipes[i];
                let img = $("").attr("src", recipe.image.source);
                // AJAX tabs
                img = $("").attr("href", recipe.href)
                    .append(img);
                let div = $("

").attr("id", recipe.recipe_name)
                    .addClass("recipe-button")
                    .append(img);
                findOrCreateDivWithClass("All", "recipeContainer").append(div);
                if (recipe.dietary.indexOf("vegetarian") >= 0)
                    findOrCreateDivWithClass("Vegetarian", "recipeContainer").append(div.clone());
            }
        });
    }
}

/**
 *
 * @param parentId
 * @param className
 * @returns {*}
 */
function findOrCreateDivWithClass(parentId, className){
    let container = $(`#${parentId}`).find(`.${className}`);
    if (!container.length)
        container = $("

").addClass(className).appendTo(`#${parentId}`);
    return container;
}<commit_msg>solve issue with accordion() executed before for-loop finishes<commit_after>// ingredient count minimum
const INGR_MIN_CNT = 2;
let ingredients; //ingredients = [egg, potato]

$(init);

function init() {
    initIngredients();

}

function initIngredients(){
    let request = new XMLHttpRequest();
    request.open("GET", "/ingredients");
    request.onreadystatechange = function () {
        if(request.readyState==4 && request.status == 200)
            ingredients = JSON.parse(request.responseText);
        initIngreMenu();

    };
    request.send(null);
    initIngreBar();
}

function initIngreMenu(){
    for(let catId in ingredients){
        let category = ingredients[catId];
        $("

").html(catId).appendTo("#ingreMenu");
        let div = $("

").appendTo("#ingreMenu");
        div = $("

").css("display","flex").attr("id",catId).addClass("ingreBar rounded-div").appendTo(div);
        for(let i in category) {
            let ingre = category[i];
            $("

").attr("id", `${catId}--${ingre.name}`)
                .html(ingre.name)
                .addClass("ingreBut")
                .appendTo(`#${catId}`)
                .addClass("rounded-div")
                .draggable({
                    scope: "ingre",
                    helper: "clone"
                });
        }
    }
    setTimeout(() => $("#ingreMenu").accordion(), 1);
}

function initIngreBar(){
    $("#ingreBar").droppable({
        activeClass: "ui-state-highlight",
        scope: "ingre",
        over: function (event, ui) {
            if(!$(this).find("#" + ui.draggable.attr("id")).length)
                ui.draggable.appendTo(this);
        },
        out: function (event, ui) {
            let catId = ui.draggable.attr("id");
            catId = catId.slice(0, catId.indexOf("--"));
            ui.draggable.appendTo(`#${catId}`);
        }
    });
}

function searches3(){
    let ingres = $("#ingreBar").find(".ingreBut");
    if(ingres.length < INGR_MIN_CNT){
        alert(`minimum ${INGR_MIN_CNT} ingredients are required`);
        return
    }
    let params = [];
    $.each(ingres, i => {params.push($(ingres[i]).html())});
    let request = new XMLHttpRequest();
    request.open("GET", `/search?ingredients=${JSON.stringify(params)}`);
    request.onreadystatechange = loadRecipes;
    request.send(null);
}

/**
 * display recipes when request is ready
 */
function loadRecipes() {
    if (this.readyState == 4 && this.status == 200) {
        let recipes = JSON.parse(this.responseText);
        //reload
        $("#searchResult").load("recipes/search_result.html", () => {
            //enable tab widget
            $("#recipe_tabs").tabs();
            // update message
            $("#notification").html(`${recipes.length} recipes have been found.`);
            // create recipe shortcut
            for (let i = 0; i < recipes.length; i++) {
                let recipe = recipes[i];
                let img = $("").attr("src", recipe.image.source);
                // AJAX tabs
                img = $("").attr("href", recipe.href)
                    .append(img);
                let div = $("

").attr("id", recipe.recipe_name)
                    .addClass("recipe-button")
                    .append(img);
                findOrCreateDivWithClass("All", "recipeContainer").append(div);
                if (recipe.dietary.indexOf("vegetarian") >= 0)
                    findOrCreateDivWithClass("Vegetarian", "recipeContainer").append(div.clone());
            }
        });
    }
}

/**
 *
 * @param parentId
 * @param className
 * @returns {*}
 */
function findOrCreateDivWithClass(parentId, className){
    let container = $(`#${parentId}`).find(`.${className}`);
    if (!container.length)
        container = $("

").addClass(className).appendTo(`#${parentId}`);
    return container;
}<|endoftext|>


<commit_before>Object.defineProperty = function defineProperty(object, property, descriptor) {
	// handle object
	if (object === null || typeof object !== 'object') {
		throw new TypeError('Object must be an object');
	}

	// handle descriptor
	if (descriptor === null || typeof descriptor !== 'object') {
		throw new TypeError('Descriptor must be an object');
	}

	var
	propertyString = String(property),
	Element = window.Element || {};

	// handle descriptor.get
	if ('get' in descriptor) {
		object[propertyString] = object === Element.prototype ? Element.__defineGetter__(propertyString, descriptor.get) : descriptor.get.call(object);
	}
	// handle descriptor.value
	else {
		object[propertyString] = descriptor.value;
	}

	// handle descriptor.set
	if ('set' in descriptor && object.constructor === Element) {
		object.attachEvent('onpropertychange', function callee(event) {
			object.detachEvent('onpropertychange', callee);

			if (event.propertyName === propertyString) {
				object[propertyString] = descriptor.set.call(object, object[propertyString]);
			}

			object.attachEvent('onpropertychange', callee);
		});
	}

	// return object
	return object;
};
<commit_msg>Update defineProperty for old IE<commit_after>Object.defineProperty = function defineProperty(object, property, descriptor) {
	// handle object
	if (object === null || typeof object !== 'object') {
		throw new TypeError('Object must be an object');
	}

	// handle descriptor
	if (descriptor === null || typeof descriptor !== 'object') {
		throw new TypeError('Descriptor must be an object');
	}

	var
	propertyString = String(property),
	Element = window.Element || {};

	// handle descriptor.get
	if ('get' in descriptor) {
		object[propertyString] = object === Element.prototype ? new Element.__getter__(descriptor.get) : descriptor.get.call(object);
	}
	// handle descriptor.value
	else {
		object[propertyString] = descriptor.value;
	}

	// handle descriptor.set
	if ('set' in descriptor && object.constructor === Element) {
		object.attachEvent('onpropertychange', function callee(event) {
			object.detachEvent('onpropertychange', callee);

			if (event.propertyName === propertyString) {
				object[propertyString] = descriptor.set.call(object, object[propertyString]);
			}

			object.attachEvent('onpropertychange', callee);
		});
	}

	// return object
	return object;
};
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var { ObjectID } = require('mongodb'); // MongoDB _id
var wcwidth = require('wcwidth');
var config = require('../../common-config.json');
var srvConfig = require('../../server-config.json');

/*
 * POST /public/attendee
 *
 * Accpet application from attendee
 *
 * Websocket Emit: newAttendee(attendee_obj)
 */
router.post('/attendee', function(req, res, next) {

  var moment = require('moment');
  const now = moment().unix();

  // Check post body data
  if (req.body.attendee_name === undefined ||
    req.body.summary === undefined ||
    req.body.email === undefined ||
    req.body.g_recaptcha_response === undefined ||
    req.body.attendee_name === '' ||
    req.body.summary === '' ||
    req.body.email === '' ||
    req.body.g_recaptcha_response === '') {

    //console.log(req.body);
    //console.log('Bad Request');
    res.status(400).send('Bad Request, lack of args');

  } else if ((now < config.allow_speaker_ts.start || now > config.allow_speaker_ts.end) &&
              !config.allow_speaker_ts.force_ignore) {

    res.status(403).send('Forbidden, system not open');

  } else if (wcwidth(req.body.attendee_name) > 20 ||
    wcwidth(req.body.summary) > 200 ) {

    //console.log(req.body);
    //console.log('Bad Request, attendee_name > 20 || summary > 200');
    res.status(400).send('Bad Request, attendee_name > 20 || summary > 200');

  } else {

    //console.log('config.direct_to_queue: %s', config.direct_to_queue);
    //console.log('config.reCAPTCHA.enabled: %s', config.reCAPTCHA.enabled);

    var request = require('request');
    var md5 = require('md5');

    // Check recaptcha response
    request.post({
      url: 'https://www.google.com/recaptcha/api/siteverify',
      form: {
        secret: srvConfig.reCAPTCHA['secret'],
        response: req.body.g_recaptcha_response,
        remoteip: req.client.remoteAddress
      }
    }, function(err, post_res, post_body) {

      if ((post_res && post_res.statusCode == 200 &&
          JSON.parse(post_body).success == true) ||
        !(config.reCAPTCHA['enabled'])) {

        var timestamp = moment().unix();

        var attendee = {
          attendee_name: req.body.attendee_name,
          summary: req.body.summary,
          email: req.body.email,
          gravatar: `https://www.gravatar.com/avatar/${md5(req.body.email)}`,
          created_at: timestamp,
          recognized_at: config.direct_to_queue ? timestamp : 0, // To be toggled by moderators or direct
          spoken_at: 0,
          removed_at: 0
        };

        var MongoClient = require('mongodb').MongoClient,
          assert = require('assert');

        var insertAttendee = function(attendeeObj, db, callback) {
          // get collection
          var collection = db.collection('attendee');
          // insert attendee
          collection.insertOne(attendeeObj, function(err, ret) {
            assert.equal(err, null);
            assert.equal(1, ret.result.n);
            assert.equal(1, ret.ops.length);
            callback(ret);
            db.close();
          });
        };

        // Connection URL
        var url = config.mongodb;

        // Use connect method to connect to the server
        MongoClient.connect(url, function(err, db) {

          assert.equal(null, err);

          insertAttendee(attendee, db, function(ret) {

            //console.log('Insert attendee success');
            //console.log(ret.ops);

            // Emit Event to moderate
            // Only emit to secret room
            res.io.to(srvConfig.websocket.secret).emit('newAttendee', ret.ops);

            res.send({
              status: ret.result.ok
            });
          });
        });
      } else {
        //console.log('Bad reCAPTCHA');
        //console.log(post_body);
        res.status(418).send('Bad reCAPTCHA, I\'m a teapot!');
      }
    });
  }
});

/*
 * GET /public/queue
 *
 * Get all attendee in the queue
 *
 * Websocket Emit: null
 */
router.get('/queue', function(req, res, next) {

  var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

  // Connection URL
  var url = config.mongodb;

  // Use connect method to connect to the server
  MongoClient.connect(url, function(err, db) {

    assert.equal(null, err);
    var collection = db.collection('attendee');

    collection.find({
      recognized_at: { $gt: 0 }, // > 0
      removed_at: 0,
      spoken_at: 0
    }).sort({
      recognized_at: 1,
      created_at: 1
    }).toArray(function(err, ret) {
      assert.equal(null, err);
      db.close();
      res.send(ret);
    });
  });
});

/*
 * GET /public/subject
 *
 * Get latest subject
 *
 * Websocket Emit: null
 */
router.get('/subject', function(req, res, next) {

  var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

  // Connection URL
  var url = config.mongodb;

  // Use connect method to connect to the server
  MongoClient.connect(url, function(err, db) {

    assert.equal(null, err);
    var collection = db.collection('subject');

    collection.find({}).sort({
      'created_at': -1
    }).limit(1).toArray(function(err, ret) {
      assert.equal(null, err);
      db.close();
      res.send(ret[0].subject);
    });
  });
});

module.exports = router;<commit_msg>Fix #11 md5 crash<commit_after>var express = require('express');
var router = express.Router();
var { ObjectID } = require('mongodb'); // MongoDB _id
var wcwidth = require('wcwidth');
var config = require('../../common-config.json');
var srvConfig = require('../../server-config.json');

/*
 * POST /public/attendee
 *
 * Accpet application from attendee
 *
 * Websocket Emit: newAttendee(attendee_obj)
 */
router.post('/attendee', function(req, res, next) {

  var moment = require('moment');
  const now = moment().unix();

  // Check post body data
  if (req.body.attendee_name === undefined ||
    req.body.summary === undefined ||
    req.body.email === undefined ||
    req.body.g_recaptcha_response === undefined ||
    req.body.attendee_name === '' ||
    req.body.summary === '' ||
    req.body.email === '' ||
    req.body.g_recaptcha_response === '') {

    //console.log(req.body);
    //console.log('Bad Request');
    res.status(400).send('Bad Request, lack of args');

  } else if ((now < config.allow_speaker_ts.start || now > config.allow_speaker_ts.end) &&
              !config.allow_speaker_ts.force_ignore) {

    res.status(403).send('Forbidden, system not open');

  } else if (wcwidth(req.body.attendee_name) > 20 ||
    wcwidth(req.body.summary) > 200 ) {

    //console.log(req.body);
    //console.log('Bad Request, attendee_name > 20 || summary > 200');
    res.status(400).send('Bad Request, attendee_name > 20 || summary > 200');

  } else {

    //console.log('config.direct_to_queue: %s', config.direct_to_queue);
    //console.log('config.reCAPTCHA.enabled: %s', config.reCAPTCHA.enabled);

    var request = require('request');
    var md5 = require('md5');

    // Check recaptcha response
    request.post({
      url: 'https://www.google.com/recaptcha/api/siteverify',
      form: {
        secret: srvConfig.reCAPTCHA['secret'],
        response: req.body.g_recaptcha_response,
        remoteip: req.client.remoteAddress
      }
    }, function(err, post_res, post_body) {

      if ((post_res && post_res.statusCode == 200 &&
          JSON.parse(post_body).success == true) ||
        !(config.reCAPTCHA['enabled'])) {

        var timestamp = moment().unix();

        var hash = '';
        if (req.body.email !== null)
          hash = md5(req.body.email);

        var attendee = {
          attendee_name: req.body.attendee_name,
          summary: req.body.summary,
          email: req.body.email,
          gravatar: `https://www.gravatar.com/avatar/${hash}`,
          created_at: timestamp,
          recognized_at: config.direct_to_queue ? timestamp : 0, // To be toggled by moderators or direct
          spoken_at: 0,
          removed_at: 0
        };

        var MongoClient = require('mongodb').MongoClient,
          assert = require('assert');

        var insertAttendee = function(attendeeObj, db, callback) {
          // get collection
          var collection = db.collection('attendee');
          // insert attendee
          collection.insertOne(attendeeObj, function(err, ret) {
            assert.equal(err, null);
            assert.equal(1, ret.result.n);
            assert.equal(1, ret.ops.length);
            callback(ret);
            db.close();
          });
        };

        // Connection URL
        var url = config.mongodb;

        // Use connect method to connect to the server
        MongoClient.connect(url, function(err, db) {

          assert.equal(null, err);

          insertAttendee(attendee, db, function(ret) {

            //console.log('Insert attendee success');
            //console.log(ret.ops);

            // Emit Event to moderate
            // Only emit to secret room
            res.io.to(srvConfig.websocket.secret).emit('newAttendee', ret.ops);

            res.send({
              status: ret.result.ok
            });
          });
        });
      } else {
        //console.log('Bad reCAPTCHA');
        //console.log(post_body);
        res.status(418).send('Bad reCAPTCHA, I\'m a teapot!');
      }
    });
  }
});

/*
 * GET /public/queue
 *
 * Get all attendee in the queue
 *
 * Websocket Emit: null
 */
router.get('/queue', function(req, res, next) {

  var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

  // Connection URL
  var url = config.mongodb;

  // Use connect method to connect to the server
  MongoClient.connect(url, function(err, db) {

    assert.equal(null, err);
    var collection = db.collection('attendee');

    collection.find({
      recognized_at: { $gt: 0 }, // > 0
      removed_at: 0,
      spoken_at: 0
    }).sort({
      recognized_at: 1,
      created_at: 1
    }).toArray(function(err, ret) {
      assert.equal(null, err);
      db.close();
      res.send(ret);
    });
  });
});

/*
 * GET /public/subject
 *
 * Get latest subject
 *
 * Websocket Emit: null
 */
router.get('/subject', function(req, res, next) {

  var MongoClient = require('mongodb').MongoClient,
    assert = require('assert');

  // Connection URL
  var url = config.mongodb;

  // Use connect method to connect to the server
  MongoClient.connect(url, function(err, db) {

    assert.equal(null, err);
    var collection = db.collection('subject');

    collection.find({}).sort({
      'created_at': -1
    }).limit(1).toArray(function(err, ret) {
      assert.equal(null, err);
      db.close();
      res.send(ret[0].subject);
    });
  });
});

module.exports = router;<|endoftext|>


<commit_before>/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { $C } from './deps/collection';
import { NULL } from './consts/links';
import { IS_NODE } from './consts/hacks';
import { Snakeskin } from './core';
import { any, _ } from './helpers/gcc';
import { setMacros } from './helpers/macros';
import { Parser } from './parser/index';
import * as rgxp from './consts/regs';

import {

	getFromCache,
	getCacheKey,
	saveIntoFnCache,
	saveIntoCache

} from './helpers/cache';

import {

	LEFT_BLOCK as lb,
	RIGHT_BLOCK as rb,
	ADV_LEFT_BLOCK as alb

} from './consts/literals';

/**
 * Compiles Snakeskin templates
 *
 * @param {(Element|string)} src - a reference to a DOM node, where the templates were declared
 *   or a text of the templates
 *
 * @param {?$$SnakeskinParams=} [opt_params] - additional runtime parameters:
 *
 *   *) [exports = 'default'] - an export type
 *   *) [context] - a storage object for the compiled templates
 *        (will be set the CommonJS export type)
 *
 *   *) [vars] - a map of super global variables, which will be added to Snakeskin.Vars
 *   *) [cache = true] - if is false, then caching is disabled
 *   *) [debug] - an object, which will be contained some debug information
 *
 *   *) [onError] - a callback for error handling
 *   *) [throws = false] - if is true, then in case of an error or a missing error handler,
 *        then will be thrown an exception
 *
 *   *) [localization = true] - if is false, then localization literals ` ... ` won't be wrapped with a i18n function
 *   *) [i18nFn = 'i18n'] - a name of the i18n function
 *   *) [language] - a map of words for localization (for example, {'Hello world': 'Привет мир'})
 *   *) [words] - an object, which will be contained all found localization words
 *
 *   *) [ignore] - a RegExp object, which specifies whitespace symbols for ignoring
 *   *) [autoReplace = false] - if is false, then macros will be disabled
 *   *) [macros] - a map of the macros
 *   *) [renderAs] - a rendering type of templates:
 *        1) placeholder - all templates will be rendered as "placeholder";
 *        2) interface - all templates will be rendered as "interface";
 *        3) template - all templates will be rendered as "template".
 *
 *   *) [renderMode = 'stringConcat'] - a rendering mode of templates:
 *        1) stringConcat - renders template to a string, for concatenation of strings will be used operator;
 *        2) stringBuffer - renders template to a string, for concatenation of strings
 *          will be used Snakeskin.StringBuffer;
 *        3) dom - renders template to a DocumentFragment object.
 *
 *   *) [eol = '\n'] - EOL symbol
 *   *) [tolerateWhitespace = false] - if is true, then whitespaces will be processed "as is"
 *   *) [inlineIterators = false] - if is true, then all forEach and forIn iterators will be rendered as loops
 *   *) [doctype = 'xml'] - a type of document:
 *        1) html;
 *        2) xml.
 *
 *   *) [replaceUndef = true] - if is false, then will be disabled the undef filter by default
 *   *) [escapeOutput = true] - if is false, then will be disabled the html filter by default
 *
 *   *) [useStrict = true] - if is false, then all templates will be compiled without the 'use strict'; mode;
 *   *) [bemFilter = 'bem'] - a name of the bem filter
 *   *) [prettyPrint = false] - if is true, then output will be formatted
 *
 * @param {?$$SnakeskinInfoParams=} [opt_info] - additional parameters for debug:
 *   *) [file] - a path of a template file
 *
 * @param {$$SnakeskinSysParams=} [opt_sysParams] - private parameters:
 *   *) [cacheKey = false] - if is true, then will bi returned a cache key of operation
 *
 *   *) [scope] - a context of directives
 *   *) [vars] - a map of local variables
 *   *) [consts] - an array of constant declarations
 *
 *   *) [proto] - parameters object of proto
 *   *) [parent] - a link for the parent object
 *
 *   *) [lines] - an array of template lines
 *   *) [needPrfx] - if is true, then for declaring directives will be used #{ ... }
 *
 * @return {(string|boolean|null)}
 */
Snakeskin.compile = function (src, opt_params, opt_info, opt_sysParams) {
	src = src || '';

	/** @type {$$SnakeskinSysParams} */
	const
		sp = any(opt_sysParams || {});

	/** @type {$$SnakeskinParams} */
	const
		p = any(opt_params || {});

	// GCC export
	// >>>

	const
		ctx = p.context || NULL,
		eol = p.eol = p.eol || '\n',
		words = p.words;

	p.exports = p.exports || 'default';
	p.prettyPrint = p.prettyPrint || false;
	p.renderMode = p.renderMode || 'stringConcat';
	p.inlineIterators = p.inlineIterators || false;
	p.tolerateWhitespace = p.tolerateWhitespace || false;
	p.replaceUndef = p.replaceUndef !== false;
	p.escapeOutput = p.escapeOutput !== false;
	p.throws = p.throws || false;
	p.cache = p.cache !== false;
	p.autoReplace = p.autoReplace || false;
	p.doctype = p.doctype !== false && (p.doctype || 'xml');

	if (p.renderMode === 'dom') {
		p.doctype = false;
	}

	p.useStrict = p.useStrict !== false;
	p.bemFilter = p.bemFilter || 'bem';
	p.vars = p.vars || {};

	$C(p.vars).forEach((val, key) => {
		Snakeskin.Vars[key] = val;
	});

	p.i18nFn = p.i18nFn || 'i18n';
	p.localization = p.localization !== false;

	// <<<
	// Debug information
	// >>>

	const
		info = any($C.extend(false, {line: 1}, opt_info || {}));

	let text;
	if (typeof src === 'object' && 'innerHTML' in src) {
		info.node = src;
		text = src.innerHTML.replace(rgxp.whitespaceStart, '');

	} else {
		text = String(src);
	}

	// <<<
	// Caching
	// >>>

	const
		cacheKey = getCacheKey(p, ctx);

	if (sp.cacheKey) {
		return cacheKey;
	}

	if (p.cache) {
		const
			tmp = getFromCache(cacheKey, text, p, ctx);

		if (tmp) {
			return tmp;
		}
	}

	// <<<
	// Working with macros
	// >>>

	let macros = {
		map: {},
		groups: {},
		inline: {},
		combo: {}
	};

	if (sp.proto) {
		macros = p.macros;

	} else {
		setMacros(p.macros, macros, null, true);
	}

	// <<<
	// File initialization
	// >>>

	let
		label = '',
		dirname,
		filename;

	if (!sp.proto) {
		Snakeskin.LocalVars.include = {};
		Snakeskin.UID = Math.random()
			.toString(16)
			.replace('0.', '')
			.substring(0, 5);

		if (IS_NODE && info.file) {
			let
				path = require('path'),
				fs = require('fs');

			filename =
				info.file = path.normalize(path.resolve(info.file));

			dirname = path.dirname(filename);
			Snakeskin.LocalVars.include[filename] = 'index';

			try {
				label = fs.statSync(filename).mtime;

			} catch (ignore) {}
		}
	}
};
<commit_msg>Fix typo<commit_after>/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { $C } from './deps/collection';
import { NULL } from './consts/links';
import { IS_NODE } from './consts/hacks';
import { Snakeskin } from './core';
import { any, _ } from './helpers/gcc';
import { setMacros } from './helpers/macros';
import { Parser } from './parser/index';
import * as rgxp from './consts/regs';

import {

	getFromCache,
	getCacheKey,
	saveIntoFnCache,
	saveIntoCache

} from './helpers/cache';

import {

	LEFT_BLOCK as lb,
	RIGHT_BLOCK as rb,
	ADV_LEFT_BLOCK as alb

} from './consts/literals';

/**
 * Compiles Snakeskin templates
 *
 * @param {(Element|string)} src - a reference to a DOM node, where the templates were declared
 *   or a text of the templates
 *
 * @param {?$$SnakeskinParams=} [opt_params] - additional runtime parameters:
 *
 *   *) [exports = 'default'] - an export type
 *   *) [context] - a storage object for the compiled templates
 *        (will be set the CommonJS export type)
 *
 *   *) [vars] - a map of super global variables, which will be added to Snakeskin.Vars
 *   *) [cache = true] - if is false, then caching will be disabled
 *   *) [debug] - an object, which will be contained some debug information
 *
 *   *) [onError] - a callback for an error handling
 *   *) [throws = false] - if is true, then in case of an error or a missing error handler,
 *        then will be thrown an exception
 *
 *   *) [localization = true] - if is false, then localization literals ` ... ` won't be wrapped with a i18n function
 *   *) [i18nFn = 'i18n'] - a name of the i18n function
 *   *) [language] - a map of words for the localization (for example, {'Hello world': 'Привет мир'})
 *   *) [words] - an object, which will be contained all found localization words
 *
 *   *) [ignore] - a RegExp object, which specifies whitespace symbols for ignoring
 *   *) [autoReplace = false] - if is false, then macros will be disabled
 *   *) [macros] - a map of the macros
 *   *) [renderAs] - a rendering type of templates:
 *        1) placeholder - all templates will be rendered as "placeholder";
 *        2) interface - all templates will be rendered as "interface";
 *        3) template - all templates will be rendered as "template".
 *
 *   *) [renderMode = 'stringConcat'] - a rendering mode of templates:
 *        1) stringConcat - renders template to a string, for concatenation of strings will be used operator;
 *        2) stringBuffer - renders template to a string, for concatenation of strings
 *          will be used Snakeskin.StringBuffer;
 *        3) dom - renders template to a DocumentFragment object.
 *
 *   *) [eol = '\n'] - EOL symbol
 *   *) [tolerateWhitespace = false] - if is true, then whitespaces will be processed "as is"
 *   *) [inlineIterators = false] - if is true, then all forEach and forIn iterators will be rendered as loops
 *   *) [doctype = 'xml'] - a type of document:
 *        1) html;
 *        2) xml.
 *
 *   *) [replaceUndef = true] - if is false, then will be disabled the undef filter by default
 *   *) [escapeOutput = true] - if is false, then will be disabled the html filter by default
 *
 *   *) [useStrict = true] - if is false, then all templates will be compiled without the 'use strict'; mode;
 *   *) [bemFilter = 'bem'] - a name of the bem filter
 *   *) [prettyPrint = false] - if is true, then output will be formatted
 *
 * @param {?$$SnakeskinInfoParams=} [opt_info] - additional parameters for debug:
 *   *) [file] - a path of a template file
 *
 * @param {$$SnakeskinSysParams=} [opt_sysParams] - private parameters:
 *   *) [cacheKey = false] - if is true, then will bi returned a cache key of operation
 *
 *   *) [scope] - a context of directives
 *   *) [vars] - a map of local variables
 *   *) [consts] - an array of constant declarations
 *
 *   *) [proto] - parameters object of proto
 *   *) [parent] - a link for the parent object
 *
 *   *) [lines] - an array of template lines
 *   *) [needPrfx] - if is true, then for declaring directives will be used #{ ... }
 *
 * @return {(string|boolean|null)}
 */
Snakeskin.compile = function (src, opt_params, opt_info, opt_sysParams) {
	src = src || '';

	/** @type {$$SnakeskinSysParams} */
	const
		sp = any(opt_sysParams || {});

	/** @type {$$SnakeskinParams} */
	const
		p = any(opt_params || {});

	// GCC export
	// >>>

	const
		ctx = p.context || NULL,
		eol = p.eol = p.eol || '\n',
		words = p.words;

	p.exports = p.exports || 'default';
	p.prettyPrint = p.prettyPrint || false;
	p.renderMode = p.renderMode || 'stringConcat';
	p.inlineIterators = p.inlineIterators || false;
	p.tolerateWhitespace = p.tolerateWhitespace || false;
	p.replaceUndef = p.replaceUndef !== false;
	p.escapeOutput = p.escapeOutput !== false;
	p.throws = p.throws || false;
	p.cache = p.cache !== false;
	p.autoReplace = p.autoReplace || false;
	p.doctype = p.doctype !== false && (p.doctype || 'xml');

	if (p.renderMode === 'dom') {
		p.doctype = false;
	}

	p.useStrict = p.useStrict !== false;
	p.bemFilter = p.bemFilter || 'bem';
	p.vars = p.vars || {};

	$C(p.vars).forEach((val, key) => {
		Snakeskin.Vars[key] = val;
	});

	p.i18nFn = p.i18nFn || 'i18n';
	p.localization = p.localization !== false;

	// <<<
	// Debug information
	// >>>

	const
		info = any($C.extend(false, {line: 1}, opt_info || {}));

	let text;
	if (typeof src === 'object' && 'innerHTML' in src) {
		info.node = src;
		text = src.innerHTML.replace(rgxp.whitespaceStart, '');

	} else {
		text = String(src);
	}

	// <<<
	// Caching
	// >>>

	const
		cacheKey = getCacheKey(p, ctx);

	if (sp.cacheKey) {
		return cacheKey;
	}

	if (p.cache) {
		const
			tmp = getFromCache(cacheKey, text, p, ctx);

		if (tmp) {
			return tmp;
		}
	}

	// <<<
	// Working with macros
	// >>>

	let macros = {
		map: {},
		groups: {},
		inline: {},
		combo: {}
	};

	if (sp.proto) {
		macros = p.macros;

	} else {
		setMacros(p.macros, macros, null, true);
	}

	// <<<
	// File initialization
	// >>>

	let
		label = '',
		dirname,
		filename;

	if (!sp.proto) {
		Snakeskin.LocalVars.include = {};
		Snakeskin.UID = Math.random()
			.toString(16)
			.replace('0.', '')
			.substring(0, 5);

		if (IS_NODE && info.file) {
			let
				path = require('path'),
				fs = require('fs');

			filename =
				info.file = path.normalize(path.resolve(info.file));

			dirname = path.dirname(filename);
			Snakeskin.LocalVars.include[filename] = 'index';

			try {
				label = fs.statSync(filename).mtime;

			} catch (ignore) {}
		}
	}
};
<|endoftext|>


<commit_before>// Libraries
import Path from 'path'
import FS from 'fs'
import MIME from 'mime-types'

// Our modules
import { asyncRequest } from '../util'
import { Image } from '../db'

// Image paths
const thumbDir = Path.join(__dirname, '..', '..', 'uploads', 'thumb')
const imgDir = Path.join(__dirname, '..', '..', 'uploads', 'source')

export default router => {
  router.get('/api/get/thumb/:id', asyncRequest(async (ctx, next) => {
    const { id } = ctx.params

    // Get image from db
    const image = await Image.get(id)
    const thumb = `${thumbDir}/${image.thumb}`

    ctx.set('Content-Type', MIME.lookup(thumb))
    ctx.body = FS.createReadStream(thumb)
  }))

  router.get('/api/get/image/:id', asyncRequest(async (ctx, next) => {
    const { id } = ctx.params

    // Get image from db
    const image = await Image.get(id)
    const img = `${imgDir}/${image.img}`

    ctx.set('Content-Type', MIME.lookup(img))
    ctx.body = FS.createReadStream(img)
  }))
}
<commit_msg>Add error handling in image/get<commit_after>// Libraries
import Path from 'path'
import FS from 'fs'
import MIME from 'mime-types'

// Our modules
import { asyncRequest } from '../util'
import { Image } from '../db'

// Image paths
const thumbDir = Path.join(__dirname, '..', '..', 'uploads', 'thumb')
const imgDir = Path.join(__dirname, '..', '..', 'uploads', 'source')

export default router => {
  router.get('/api/get/thumb/:id', asyncRequest(async (ctx, next) => {
    const { id } = ctx.params

    if (!id) {
      ctx.status = 400
      ctx.body = 'Error: did not receive valid Image ID'
      return
    }

    // Get image from db
    const image = await Image.get(id)
    const thumb = `${thumbDir}/${image.thumb}`

    ctx.set('Content-Type', MIME.lookup(thumb))
    ctx.body = FS.createReadStream(thumb)
  }))

  router.get('/api/get/image/:id', asyncRequest(async (ctx, next) => {
    const { id } = ctx.params

    if (!id) {
      ctx.status = 400
      ctx.body = 'Error: did not receive valid Image ID'
      return
    }

    // Get image from db
    const image = await Image.get(id)
    const img = `${imgDir}/${image.img}`

    ctx.set('Content-Type', MIME.lookup(img))
    ctx.body = FS.createReadStream(img)
  }))
}
<|endoftext|>


<commit_before>/* jshint node: true, esnext: true */
'use strict';

var AWS = require('aws-sdk');
var modes = require('js-git/lib/modes');

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

var s3db = require('./s3-db');
var fsdb = require('./fs-db');
var cachedb = require('./cache-db');
var callback = require('./callback');

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

AWS.config.update({ region : 'eu-west-1' });
if (process.env.DEBUG) {
  AWS.config.update({ logger : process.stdout });
}

var listFiles = callback(fs.readdir, fs);
var readFile = callback(fs.readFile, fs);
var stat = callback(fs.stat, fs);

function statFile(repo, file, name) {
  return readFile(file)
    .then(buffer => repo.hash('blob', buffer))
    .then(hash => ({ mode : modes.file, hash, name, path : file }));
}

function uploadFile(repo, file) {
  console.log('Uploading file: ' + file);
  return readFile(file)
    .then(buffer => repo.saveAs('blob', buffer));
}

function statFolder(repo, folder, name) {
  return listFiles(folder)
    .then(files => {
      return Promise.all(files.map(statFileOrFolder.bind(null, repo, folder)));
    })
    .then(items => {
      var tree = items.reduce((t, item) => {
        t[item.name] = { mode : item.mode, hash : item.hash };
        return t;
      }, {});
      return repo.hash('tree', tree)
        .then(hash => ({ mode : modes.tree, hash, name, items, path : folder }));
    });
}

function uploadFolder(repo, hash, items, folder) {
  return repo.inStore(hash)
    .then(exists => {
      if (exists) {
        console.log('Already up to date folder: ' + folder);
        return hash;
      } else {
        return Promise.all(items.map(uploadDesc.bind(null, repo)))
          .then(actualHashes => {
            var tree = items.reduce((t, item, idx) => {
              t[item.name] = { mode : item.mode, hash : actualHashes[idx] };
              return t;
            }, {});
            console.log('Uploading folder: ' + folder);
            return repo.saveAs('tree', tree);
          });
      }
    });
}

function statFileOrFolder(repo, folder, file) {
  var item = path.join(folder, file);
  return stat(item)
    .then(stats => {
      if (stats.isFile()) {
        return statFile(repo, item, file);
      } else if (stats.isDirectory()) {
        return statFolder(repo, item, file);
      } else {
        return Promise.reject(new Error('Unrecognized stats: ' + JSON.stringify(stats)));
      }
    });
}

function uploadDesc(repo, desc) {
  if (desc.mode === modes.file) {
    return uploadFile(repo, desc.path);
  } else {
    return uploadFolder(repo, desc.hash, desc.items, desc.path);
  }
}

function upload(repo, folder) {
  return statFolder(repo, folder, 'IGNORED')
    .then(desc => uploadDesc(repo, desc));
}

s3db(AWS, conf.bucket, conf.key)
  .then(s3repo => {
    var fsrepo = fsdb(conf.cache);
    return cachedb(fsrepo, s3repo, ['tree', 'commit', 'blob']);
  })
  .then(repo => {
    return Promise.all(Object.keys(conf.folders).map(ref => {
      return upload(repo, conf.folders[ref])
        .then(treeHash => {
          // TODO keep parent
          return repo.saveAs('commit', {
            parents : [],
            author : { name : 'Mathieu', email : 'code@mais-h.eu', date : new Date() },
            committer : { name : 'Mathieu', email : 'code@mais-h.eu', date : new Date() },
            tree : treeHash,
            message : 'Push'
          });
        })
        .then(commitHash => {
          // TODO make reference update safe for concurrent access
          return repo.updateRef(ref, commitHash);
        });
    }));
  }).then(console.log.bind(console, 'Finished'), err => console.error('Failed', err.stack));
<commit_msg>Blobs are not cached<commit_after>/* jshint node: true, esnext: true */
'use strict';

var AWS = require('aws-sdk');
var modes = require('js-git/lib/modes');

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

var s3db = require('./s3-db');
var fsdb = require('./fs-db');
var cachedb = require('./cache-db');
var callback = require('./callback');

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

AWS.config.update({ region : 'eu-west-1' });
if (process.env.DEBUG) {
  AWS.config.update({ logger : process.stdout });
}

var listFiles = callback(fs.readdir, fs);
var readFile = callback(fs.readFile, fs);
var stat = callback(fs.stat, fs);

function statFile(repo, file, name) {
  return readFile(file)
    .then(buffer => repo.hash('blob', buffer))
    .then(hash => ({ mode : modes.file, hash, name, path : file }));
}

function uploadFile(repo, file) {
  console.log('Uploading file: ' + file);
  return readFile(file)
    .then(buffer => repo.saveAs('blob', buffer));
}

function statFolder(repo, folder, name) {
  return listFiles(folder)
    .then(files => {
      return Promise.all(files.map(statFileOrFolder.bind(null, repo, folder)));
    })
    .then(items => {
      var tree = items.reduce((t, item) => {
        t[item.name] = { mode : item.mode, hash : item.hash };
        return t;
      }, {});
      return repo.hash('tree', tree)
        .then(hash => ({ mode : modes.tree, hash, name, items, path : folder }));
    });
}

function uploadFolder(repo, hash, items, folder) {
  return repo.inStore(hash)
    .then(exists => {
      if (exists) {
        console.log('Already up to date folder: ' + folder);
        return hash;
      } else {
        return Promise.all(items.map(uploadDesc.bind(null, repo)))
          .then(actualHashes => {
            var tree = items.reduce((t, item, idx) => {
              t[item.name] = { mode : item.mode, hash : actualHashes[idx] };
              return t;
            }, {});
            console.log('Uploading folder: ' + folder);
            return repo.saveAs('tree', tree);
          });
      }
    });
}

function statFileOrFolder(repo, folder, file) {
  var item = path.join(folder, file);
  return stat(item)
    .then(stats => {
      if (stats.isFile()) {
        return statFile(repo, item, file);
      } else if (stats.isDirectory()) {
        return statFolder(repo, item, file);
      } else {
        return Promise.reject(new Error('Unrecognized stats: ' + JSON.stringify(stats)));
      }
    });
}

function uploadDesc(repo, desc) {
  if (desc.mode === modes.file) {
    return uploadFile(repo, desc.path);
  } else {
    return uploadFolder(repo, desc.hash, desc.items, desc.path);
  }
}

function upload(repo, folder) {
  return statFolder(repo, folder, 'IGNORED')
    .then(desc => uploadDesc(repo, desc));
}

s3db(AWS, conf.bucket, conf.key)
  .then(s3repo => {
    var fsrepo = fsdb(conf.cache);
    return cachedb(fsrepo, s3repo, ['tree', 'commit']);
  })
  .then(repo => {
    return Promise.all(Object.keys(conf.folders).map(ref => {
      return upload(repo, conf.folders[ref])
        .then(treeHash => {
          // TODO keep parent
          return repo.saveAs('commit', {
            parents : [],
            author : { name : 'Mathieu', email : 'code@mais-h.eu', date : new Date() },
            committer : { name : 'Mathieu', email : 'code@mais-h.eu', date : new Date() },
            tree : treeHash,
            message : 'Push'
          });
        })
        .then(commitHash => {
          // TODO make reference update safe for concurrent access
          return repo.updateRef(ref, commitHash);
        });
    }));
  }).then(console.log.bind(console, 'Finished'), err => console.error('Failed', err.stack));
<|endoftext|>


<commit_before>// @author Taehoon Moon
require('../styles');

var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Modifier = require('famous/core/Modifier');
var OptionsManager = require('famous/core/OptionsManager');
var ImageSurface = require('famous/surfaces/ImageSurface');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var SequentialLayout = require('famous/views/SequentialLayout');
var Utility = require('famous/utilities/Utility');

var PaperRipple = require('./PaperRipple');

function PaperButton(options) {
    ContainerSurface.apply(this, arguments);

    this.options = {
        flat: false,
        disabled: false,
        selected: false,
        label: {
            size: [true, 36],
            properties: {
                textAlign: 'left',
                lineHeight: '38px',
                fontSize: '18px',
                padding: '0 5px 0 5px'
            }
        },
        icon: {
            size: [36, 36]
        },
        ripple: {
        },
        properties: {
            backgroundColor: 'transparent',
            color: 'black'
        },
        disabledProperties: {
            backgroundColor: 'rgba(0, 0, 0, 0.2)',
            color: '#8d8d8d'
        },
        selectedProperties: {
            backgroundColor: '#639dee',// rgba(30, 30, 190, 0.2)',
            color: 'white'
        }
    };

    if (options)
        OptionsManager.patch(this.options, options);

    if (!this.options.flat)
        this.addClass('paper-shadow').addClass('paper-border');

    var w = 0;
    var h;
    if (this.options.label.content) {
        if (typeof this.options.label.size[0] === 'number')
            w += this.options.label.size[0];
        else
            w = this.options.label.size[0];

        h = this.options.label.size[1];
    }

    if (this.options.icon.content) {
        if (typeof this.options.icon.size[0] === 'number')
            w += this.options.icon.size[0];
        else
            w = this.options.icon.size[0];

        if (this.options.icon.size[1] > h)
            h = this.options.icon.size[1];
    }
    else {
        w = undefined;
        this.options.label.size[0] = undefined;
        this.options.label.properties.textAlign = 'center';
    }

    var rippleModifier = new Modifier({
        transform: Transform.translate(0, 0, 0.01)
    });

    this._ripple = new PaperRipple({ ripple: this.options.ripple });

    if (this.options.disabled)
        this.setDisabled(true);

    if (this.options.selected)
        this.setSelected(true);

    var layoutModifier = new Modifier({
        size: [w, h],
        origin: [0, 0.5],
        align: [0, 0.5]
    });

    if (this.options.icon.content)
        layoutModifier.transformFrom(Transform.translate(5, 0));

    var layout = new SequentialLayout({
        direction: Utility.Direction.X
    });

    var items = [];

    if (this.options.icon.content) {
        this._imageSurface = new ImageSurface(this.options.icon);
        items.push(this._imageSurface);
    }

    if (this.options.label.content) {
        this._labelSurface = new Surface(this.options.label);
        items.push(this._labelSurface);
    }

    layout.sequenceFrom(items);

    this.add(layoutModifier).add(layout);
    this.add(rippleModifier).add(this._ripple);
}

PaperButton.prototype = Object.create(ContainerSurface.prototype);
PaperButton.prototype.constructor = PaperRipple;

PaperButton.prototype.setDisabled = function setDisabled(disabled) {
    this.options.disabled = disabled;
    this._ripple.setDisabled(disabled);
    if (disabled) {
        this.setProperties(this.options.disabledProperties);
        this.removeClass('paper-shadow');
    }
    else {
        this.setProperties(this.options.properties);
        if (!this.options.flat)
            this.addClass('paper-shadow');
    }
};

PaperButton.prototype.getSelected = function getSelected() {
    return this.options.selected;
};

PaperButton.prototype.setSelected = function setSelected(selected) {
    this.options.selected = selected;
    if (selected)
        this.setProperties(this.options.selectedProperties);
    else
        this.setProperties(this.options.properties);
};

PaperButton.prototype.setLabelContent = function setLabelContent(content) {
    if (!this._labelSurface)
        return;

    this.options.label.content = content;
    this._labelSurface.setContent(content);
};

module.exports = PaperButton;
<commit_msg>Added getting label content function to PaperButton<commit_after>// @author Taehoon Moon
require('../styles');

var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Modifier = require('famous/core/Modifier');
var OptionsManager = require('famous/core/OptionsManager');
var ImageSurface = require('famous/surfaces/ImageSurface');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var SequentialLayout = require('famous/views/SequentialLayout');
var Utility = require('famous/utilities/Utility');

var PaperRipple = require('./PaperRipple');

function PaperButton(options) {
    ContainerSurface.apply(this, arguments);

    this.options = {
        flat: false,
        disabled: false,
        selected: false,
        label: {
            size: [true, 36],
            properties: {
                textAlign: 'left',
                lineHeight: '38px',
                fontSize: '18px',
                padding: '0 5px 0 5px'
            }
        },
        icon: {
            size: [36, 36]
        },
        ripple: {
        },
        properties: {
            backgroundColor: 'transparent',
            color: 'black'
        },
        disabledProperties: {
            backgroundColor: 'rgba(0, 0, 0, 0.2)',
            color: '#8d8d8d'
        },
        selectedProperties: {
            backgroundColor: '#639dee',// rgba(30, 30, 190, 0.2)',
            color: 'white'
        }
    };

    if (options)
        OptionsManager.patch(this.options, options);

    if (!this.options.flat)
        this.addClass('paper-shadow').addClass('paper-border');

    var w = 0;
    var h;
    if (this.options.label.content) {
        if (typeof this.options.label.size[0] === 'number')
            w += this.options.label.size[0];
        else
            w = this.options.label.size[0];

        h = this.options.label.size[1];
    }

    if (this.options.icon.content) {
        if (typeof this.options.icon.size[0] === 'number')
            w += this.options.icon.size[0];
        else
            w = this.options.icon.size[0];

        if (this.options.icon.size[1] > h)
            h = this.options.icon.size[1];
    }
    else {
        w = undefined;
        this.options.label.size[0] = undefined;
        this.options.label.properties.textAlign = 'center';
    }

    var rippleModifier = new Modifier({
        transform: Transform.translate(0, 0, 0.01)
    });

    this._ripple = new PaperRipple({ ripple: this.options.ripple });

    if (this.options.disabled)
        this.setDisabled(true);

    if (this.options.selected)
        this.setSelected(true);

    var layoutModifier = new Modifier({
        size: [w, h],
        origin: [0, 0.5],
        align: [0, 0.5]
    });

    if (this.options.icon.content)
        layoutModifier.transformFrom(Transform.translate(5, 0));

    var layout = new SequentialLayout({
        direction: Utility.Direction.X
    });

    var items = [];

    if (this.options.icon.content) {
        this._imageSurface = new ImageSurface(this.options.icon);
        items.push(this._imageSurface);
    }

    if (this.options.label.content) {
        this._labelSurface = new Surface(this.options.label);
        items.push(this._labelSurface);
    }

    layout.sequenceFrom(items);

    this.add(layoutModifier).add(layout);
    this.add(rippleModifier).add(this._ripple);
}

PaperButton.prototype = Object.create(ContainerSurface.prototype);
PaperButton.prototype.constructor = PaperRipple;

PaperButton.prototype.setDisabled = function setDisabled(disabled) {
    this.options.disabled = disabled;
    this._ripple.setDisabled(disabled);
    if (disabled) {
        this.setProperties(this.options.disabledProperties);
        this.removeClass('paper-shadow');
    }
    else {
        this.setProperties(this.options.properties);
        if (!this.options.flat)
            this.addClass('paper-shadow');
    }
};

PaperButton.prototype.getSelected = function getSelected() {
    return this.options.selected;
};

PaperButton.prototype.setSelected = function setSelected(selected) {
    this.options.selected = selected;
    if (selected)
        this.setProperties(this.options.selectedProperties);
    else
        this.setProperties(this.options.properties);
};

PaperButton.prototype.getLabelContent = function getLabelContent() {
    if (!this._labelSurface)
        return undefined;

    return this.options.label.content;
};

PaperButton.prototype.setLabelContent = function setLabelContent(content) {
    if (!this._labelSurface)
        return;

    this.options.label.content = content;
    this._labelSurface.setContent(content);
};

module.exports = PaperButton;
<|endoftext|>


<commit_before>'use strict';

import Board from './board';
import server from './sendToServer.js';
import createCanvasGame from './createCanvasGame.js';
import displayMessage from './displayMessage.js';
import * as constant from './constant';
import $ from 'jquery';

document.addEventListener('DOMContentLoaded', function () {
	server.on('connection', function(){

		$('form.username').submit(function(e) {
			e.preventDefault();
			var name = $(this).find('input.username')[0].value;

			$('div.username').remove();

			let context = createCanvasGame();
			let board = new Board(context);
			board.createScoreboard();

			let long = Math.floor(Math.random() * (constant.CANVAS_WIDTH/constant.GRID_SIZE)) * constant.GRID_SIZE;
			let lat = Math.floor(Math.random() * (constant.CANVAS_HEIGHT/constant.GRID_SIZE)) * constant.GRID_SIZE;
			let clientLocaleSnake = '';

			board.clientLocalSnake = clientLocaleSnake;

			server.sendSnakeNew(name);

			server.on('new_apple', function(data){
				let apple = board.newApple(data.x, data.y);
				apple.draw();
			});

			server.on('new_snake', function(data){
				clientLocaleSnake = board.newSnake(data.x, data.y, data.name);
			});
			server.on('joinGame', function(apples){
				apples.forEach((apple) => {
					let drawApple = board.newApple(apple.x, apple.y);
					drawApple.draw();
				});
			});

			server.on('setDirection', data => {
				board.snakes.forEach(snake => {
					if (snake.name === data.name) {
						snake.direction = data.direction;
					}
				});
			});

			//server.sendDeleteUser();
			server.sendMove();

			//server.sendAppleEaten(x, y);

			board.render();
			board.on('appleEaten', function(position){
				server.sendAppleEaten(position);
			});

			server.on('disconnect', function(){
				board.stopRendering();
				displayMessage("Warning !", "You have been disconnected from the server ! Check your internet connection !");
			});

			$('body').keydown((e) => {
				if (e.keyCode === 37 && clientLocaleSnake.direction !== 'right') {
					server.changeDirection(clientLocaleSnake.name, 'left');
				}
				else if (e.keyCode === 38 && clientLocaleSnake.direction !== 'down') {
					server.changeDirection(clientLocaleSnake.name, 'up');
				}
				else if (e.keyCode === 39 && clientLocaleSnake.direction !== 'left') {
					server.changeDirection(clientLocaleSnake.name, 'right');
				}
				else if (e.keyCode === 40 && clientLocaleSnake.direction !== 'up') {
					server.changeDirection(clientLocaleSnake.name, 'down');
				}
			});
		});
	});
});
<commit_msg>correction bugs<commit_after>'use strict';

import Board from './board';
import server from './sendToServer.js';
import createCanvasGame from './createCanvasGame.js';
import displayMessage from './displayMessage.js';
import * as constant from './constant';
import $ from 'jquery';

document.addEventListener('DOMContentLoaded', function () {
	server.on('connection', function(){

		$('form.username').submit(function(e) {
			e.preventDefault();
			var name = $(this).find('input.username')[0].value;

			$('div.username').remove();

			let context = createCanvasGame();
			let board = new Board(context);
			board.createScoreboard();

			let long = Math.floor(Math.random() * (constant.CANVAS_WIDTH/constant.GRID_SIZE)) * constant.GRID_SIZE;
			let lat = Math.floor(Math.random() * (constant.CANVAS_HEIGHT/constant.GRID_SIZE)) * constant.GRID_SIZE;
			let clientLocaleSnake = undefined;

			board.clientLocalSnake = clientLocaleSnake;

			server.sendSnakeNew(name);

			server.on('new_apple', function(data){
				let apple = board.newApple(data.x, data.y);
				apple.draw();
			});

			server.on('new_snake', function(data){
				clientLocaleSnake = board.newSnake(data.x, data.y, data.name);
			});
			server.on('joinGame', function(apples){
				apples.forEach((apple) => {
					let drawApple = board.newApple(apple.x, apple.y);
					drawApple.draw();
				});
			});

			server.on('setDirection', data => {
				board.snakes.forEach(snake => {
					if (snake.name === data.name) {
						snake.direction = data.direction;
					}
				});
			});

			//server.sendDeleteUser();
			server.sendMove();

			//server.sendAppleEaten(x, y);

			board.render();
			board.on('appleEaten', function(position){
				server.sendAppleEaten(position);
			});

			server.on('disconnect', function(){
				board.stopRendering();
				displayMessage("Warning !", "You have been disconnected from the server ! Check your internet connection !");
			});

			$('body').keydown((e) => {
				if (e.keyCode === 37 && clientLocaleSnake.direction !== 'right') {
					server.changeDirection(clientLocaleSnake.name, 'left');
				}
				else if (e.keyCode === 38 && clientLocaleSnake.direction !== 'down') {
					server.changeDirection(clientLocaleSnake.name, 'up');
				}
				else if (e.keyCode === 39 && clientLocaleSnake.direction !== 'left') {
					server.changeDirection(clientLocaleSnake.name, 'right');
				}
				else if (e.keyCode === 40 && clientLocaleSnake.direction !== 'up') {
					server.changeDirection(clientLocaleSnake.name, 'down');
				}
			});
		});
	});
});
<|endoftext|>


<commit_before>'use strict';

var path = process.cwd();
var ctrlPath = path + '/server/ctrl';

const UserController = require(ctrlPath + '/user-ctrl.server.js');
const BookController = require(ctrlPath + '/book-ctrl.server.js');
const TradeController = require(ctrlPath + '/trade-ctrl.server.js');
const BookSearch = require('../common/book-search');
const debug = require('debug')('book:routes');

var _log = function(msg) {
    console.log('[LOG@SERVER]: ' + msg);
};

/* Function for debug logging requests.*/
var reqDebug = function(req) {
	_log('\t\tHeaders: ' + JSON.stringify(req.headers));
	_log('\t\tBody: ' + JSON.stringify(req.body));
	_log('\t\tParams: ' + JSON.stringify(req.params));
	_log('\t\tUrl:' + JSON.stringify(req.url));
	_log('\t\tText:' + JSON.stringify(req.text));
	_log('\t\tContent:' + JSON.stringify(req.content));
	_log('\t\tQuery:' + JSON.stringify(req.query));
};

const _u = function(username) {
    return '|' + username + '|';
};

// Msg objects sent back to the client
var notAuthorized = {msg: 'Operation not authorized. Log in first.'};
var errorInternal = {msg: 'Server internal error.'};
var errorForbidden = {msg: 'Requested action forbidden.'};
var requestOk = {msg: 'Request was completed OK.'};

/* Contains all routes for this application. */
module.exports = function(app, passport) {

    /* Renders a pug template.*/
    var renderPug = function(req, res, pugFile) {
        var isAuth = req.isAuthenticated();
        debug('renderPug auth: ' + isAuth + ' file: ' + pugFile);
        res.render(path + '/pug/' + pugFile, {isAuth: isAuth});
    };

    /* loggedIn func from clementine.js. */
	var isLoggedIn = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Redirecting non-auth user to /login');
			return res.redirect('/login');
		}
	};

    /* Returns the username from the request. Logs an error if username is not
     * present. */
    var getUserName = function(req, route) {
        if (req.user) {
            if (req.user.username) {
                return req.user.username;
            }
            else {
                logError(route, 'getUserName: No req.user.username exists.',
                    req);
            }
        }
        else {
            logError(route, 'getUserName: No req.user exists.', req);
        }
        return null;
    };

    var logErrorReq = function(req) {
        console.error('Error REQ headers: ');
        reqDebug(req);
    };

    /* Logs an error with route and request information included.*/
    var logError = function(route, err, req) {
        var date = new Date();
        console.error(date + ' [ERROR@SERVER] route ' + route + ' | ' + err);
        if (req) {
            logErrorReq(req);
        }
    };

    var debugJSON = function(msg, obj) {
        debug(msg + ' ' + JSON.stringify(obj));
    };

    // CONTROLLERS
    var userController = new UserController(path);
    var bookController = new BookController(path);
    var tradeController = new TradeController(path);

    var bookSearch = new BookSearch({apiKey: process.env.API_KEY});

    //----------------------------------------------------------------------
    // ROUTES
    //----------------------------------------------------------------------

	app.route('/')
		.get((req, res) => {
            renderPug(req, res, 'index.pug');
		});

	app.route('/about')
		.get((req, res) => {
            renderPug(req, res, 'about.pug');
		});

	app.route('/allbooks')
		.get((req, res) => {
            renderPug(req, res, 'books.pug');
		});

	app.route('/signup')
		.get((req, res) => {
            renderPug(req, res, 'signup.pug');
		});

	app.route('/login')
		.get((req, res) => {
            renderPug(req, res, 'login.pug');
		});

	app.route('/loginFailed')
		.get((req, res) => {
            res.render(path + '/pug/login.pug',
                {isAuth: false, loginFailed: true});
        });

    // If a user logs out, return to main page
	app.route('/logout')
		.get((req, res) => {
			req.logout();
			res.redirect('/');
		});

	app.route('/profile')
		.get(isLoggedIn, (req, res) => {
            renderPug(req, res, 'profile.pug');
		});

    // Handle registration of user
    app.route('/forms/signup')
        .post((req, res) => {
            debug('Got a signup form GET request..');
            userController.addLocalUser(req, res);
        });

    // Called by client to check their authentication status
	app.route('/amiauth')
		.get((req, res) => {
            var data = {isAuth: false};
            if (req.isAuthenticated()) {
                data.isAuth = true;
                data.username = req.user.username;
                userController.getUserID(data.username, (err, userID) => {
                    if (err) {
                        logError('/amiauth', err, req);
                        res.status(500).json({error: 'Failed to authenticate'});
                    }
                    else {
                        data.userID = userID;
                        res.status(200).json(data);
                    }
                });
            }
            else {
                res.status(200).json(data);
            }
		});

    //----------------------------------
    // Routes for manipulating user data
    //----------------------------------

    app.route('/user/:name')
        .get(isLoggedIn, (req, res) => {
            var username = req.params.name;
            if (username === req.user.username) {
                userController.getUserByName(username, (err, data) => {
                    if (err) {
                        logError('/user/' + username, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        delete data.local.password;
                        res.json(data);
                    }
                });
            }
            else {
                // Forbidden
                logError('/user/' + username,
                    'Forbidden action attempted.', req);
                res.status(403).json(errorForbidden);
            }
        });

    app.route('/user/update')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/user/update');
            var userInfo = req.body;
            debugJSON('/user/update ' + _u(username) + ' info: ', userInfo);
            userController.updateUserInfo(username, userInfo, (err, data) => {
                if (err) {
                    logError('/user/update', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.json(data);
                }
            });
        });

    //--------------------------------------
    // Routes for the book data
    //--------------------------------------
    app.route('/book')

        .get(isLoggedIn, (req, res) => {
            var username = req.user.username;
            bookController.getBooks(username, (err, data) => {
                if (err) {
                    logError('GET /book/', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(data);
                }
            });
        })

        .post(isLoggedIn, (req, res) => {
            var username = req.body.username;
            var book = req.body.book;
            _log('Server got POST-req to /book. User: ' + _u(username));

            if (username === req.user.username) {
                var bookData = {username: username, book: book};
                bookController.addBook(bookData, (err, bookData) => {
                    if (err) {
                        var title = book.volumeInfo.title;
                        logError('POST /book/' + title, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        debug('bookData is ' + JSON.stringify(bookData));
                        res.status(200).json(bookData);
                    }
                });
            }
            else {
                res.status(403).json(notAuthorized);
            }

        })

        .delete(isLoggedIn, (req, res) => {
            if (req.body) {
                var bookData = req.body;
                var updateObj = {
                    username: req.user.username,
                    book: bookData
                };
                debug('Server got DELETE-req to /book. Data: '
                    + JSON.stringify(bookData));
                bookController.deleteBook(updateObj, (err) => {
                    if (err) {
                        logError('DELETE /book/' + bookData, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        res.status(200).json({msg: 'OK'});
                    }
                });
            }
            else {
                res.status(400).json({msg: 'No proper body in DELETE'});
            }

        });

    /* Route for handling book searches via external API.*/
    app.route('/books/search')
        .post(isLoggedIn, (req, res) => {
            var username = req.user.username;
            var search = req.body.search;
            debugJSON('/POST /books/search ', req.body);

            if (search) {
                bookSearch.search({word: search}, (err, data) => {
                        if (err) {
                            logError('POST /books/search with ' + username);
                            res.status(500).json(errorInternal);

                        }
                        else {
                            res.status(200).json(data);
                        }
                    });
            }
            else {
                res.status(400).json({msg: 'search post-param not found'});
            }

        });

    /* Returns all books owned by the given user. */
    app.route('/books/:username')
        .get(isLoggedIn, (req, res) => {
            var username = req.params.username;
            debug('/books/:username with ' + username);
            bookController.getBooksForUser(username, (err, books) => {
                if (err) {
                    logError('GET /books/:username with ' + username);
                    res.status(500).json(errorInternal);
                }
                else {
                    var respObj = {books: books};
                    res.status(200).json(respObj);
                }
            });
        });

    //----------------------------------
    // Routes for Trade Requests
    //----------------------------------

    /* Accepts tradeReq. */
    app.route('/tradereq/accept')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq/accept');
            tradeController.acceptTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq/accept', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debug('accept user ' + _u(username));
                    res.status(200).json(requestOk);
                }

            });

        });

    /* Rejects tradeReq. */
    app.route('/tradereq/reject')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, 'tradereq/reject');
            tradeController.rejectTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq/reject', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debug('reject user ' + _u(username));
                    res.status(200).json(requestOk);
                }
            });
        });

    /* Add/delete tradeReqs. */
    app.route('/tradereq')

        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq');
            tradeController.addTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(requestOk);
                }
            });
        })

        .delete(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq');
            debug('delete /tradereq, for user ' + _u(username));
            tradeController.removeTradeReq(username, req.body, err => {
                if (err) {
                    logError('DELETE /tradereq', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(requestOk);
                }
            });
        });

    //--------------------------------------
    // User registration and authentication
    //--------------------------------------

	app.route('/api/:id')
		.get((req, res) => {
            userController.getUser(req, res);
		});

    // Logs user in via form (after successful authentication
	app.route('/auth/userlogin')
        .post(passport.authenticate('local',
            { failureRedirect: '/loginFailed' }),
		(req, res) => {
			res.redirect('/');
		});

};
<commit_msg>Renamed API endpoints, user -> users, book -> books.<commit_after>'use strict';

var path = process.cwd();
var ctrlPath = path + '/server/ctrl';

const UserController = require(ctrlPath + '/user-ctrl.server.js');
const BookController = require(ctrlPath + '/book-ctrl.server.js');
const TradeController = require(ctrlPath + '/trade-ctrl.server.js');
const BookSearch = require('../common/book-search');
const debug = require('debug')('book:routes');

var _log = function(msg) {
    console.log('[LOG@SERVER]: ' + msg);
};

/* Function for debug logging requests.*/
var reqDebug = function(req) {
	_log('\t\tHeaders: ' + JSON.stringify(req.headers));
	_log('\t\tBody: ' + JSON.stringify(req.body));
	_log('\t\tParams: ' + JSON.stringify(req.params));
	_log('\t\tUrl:' + JSON.stringify(req.url));
	_log('\t\tText:' + JSON.stringify(req.text));
	_log('\t\tContent:' + JSON.stringify(req.content));
	_log('\t\tQuery:' + JSON.stringify(req.query));
};

const _u = function(username) {
    return '|' + username + '|';
};

// Msg objects sent back to the client
var notAuthorized = {msg: 'Operation not authorized. Log in first.'};
var errorInternal = {msg: 'Server internal error.'};
var errorForbidden = {msg: 'Requested action forbidden.'};
var requestOk = {msg: 'Request was completed OK.'};

/* Contains all routes for this application. */
module.exports = function(app, passport) {

    /* Renders a pug template.*/
    var renderPug = function(req, res, pugFile) {
        var isAuth = req.isAuthenticated();
        debug('renderPug auth: ' + isAuth + ' file: ' + pugFile);
        res.render(path + '/pug/' + pugFile, {isAuth: isAuth});
    };

    /* loggedIn func from clementine.js. */
	var isLoggedIn = function(req, res, next) {
		if (req.isAuthenticated()) {
			return next();
		}
        else {
            debug('Redirecting non-auth user to /login');
			return res.redirect('/login');
		}
	};

    /* Returns the username from the request. Logs an error if username is not
     * present. */
    var getUserName = function(req, route) {
        if (req.user) {
            if (req.user.username) {
                return req.user.username;
            }
            else {
                logError(route, 'getUserName: No req.user.username exists.',
                    req);
            }
        }
        else {
            logError(route, 'getUserName: No req.user exists.', req);
        }
        return null;
    };

    var logErrorReq = function(req) {
        console.error('Error REQ headers: ');
        reqDebug(req);
    };

    /* Logs an error with route and request information included.*/
    var logError = function(route, err, req) {
        var date = new Date();
        console.error(date + ' [ERROR@SERVER] route ' + route + ' | ' + err);
        if (req) {
            logErrorReq(req);
        }
    };

    var debugJSON = function(msg, obj) {
        debug(msg + ' ' + JSON.stringify(obj));
    };

    // CONTROLLERS
    var userController = new UserController(path);
    var bookController = new BookController(path);
    var tradeController = new TradeController(path);

    var bookSearch = new BookSearch({apiKey: process.env.API_KEY});

    //----------------------------------------------------------------------
    // ROUTES
    //----------------------------------------------------------------------

	app.route('/')
		.get((req, res) => {
            renderPug(req, res, 'index.pug');
		});

	app.route('/about')
		.get((req, res) => {
            renderPug(req, res, 'about.pug');
		});

	app.route('/allbooks')
		.get((req, res) => {
            renderPug(req, res, 'books.pug');
		});

	app.route('/signup')
		.get((req, res) => {
            renderPug(req, res, 'signup.pug');
		});

	app.route('/login')
		.get((req, res) => {
            renderPug(req, res, 'login.pug');
		});

	app.route('/loginFailed')
		.get((req, res) => {
            res.render(path + '/pug/login.pug',
                {isAuth: false, loginFailed: true});
        });

    // If a user logs out, return to main page
	app.route('/logout')
		.get((req, res) => {
			req.logout();
			res.redirect('/');
		});

	app.route('/profile')
		.get(isLoggedIn, (req, res) => {
            renderPug(req, res, 'profile.pug');
		});

    // Handle registration of user
    app.route('/forms/signup')
        .post((req, res) => {
            debug('Got a signup form GET request..');
            userController.addLocalUser(req, res);
        });

    //----------------------------------------------------
    // /users/ Routes for accessing/manipulating user data
    //----------------------------------------------------

    // Called by client to check their authentication status
	app.route('/users/amiauth')
		.get((req, res) => {
            var data = {isAuth: false};
            if (req.isAuthenticated()) {
                data.isAuth = true;
                data.username = req.user.username;
                userController.getUserID(data.username, (err, userID) => {
                    if (err) {
                        logError('/users/amiauth', err, req);
                        res.status(500).json({error: 'Failed to authenticate'});
                    }
                    else {
                        data.userID = userID;
                        res.status(200).json(data);
                    }
                });
            }
            else {
                res.status(200).json(data);
            }
		});

    app.route('/users/:name')
        .get(isLoggedIn, (req, res) => {
            var username = req.params.name;
            if (username === req.user.username) {
                userController.getUserByName(username, (err, data) => {
                    if (err) {
                        logError('/users/' + username, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        delete data.local.password;
                        res.json(data);
                    }
                });
            }
            else {
                // Forbidden
                logError('/users/' + username,
                    'Forbidden action attempted.', req);
                res.status(403).json(errorForbidden);
            }
        });

    app.route('/users/update')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/user/update');
            var userInfo = req.body;
            debugJSON('/users/update ' + _u(username) + ' info: ', userInfo);
            userController.updateUserInfo(username, userInfo, (err, data) => {
                if (err) {
                    logError('/users/update', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.json(data);
                }
            });
        });

    //--------------------------------------
    // Routes for the book data
    //--------------------------------------
    app.route('/books')

        .get(isLoggedIn, (req, res) => {
            var username = req.user.username;
            bookController.getBooks(username, (err, data) => {
                if (err) {
                    logError('GET /books/', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(data);
                }
            });
        })

        .post(isLoggedIn, (req, res) => {
            var username = req.body.username;
            var book = req.body.book;
            _log('Server got POST-req to /books. User: ' + _u(username));

            if (username === req.user.username) {
                var bookData = {username: username, book: book};
                bookController.addBook(bookData, (err, bookData) => {
                    if (err) {
                        var title = book.volumeInfo.title;
                        logError('POST /books/' + title, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        debug('bookData is ' + JSON.stringify(bookData));
                        res.status(200).json(bookData);
                    }
                });
            }
            else {
                res.status(403).json(notAuthorized);
            }

        })

        .delete(isLoggedIn, (req, res) => {
            if (req.body) {
                var bookData = req.body;
                var updateObj = {
                    username: req.user.username,
                    book: bookData
                };
                debug('Server got DELETE-req to /books. Data: '
                    + JSON.stringify(bookData));
                bookController.deleteBook(updateObj, (err) => {
                    if (err) {
                        logError('DELETE /books/' + bookData, err, req);
                        res.status(500).json(errorInternal);
                    }
                    else {
                        res.status(200).json({msg: 'OK'});
                    }
                });
            }
            else {
                res.status(400).json({msg: 'No proper body in DELETE'});
            }

        });

    /* Route for handling book searches via external API.*/
    app.route('/books/search')
        .post(isLoggedIn, (req, res) => {
            var username = req.user.username;
            var search = req.body.search;
            debugJSON('/POST /books/search ', req.body);

            if (search) {
                bookSearch.search({word: search}, (err, data) => {
                        if (err) {
                            logError('POST /books/search with ' + username);
                            res.status(500).json(errorInternal);

                        }
                        else {
                            res.status(200).json(data);
                        }
                    });
            }
            else {
                res.status(400).json({msg: 'search post-param not found'});
            }

        });

    /* Returns all books owned by the given user. */
    app.route('/books/:username')
        .get(isLoggedIn, (req, res) => {
            var username = req.params.username;
            debug('/books/:username with ' + username);
            bookController.getBooksForUser(username, (err, books) => {
                if (err) {
                    logError('GET /books/:username with ' + username);
                    res.status(500).json(errorInternal);
                }
                else {
                    var respObj = {books: books};
                    res.status(200).json(respObj);
                }
            });
        });

    //----------------------------------
    // Routes for Trade Requests
    //----------------------------------

    /* Accepts tradeReq. */
    app.route('/tradereq/accept')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq/accept');
            tradeController.acceptTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq/accept', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debug('accept user ' + _u(username));
                    res.status(200).json(requestOk);
                }

            });

        });

    /* Rejects tradeReq. */
    app.route('/tradereq/reject')
        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, 'tradereq/reject');
            tradeController.rejectTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq/reject', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    debug('reject user ' + _u(username));
                    res.status(200).json(requestOk);
                }
            });
        });

    /* Add/delete tradeReqs. */
    app.route('/tradereq')

        .post(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq');
            tradeController.addTradeReq(username, req.body, err => {
                if (err) {
                    logError('POST /tradereq', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(requestOk);
                }
            });
        })

        .delete(isLoggedIn, (req, res) => {
            var username = getUserName(req, '/tradereq');
            debug('delete /tradereq, for user ' + _u(username));
            tradeController.removeTradeReq(username, req.body, err => {
                if (err) {
                    logError('DELETE /tradereq', err, req);
                    res.status(500).json(errorInternal);
                }
                else {
                    res.status(200).json(requestOk);
                }
            });
        });

    //--------------------------------------
    // User registration and authentication
    //--------------------------------------

    // Logs user in via form (after successful authentication)
	app.route('/auth/userlogin')
        .post(passport.authenticate('local',
            { failureRedirect: '/loginFailed' }), (req, res) => {
			res.redirect('/');
		});

};
<|endoftext|>