<commit_before>'use strict';

var util = require('util');

var re4Integer = '-?(?:0|[1-9][0-9]*)';

var re = exports.re = {
    identifier: new RegExp('^[a-zA-Z_\\$]+[a-zA-Z0-9_]*'),
    integer: new RegExp(re4Integer),
    range: new RegExp(util.format('^(%s)?\\:(%s)?(?:\\:(%s)?)?', re4Integer, re4Integer, re4Integer)),
    q_string: new RegExp('^\'(?:\\\\[\'bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\'\\\\])*\''),
    qq_string: new RegExp('^\"(?:\\\\[\"bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\"\\\\])*\"')
};

var types = {
    ROOT: {
        type: 'root'
    },
    WILDCARD: {
        type: 'wildcard'
    },
    RECURSIVE_DESCENT: {
        type: 'recursive_descent'
    },
    PARENT: {
        type: 'parent'
    }
};

var propertyUpdate = {
    identifier: function (properties, reExecResult) {
        properties.push(reExecResult[0]);
    },
    integer: function (properties, reExecResult) {
        var i = parseInt(reExecResult[0], 10);
        properties.push(i);
    },
    q_string: function (properties, reExecResult) {
        var r = reExecResult[0];
        properties.push(r.substring(1, r.length - 1));
    },
    qq_string: function (properties, reExecResult) {
        var r = reExecResult[0];
        properties.push(r.substring(1, r.length - 1));
    },
    range: function (properties, reExecResult) {
        var start = (reExecResult[1] && parseInt(reExecResult[1], 10)) || 0;
        var end = (reExecResult[2] && parseInt(reExecResult[2], 10)) || null;
        var step = (reExecResult[3] && parseInt(reExecResult[3], 10)) || 1;
        properties.push({
            start: start,
            end: end,
            step: step
        });
    }
};

var expandSubscriptProperties = exports.expandSubscriptProperties = function expandSubscriptProperties(subscript, properties) {
    var reKeys = ['range', 'identifier', 'integer', 'q_string', 'qq_string'];
    var n = reKeys.length;
    for (var i = 0; i < n; ++i) {
        var key = reKeys[i];
        var r = re[key];
        var result = r.exec(subscript);
        if (result) {
            propertyUpdate[key](properties, result);
            var nResult = result[0].length;
            if (nResult === subscript.length) {
                return true;
            }
            if (subscript[nResult] !== ',') {
                var msg = util.format('Invalid character "%s" in %s.', subscript[nResult], subscript);
                throw new Error(msg);
            }
            subscript = subscript.substring(nResult + 1);
            return expandSubscriptProperties(subscript, properties);
        }
    }
    return false;
};

var subscriptHandlers = {
    '$': {
        verify: function (subscript) {
            return (subscript.length > 1) && (subscript.charAt(1) === '.');
        },
        node: function (subscript) {
            return {
                type: 'subpath',
                parameter: subscript
            };
        }
    },
    '?': {
        verify: function (subscript) {
            var n = subscript.length;
            if ((n < 2) || (subscript.charAt(1) !== '(')) {
                throw new Error('Subscript start with "?" but the second character is not "("');
            }
            if (subscript.charAt(n - 1) !== ')') {
                throw new Error('Subscript starts with "?(" but does not end with ")".');
            }
            return true;
        },
        node: function (subscript) {
            var n = subscript.length;
            return {
                type: 'filter_script',
                parameter: subscript.substring(2, n - 1)
            };
        }
    },
    '(': {
        verify: function (subscript) {
            var n = subscript.length;
            if (subscript.charAt(n - 1) !== ')') {
                throw new Error('Subscript starts with "(" but does not end with ")".');
            }
            return true;
        },
        node: function (subscript) {
            var n = subscript.length;
            return {
                type: 'script',
                parameter: subscript.substring(1, n - 1)
            };
        }
    },
    '*': {
        verify: function (subscript) {
            return subscript.length === 1;
        },
        node: function (subscript) {
            return types.WILDCARD;
        }
    }
};

var subscriptToNode = function (subscript) {
    if (subscript.length === 0) {
        throw new Error('Empty subscript in path.');
    }

    var c = subscript.charAt(0);
    var handler = subscriptHandlers[c];
    if (handler && handler.verify(subscript)) {
        return handler.node(subscript);
    }

    var properties = [];
    var result = expandSubscriptProperties(subscript, properties);
    if (result) {
        var single = (properties.length === 1) && (typeof properties[0] !== 'object');
        return {
            type: single ? 'property' : 'properties',
            parameter: single ? properties[0] : properties
        };
    }

    throw new Error('Invalid subscript: ' + subscript);
};

var updateNodesWithProperty = function (property, nodes) {
    var n = property.length;
    if (property.substring(n - 2, n) === '()') {
        nodes.push({
            type: 'fn',
            parameter: property.substring(0, n - 2)
        });
        return;
    }
    nodes.push({
        type: 'property',
        parameter: property
    });
};

var findMatchingSquareBracket = function (path, index) {
    var length = path.length;
    var openBrackets = 1;
    while (index < length) {
        var c = path.charAt(index);
        if (c === '[') {
            ++openBrackets;
            ++index;
        } else if (c === ']') {
            --openBrackets;
            if (openBrackets === 0) {
                return index;
            }
            ++index;
        } else {
            ++index;
        }
    }
    throw new Error('Closing square brackets is not found');
};

var nodeAccumulator = (function () {
    var prototype = {
        pushNode: function (node) {
            this.exprList.push(node);
            ++this.index;
            this.lastIndex = this.index;
        },
        clearBuffer: function () {
            if (this.lastIndex < this.index) {
                var subExpr = this.expr.substring(this.lastIndex, this.index);
                updateNodesWithProperty(subExpr, this.exprList);
            }
        },
        '.': function () {
            this.clearBuffer();
            ++this.index;
            this.lastIndex = this.index;
            var cp1 = this.expr.charAt(this.index);
            if (cp1 === '.') {
                this.exprList.push(types.RECURSIVE_DESCENT);
                ++this.index;
                this.lastIndex = this.index;
            } else if (this.index === this.length) {
                throw new Error('Incomplete path.');
            }
            if (this.expr.charAt(this.index) === '.') {
                throw new Error('Invalid syntax "...".');
            }
            return true;
        },
        '[': function () {
            this.clearBuffer();
            ++this.index;
            this.lastIndex = this.index;
            this.index = findMatchingSquareBracket(this.expr, this.index);
            var subExprInside = this.expr.substring(this.lastIndex, this.index);
            var scriptResult = subscriptToNode(subExprInside);
            this.pushNode(scriptResult);
            return true;
        },
        '*': function () {
            if (this.lastIndex === this.index) {
                this.pushNode(types.WILDCARD);
                return true;
            } else {
                return false;
            }
        },
        '$': function () {
            if ((this.index === 0) && (this.expr.charAt(1) === '.')) {
                this.pushNode(types.ROOT);
                return true;
            } else {
                return false;
            }
        },
        '^': function () {
            this.clearBuffer();
            this.pushNode(types.PARENT);
            return true;
        }
    };

    return function (expr) {
        var result = Object.create(prototype);
        result.expr = expr;
        result.exprList = [];
        result.index = 0;
        result.length = expr.length;
        result.lastIndex = 0;
        return result;
    };
})();

exports.normalize = function (expr) {
    var accum = nodeAccumulator(expr);
    while (accum.index < accum.length) {
        var c = expr.charAt(accum.index);
        var handler = accum[c];
        if (handler) {
            var r = handler.call(accum);
            if (r) {
                continue;
            }
        }
        ++accum.index;
    }
    accum.clearBuffer();
    return accum.exprList;
};
<commit_msg>code cleaning<commit_after>'use strict';

var util = require('util');

var re4Integer = '-?(?:0|[1-9][0-9]*)';

var re = exports.re = {
    identifier: new RegExp('^[a-zA-Z_\\$]+[a-zA-Z0-9_]*'),
    integer: new RegExp(re4Integer),
    range: new RegExp(util.format('^(%s)?\\:(%s)?(?:\\:(%s)?)?', re4Integer, re4Integer, re4Integer)),
    q_string: new RegExp('^\'(?:\\\\[\'bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\'\\\\])*\''),
    qq_string: new RegExp('^\"(?:\\\\[\"bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\"\\\\])*\"')
};

var types = {
    ROOT: {
        type: 'root'
    },
    WILDCARD: {
        type: 'wildcard'
    },
    RECURSIVE_DESCENT: {
        type: 'recursive_descent'
    },
    PARENT: {
        type: 'parent'
    }
};

var propertyUpdate = {
    identifier: function (properties, reExecResult) {
        properties.push(reExecResult[0]);
    },
    integer: function (properties, reExecResult) {
        var i = parseInt(reExecResult[0], 10);
        properties.push(i);
    },
    q_string: function (properties, reExecResult) {
        var r = reExecResult[0];
        properties.push(r.substring(1, r.length - 1));
    },
    qq_string: function (properties, reExecResult) {
        var r = reExecResult[0];
        properties.push(r.substring(1, r.length - 1));
    },
    range: function (properties, reExecResult) {
        var start = (reExecResult[1] && parseInt(reExecResult[1], 10)) || 0;
        var end = (reExecResult[2] && parseInt(reExecResult[2], 10)) || null;
        var step = (reExecResult[3] && parseInt(reExecResult[3], 10)) || 1;
        properties.push({
            start: start,
            end: end,
            step: step
        });
    }
};

var expandSubscriptProperties = exports.expandSubscriptProperties = function expandSubscriptProperties(subscript, properties) {
    var reKeys = ['range', 'identifier', 'integer', 'q_string', 'qq_string'];
    var n = reKeys.length;
    for (var i = 0; i < n; ++i) {
        var key = reKeys[i];
        var r = re[key];
        var result = r.exec(subscript);
        if (result) {
            propertyUpdate[key](properties, result);
            var nResult = result[0].length;
            if (nResult === subscript.length) {
                return true;
            }
            if (subscript[nResult] !== ',') {
                var msg = util.format('Invalid character "%s" in %s.', subscript[nResult], subscript);
                throw new Error(msg);
            }
            subscript = subscript.substring(nResult + 1);
            return expandSubscriptProperties(subscript, properties);
        }
    }
    return false;
};

var subscriptHandlers = {
    '$': {
        verify: function (subscript) {
            return (subscript.length > 1) && (subscript.charAt(1) === '.');
        },
        node: function (subscript) {
            return {
                type: 'subpath',
                parameter: subscript
            };
        }
    },
    '?': {
        verify: function (subscript) {
            var n = subscript.length;
            if ((n < 2) || (subscript.charAt(1) !== '(')) {
                throw new Error('Subscript start with "?" but the second character is not "("');
            }
            if (subscript.charAt(n - 1) !== ')') {
                throw new Error('Subscript starts with "?(" but does not end with ")".');
            }
            return true;
        },
        node: function (subscript) {
            var n = subscript.length;
            return {
                type: 'filter_script',
                parameter: subscript.substring(2, n - 1)
            };
        }
    },
    '(': {
        verify: function (subscript) {
            var n = subscript.length;
            if (subscript.charAt(n - 1) !== ')') {
                throw new Error('Subscript starts with "(" but does not end with ")".');
            }
            return true;
        },
        node: function (subscript) {
            var n = subscript.length;
            return {
                type: 'script',
                parameter: subscript.substring(1, n - 1)
            };
        }
    },
    '*': {
        verify: function (subscript) {
            return subscript.length === 1;
        },
        node: function (subscript) {
            return types.WILDCARD;
        }
    }
};

var subscriptToNode = function (subscript) {
    if (subscript.length === 0) {
        throw new Error('Empty subscript in path.');
    }

    var c = subscript.charAt(0);
    var handler = subscriptHandlers[c];
    if (handler && handler.verify(subscript)) {
        return handler.node(subscript);
    }

    var properties = [];
    var result = expandSubscriptProperties(subscript, properties);
    if (result) {
        var single = (properties.length === 1) && (typeof properties[0] !== 'object');
        return {
            type: single ? 'property' : 'properties',
            parameter: single ? properties[0] : properties
        };
    }

    throw new Error('Invalid subscript: ' + subscript);
};

var updateNodesWithProperty = function (property, nodes) {
    var n = property.length;
    if (property.substring(n - 2, n) === '()') {
        nodes.push({
            type: 'fn',
            parameter: property.substring(0, n - 2)
        });
        return;
    }
    nodes.push({
        type: 'property',
        parameter: property
    });
};

var findMatchingSquareBracket = function (path, index) {
    var length = path.length;
    var openBrackets = 1;
    while (index < length) {
        var c = path.charAt(index);
        if (c === '[') {
            ++openBrackets;
            ++index;
        } else if (c === ']') {
            --openBrackets;
            if (openBrackets === 0) {
                return index;
            }
            ++index;
        } else {
            ++index;
        }
    }
    throw new Error('Closing square brackets is not found');
};

var propertyHandlers = {
    '.': {
        verify: function (accum) {
            if (accum.index + 1 === accum.length) {
                throw new Error('Incomplete path.');
            }
            if ((accum.expr.charAt(accum.index + 1) === '.') && (accum.expr.charAt(accum.index + 2) === '.')) {
                throw new Error('Invalid syntax "...".');
            }
            return true;
        },
        update: function (accum) {
            accum.clearBuffer();
            ++accum.index;
            accum.lastIndex = accum.index;
            if (accum.expr.charAt(accum.index) === '.') {
                accum.pushNode(types.RECURSIVE_DESCENT);
            }
        }
    },
    '[': {
        verify: function (accum) {
            return true;
        },
        update: function (accum) {
            accum.clearBuffer();
            ++accum.index;
            accum.lastIndex = accum.index;
            accum.index = findMatchingSquareBracket(accum.expr, accum.index);
            var subExprInside = accum.expr.substring(accum.lastIndex, accum.index);
            var scriptResult = subscriptToNode(subExprInside);
            accum.pushNode(scriptResult);
        }
    },
    '*': {
        verify: function (accum) {
            return accum.lastIndex === accum.index;
        },
        update: function (accum) {
            accum.pushNode(types.WILDCARD);
        }
    },
    '$': {
        verify: function (accum) {
            return (accum.index === 0) && (accum.expr.charAt(1) === '.');
        },
        update: function (accum) {
            accum.pushNode(types.ROOT);
        }
    },
    '^': {
        verify: function (accum) {
            return true;
        },
        update: function (accum) {
            accum.clearBuffer();
            accum.pushNode(types.PARENT);
        }
    }
};

var nodeAccumulator = (function () {
    var prototype = {
        pushNode: function (node) {
            this.exprList.push(node);
            ++this.index;
            this.lastIndex = this.index;
        },
        clearBuffer: function () {
            if (this.lastIndex < this.index) {
                var subExpr = this.expr.substring(this.lastIndex, this.index);
                updateNodesWithProperty(subExpr, this.exprList);
            }
        }
    };

    return function (expr) {
        var result = Object.create(prototype);
        result.expr = expr;
        result.exprList = [];
        result.index = 0;
        result.length = expr.length;
        result.lastIndex = 0;
        return result;
    };
})();

exports.normalize = function (expr) {
    var accum = nodeAccumulator(expr);
    while (accum.index < accum.length) {
        var c = expr.charAt(accum.index);
        var handler = propertyHandlers[c];
        if (handler && handler.verify(accum)) {
            handler.update(accum);
        } else {
            ++accum.index;
        }
    }
    accum.clearBuffer();
    return accum.exprList;
};
<|endoftext|>


<commit_before>module.exports = setup;

function setup(app) {
	setInterval(function () {
		var models = app.get('models');
		var sql = 'SELECT * FROM tags t JOIN issue_tags it ON it.tagId = t.name JOIN issues i ON it.issueId = i.id';

		models._sequelize.query(sql, models.Tag)
			.success(function (tags) {
				ingest(app, tags);
			});
	}, 30 * 1000);
}

function ingest(app, tags) {
	getInstagramMedia(app, tags, function (err, media) {
		if (err) {
			console.log('error getting instagram media');
			console.log(err);
			return;
		}

		console.log('retrieved ' + media.length + ' media');

		importInstagramMedia(app, media, function (err, media) {
			if (err) {
				console.log('error importing media');
				console.log(err);
				return;
			}

			console.log('created ' + media.length + ' new media items');
		});
	});
}

function getInstagramMedia(app, tags, callback) {
	var inst = app.get('instagram');

	var results = [];
	var errors = [];
	var count = 0;

	for (var i = 0; i < tags.length; i++) {
		inst.tags.recent({
			name: tags[i].name,

			error: function (errorMessage, errorObject, caller) {
				errors.push(errorMessage);
				check();
			},

			complete: function (media, pagination) {
				results.push(media);
				check();
			}
		});
	}

	function check() {
		if (count !== tags.length)
			return;

		if (errors.length) {
			var err = new Error('Failed to retrieve media');
			err.innerErrors = errors;
			callback(err);
			return;
		}

		var media = [];
		for (var i = 0; i < results.length; i++)
			media = media.concat(results[i]);

		callback(null, media);
	}
}

function importInstagramMedia(app, media, callback) {
	var tagsNeeded = [];
	for (var i = 0; i < media.length; i++)
		tagsNeeded = tagsNeeded.concat(media[i].tags);

	getTags(app, tagsNeeded, function (err, tags) {
		if (err) {
			callback(err);
			return;
		}

		var results = [];
		var errors = [];
		var count = 0;

		for (var i = 0; i < media.length; i++) {
			createMedium(app, tags, media[i], function (err, medium) {
				count++;

				if (err) {
					if (err.code !== 'ER_DUP_ENTRY')
						errors.push(err);
				} else {
					results.push(medium);
				}

				if (count === media.length) {
					if (errors.length) {
						var err = new Error('Failed to import media');
						err.innerErrors = errors;
						callback(err);
						return;
					}

					callback(null, results);
				}
			});
		}
	});
}

function getTags(app, tags, callback) {
	var models = app.get('models');

	models.Tag.findAll()
		.error(callback)
		.success(function (existingTags) {
			// deduplicate
			tags = tags.filter(function (obj, pos, arr) {
				return arr.indexOf(obj) == pos;
			});

			// remove existing
			for (var i = 0; i < existingTags.length; i++) {
				var j = tags.indexOf(existingTags[i].name);
				if (j > -1) tags[j] = null;
			}

			var cleanedTags = [];
			for (var i = 0; i < tags.length; i++)
				if (tags[i])
					cleanedTags.push(tags[i]);
			tags = cleanedTags;
			delete cleanedTags;

			// create new tags
			tags = tags.map(function (t) { return { name: t }; });

			models.Tag.bulkCreate(tags)
				.error(callback)
				.success(function (newTags) {
					tags = existingTags.concat(newTags);

					// array<Tag> -> map<string, Tag>
					tagMap = {};
					for (var i = 0; i < tags.length; i++)
						tagMap[tags[i].name] = tags[i];
					tags = tagMap;
					delete tagMap;

					callback(null, tagMap);
				});
		});
}

function createMedium(app, tags, medium, callback) {
	var thumb = medium.images.thumbnail.url;
	var standard = medium.images.standard_resolution.url;

	var obj = {
		instagramId: medium.id,
		date: new Date(medium.created_time * 1000),
		thumbnailUrl: thumb,
		imageUrl: standard
	};

	models.Media.create(obj)
		.error(callback)
		.success(function (medium, created) {
			var mediumTags = [];
			for (var i = 0; i < medium.tags.length; i++)
			 	mediumTags.push(tags[medium.tags[i]]);

			medium.setTags(medium)
				.error(callback)
				.success(function () {
					callback(null, medium);
				});
		});
}
<commit_msg>no message<commit_after>module.exports = setup;

function setup(app) {
	setInterval(function () {
		var models = app.get('models');
		var sql = 'SELECT * FROM tags t JOIN issue_tags it ON it.tagId = t.name JOIN issues i ON it.issueId = i.id';

		models._sequelize.query(sql, models.Tag)
			.success(function (tags) {
				ingest(app, tags);
			});
	}, 30 * 1000);
}

function ingest(app, tags) {
	getInstagramMedia(app, tags, function (err, media) {
		if (err) {
			console.log('error getting instagram media');
			console.log(err);
			return;
		}

		console.log('retrieved ' + media.length + ' media');

		importInstagramMedia(app, media, function (err, media) {
			if (err) {
				console.log('error importing media');
				console.log(err);
				return;
			}

			console.log('created ' + media.length + ' new media items');
		});
	});
}

function getInstagramMedia(app, tags, callback) {
	var inst = app.get('instagram');

	var results = [];
	var errors = [];
	var count = 0;

	for (var i = 0; i < tags.length; i++) {
		inst.tags.recent({
			name: tags[i].name,

			error: function (errorMessage, errorObject, caller) {
				errors.push(errorMessage);
				check();
			},

			complete: function (media, pagination) {
				results.push(media);
				check();
			}
		});
	}

	function check() {
		count++;

		if (count !== tags.length)
			return;

		if (errors.length) {
			var err = new Error('Failed to retrieve media');
			err.innerErrors = errors;
			callback(err);
			return;
		}

		var media = [];
		for (var i = 0; i < results.length; i++)
			media = media.concat(results[i]);

		callback(null, media);
	}
}

function importInstagramMedia(app, media, callback) {
	var tagsNeeded = [];
	for (var i = 0; i < media.length; i++)
		tagsNeeded = tagsNeeded.concat(media[i].tags);

	getTags(app, tagsNeeded, function (err, tags) {
		if (err) {
			callback(err);
			return;
		}

		var results = [];
		var errors = [];
		var count = 0;

		for (var i = 0; i < media.length; i++) {
			createMedium(app, tags, media[i], function (err, medium) {
				count++;

				if (err) {
					if (err.code !== 'ER_DUP_ENTRY')
						errors.push(err);
				} else {
					results.push(medium);
				}

				if (count === media.length) {
					if (errors.length) {
						var err = new Error('Failed to import media');
						err.innerErrors = errors;
						callback(err);
						return;
					}

					callback(null, results);
				}
			});
		}
	});
}

function getTags(app, tags, callback) {
	var models = app.get('models');

	models.Tag.findAll()
		.error(callback)
		.success(function (existingTags) {
			// deduplicate
			tags = tags.filter(function (obj, pos, arr) {
				return arr.indexOf(obj) == pos;
			});

			// remove existing
			for (var i = 0; i < existingTags.length; i++) {
				var j = tags.indexOf(existingTags[i].name);
				if (j > -1) tags[j] = null;
			}

			var cleanedTags = [];
			for (var i = 0; i < tags.length; i++)
				if (tags[i])
					cleanedTags.push(tags[i]);
			tags = cleanedTags;
			delete cleanedTags;

			// create new tags
			tags = tags.map(function (t) { return { name: t }; });

			models.Tag.bulkCreate(tags)
				.error(callback)
				.success(function (newTags) {
					tags = existingTags.concat(newTags);

					// array<Tag> -> map<string, Tag>
					tagMap = {};
					for (var i = 0; i < tags.length; i++)
						tagMap[tags[i].name] = tags[i];
					tags = tagMap;
					delete tagMap;

					callback(null, tagMap);
				});
		});
}

function createMedium(app, tags, medium, callback) {
	var thumb = medium.images.thumbnail.url;
	var standard = medium.images.standard_resolution.url;

	var obj = {
		instagramId: medium.id,
		date: new Date(medium.created_time * 1000),
		thumbnailUrl: thumb,
		imageUrl: standard
	};

	models.Media.create(obj)
		.error(callback)
		.success(function (medium, created) {
			var mediumTags = [];
			for (var i = 0; i < medium.tags.length; i++)
			 	mediumTags.push(tags[medium.tags[i]]);

			medium.setTags(medium)
				.error(callback)
				.success(function () {
					callback(null, medium);
				});
		});
}
<|endoftext|>


<commit_before>var express = require("express");
var app = express();

// fucking dependencies
var bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
var session = require('express-session');
var path = require('path');
var async = require('async');
var UAParser = require('ua-parser-js');
var md = require("node-markdown").Markdown;
var fs = require("fs");

require('colors');	// for fantastic debug

// setting app -> too dizzy to fuck with
app.use(cookieParser());
app.use(session({ secret: "secret" }));

var set = require('./setting.json');
var options = process.argv;

for( num in options){
	if(options[num] == "--port" || options[num] == "-p"){
		set.port = options[Number(num)+1];
	}
}

app.set("view engine", "ejs");
app.set("views", __dirname+"/app/views");
app.use( express.static( __dirname + "/public" ));
app.use(bodyParser.urlencoded({ extended: false }));

// homemade modules
var auth = require("./auth.js");
auth.init(app);
var passport = auth.getPassport();

require('./database.js')();

// fucking routing
app.get('/auth/fb', passport.authenticate('facebook'));

app.get('/auth/fb/callback',
    passport.authenticate('facebook', {
		successRedirect: '/join',
        failureRedirect: '/loginFail'
	})
);

app.get('/loginSuccess', auth.checkAuthState, function(req, res){
	console.log("로그인성공");
    res.send(req.user);
});
app.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
});

app.route("/")
	.get(auth.inspect, function(req, res){
		var parser = new UAParser();
		var ua = req.headers['user-agent'];
		var browserName = parser.setUA(ua).getBrowser().name;
		var browserVersion = parser.setUA(ua).getBrowser().version.split(".",1).toString();
		// && browserVersion <= 9
		if (browserName == 'IE') {
			res.write("<script>window.open('http://www.opera.com/ko/computer');</script>");
			res.write("<script>window.open('https://www.mozilla.org/ko/firefox/new/');</script>");
			res.end("<script>location.href='https://www.google.com/chrome/browser/desktop/index.html';</script>");
		}

        Works.findAll().then(function(works, err) {
            if(err) console.error(err);
            else {
                res.render("frontpage.ejs", {works: works, login: req.authState, user: req.user});
            }
        });
	})
	.post(function(req, res){
		var workId = req.params.workId;
		Works.findOrCreate({
			where: {
				name: req.body.name,
				desc: req.body.desc
			}
		}).then(function(work, err) {
			if(err) {
				console.error(err);
				console.log("이미있는 공작이다".cyan);
				res.write("<script>alert('이미있는공작입니다')</script>");
				res.redirect('/');
			}
	        else {
				console.log("공작 생성 :".cyan, work.name);
	            res.redirect('/');
	        }
		});
	});

app.route("/join")
	.get(auth.checkAuthState, function(req, res) {
		console.log("REQ", req.user)
		Users.findOne({
			where: {
				"fbId": req.user.fbId
			}
		}).then(function(user, err) {
			console.log(user);
			if(err) console.error("ERROR".red, err);
			else if(user) {
				if(user.nickname == null)
					res.render('join.ejs', {
						name: req.user.name,
						picture: req.user.picture
					});
				else res.redirect('/'); //닉네임 이미 등록됨.
			} else {
				res.redirect('/'); //잘못된 접근: 세션은 인증되어 있는데 해당하는 정보가 DB에 없음
			}
		})
	})
	.post(function(req, res) {
		console.log(req.body);
		Users.findOne({ // 해당 닉네임 있는지 확인
			where: {
				nickname: req.body.nickname
		}}).then(function(user, err) {
			if(err) console.error(err);
			if(!user) { // 가능한 닉네임
				Users.findOne({
					fbId: req.user.fbId, // 현재 세션의 페이스북 uid로 찾는다
				}).then(function(user, err) {
					if(err) console.error(err);
					else if(!user){ // 그 세션의 uid에 해당하는 게 등록 안되어있음 (이상한 케이스)
						res.redirect('/');
					} else {
						user.updateAttributes({ // 찾은 유저정보에서 닉네임을 받은 닉네임으로 바꿔준다
							nickname: req.body.nickname
						}).then(function(user, err) {
							if(err) {
								console.error(err);
								res.status(500).end();
							}
							else {
								console.log("유저 생성 :".cyan, user.name);
								res.status(201).end();
							}
						});
					}
				});
			} else {
				// 이미 존재하는 닉네임
				res.status(409).end();
			}
		})
	});

app.route("/work/:workId/:workName")
	.get(function(req, res){
		var workId = req.params.workId;
		Works.findOne({
			where: {
				id: workId
			}
		}).then(function(work, err) {
			if(err) console.error(err);
			else {
				console.log("공작 조회 :".cyan, work.name);
				res.render("workpage.ejs", {work: work} );
			}
		});
	})
	.post(function(req, res){
		var workId = req.params.workId;

		Works.findOne({
			where: {
				id: workId
			}
		}).then(function(work, err) {
			if(err) console.error(err);
			else {
				fs.mkdir("./WorkPage/"+work.name, function(err){
					console.log(err);
					if (req.body.reqType == "md") {
						var html = md(req.body.md);
						fs.writeFile("./WorkPage/"+work.name+"/front.html", html, function(err){
							if(err) console.log(err);
							work.updateAttributes({
								frontboard: "./WorkPage" + work.name + "/front.html"
							}).then(function(work, err){
								if(err) console.log(err);
								res.redirect("/work/"+work.id+"/"+work.name);
							});
						});
					}
					else if ( req.body.reqType == "need" ) {
						var html = md(req.body.need)
						fs.writeFile("./WorkPage/"+work.name+"/need.html", html, function(err){
							if(err) console.log(err);
							work.updateAttributes({
								needs: "./WorkPage" + work.name + "/need.html"
							}).then(function(work, err){
								if(err) console.log(err);
								res.redirect("/work/"+work.id+"/"+work.name);
							});
						});
					}
				});
			}
		});
	});

app.route("/user/:userNick")
	.get(function(req, res){
		var userNick = req.parmas.userNick;
	})
	.post(function(req, res){
		// edit user information
	});

var server = app.listen(set.port || 8080);
var io = require('socket.io').listen(server);
console.log((set.host+":"+(set.port || 8080)).cyan+"에서 서버 시작".green);

io.sockets.on('connection',function(socket){
	socket.on('client_update_dislike',function(data){
		console.log("get socket request".red);
		console.log("this is id of work".red, data.workId);
		console.log("this is id of user".red, data.userId);

		async.waterfall([
			function(cb){
				Dislike.findOne({
					where: {
						userId: data.workId,
						workId: data.userId
					}
				}).then(function(dislike, err) {
					if(err) console.log(err);

					if(dislike != null){
						cb(true, dislike);
					} else {
						cb(false, dislike);
					}
				});
			},
			function(exist, dislike, cb){
				if(exist){
					Dislike.destroy({
						where: {
							userId: dislike.userId,
							workId: dislike.workId
						}
					}).then(function(){
						console.log("destroy dislike".red);
						cb(null, null);
					});
				} else {
					Dislike.create({
						userId: data.userId,
						workId: data.workId
					}).then(function(){
						console.log("create dislike".red);
						cb(null, null);
					});
				}
			}
		],
		function(err, result){
			socket.broadcast.emit('server_update',data);
		   	// socket.emit('server_update',data);
		});

	});
});

<commit_msg>merging makes me fucking nervous<commit_after>var express = require("express");
var app = express();

// fucking dependencies
var bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
var session = require('express-session');
var path = require('path');
var async = require('async');
var UAParser = require('ua-parser-js');
var md = require("node-markdown").Markdown;
var fs = require("fs");

require('colors');	// for fantastic debug

// setting app -> too dizzy to fuck with
app.use(cookieParser());
app.use(session({ secret: "secret" }));

var set = require('./setting.json');
var options = process.argv;

for( num in options){
	if(options[num] == "--port" || options[num] == "-p"){
		set.port = options[Number(num)+1];
	}
}

app.set("view engine", "ejs");
app.set("views", __dirname+"/app/views");
app.use( express.static( __dirname + "/public" ));
app.use(bodyParser.urlencoded({ extended: false }));

// homemade modules
var auth = require("./auth.js");
auth.init(app);
var passport = auth.getPassport();

require('./database.js')();

// fucking routing
app.get('/auth/fb', passport.authenticate('facebook'));

app.get('/auth/fb/callback',
    passport.authenticate('facebook', {
		successRedirect: '/join',
        failureRedirect: '/loginFail'
	})
);

app.get('/loginSuccess', auth.checkAuthState, function(req, res){
	console.log("로그인성공");
    res.send(req.user);
});
app.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
});

app.route("/")
	.get(auth.inspect, function(req, res){
		var parser = new UAParser();
		var ua = req.headers['user-agent'];
		var browserName = parser.setUA(ua).getBrowser().name;
		var browserVersion = parser.setUA(ua).getBrowser().version.split(".",1).toString();
		// && browserVersion <= 9
		if (browserName == 'IE') {
			res.write("<script>window.open('http://www.opera.com/ko/computer');</script>");
			res.write("<script>window.open('https://www.mozilla.org/ko/firefox/new/');</script>");
			res.end("<script>location.href='https://www.google.com/chrome/browser/desktop/index.html';</script>");
		}

        Works.findAll().then(function(works, err) {
            if(err) console.error(err);
            else {
                res.render("frontpage.ejs", {works: works, login: req.authState, user: req.user});
            }
        });
	})
	.post(function(req, res){
		var workId = req.params.workId;
		Works.findOrCreate({
			where: {
				name: req.body.name,
				desc: req.body.desc
			}
		}).then(function(work, err) {
			if(err) {
				console.error(err);
				console.log("이미있는 공작이다".cyan);
				res.write("<script>alert('이미있는공작입니다')</script>");
				res.redirect('/');
			}
	        else {
				console.log("공작 생성 :".cyan, work.name);
	            res.redirect('/');
	        }
		});
	});

app.route("/join")
	.get(auth.checkAuthState, function(req, res) {
		console.log("REQ", req.user)
		Users.findOne({
			where: {
				"fbId": req.user.fbId
			}
		}).then(function(user, err) {
			console.log(user);
			if(err) console.error("ERROR".red, err);
			else if(user) {
				if(user.nickname == null)
					res.render('join.ejs', {
						name: req.user.name,
						picture: req.user.picture
					});
				else res.redirect('/'); //닉네임 이미 등록됨.
			} else {
				res.redirect('/'); //잘못된 접근: 세션은 인증되어 있는데 해당하는 정보가 DB에 없음
			}
		})
	})
	.post(function(req, res) {
		console.log(req.body);
		Users.findOne({ // 해당 닉네임 있는지 확인
			where: {
				nickname: req.body.nickname
		}}).then(function(user, err) {
			if(err) console.error(err);
			if(!user) { // 가능한 닉네임
				Users.findOne({
					fbId: req.user.fbId, // 현재 세션의 페이스북 uid로 찾는다
				}).then(function(user, err) {
					if(err) console.error(err);
					else if(!user){ // 그 세션의 uid에 해당하는 게 등록 안되어있음 (이상한 케이스)
						res.redirect('/');
					} else {
						user.updateAttributes({ // 찾은 유저정보에서 닉네임을 받은 닉네임으로 바꿔준다
							nickname: req.body.nickname
						}).then(function(user, err) {
							if(err) {
								console.error(err);
								res.status(500).end();
							}
							else {
								console.log("유저 생성 :".cyan, user.name);
								res.status(201).end();
							}
						});
					}
				});
			} else {
				// 이미 존재하는 닉네임
				res.status(409).end();
			}
		})
	});

app.route("/work/:workId/:workName")
	.get(function(req, res){
		var workId = req.params.workId;
		Works.findOne({
			where: {
				id: workId
			}
		}).then(function(work, err) {
			if(err) console.error(err);
			else {
				console.log("공작 조회 :".cyan, work.name);
				res.render("workpage.ejs", {work: work} );
			}
		});
	})
	.post(function(req, res){
		var workId = req.params.workId;

		Works.findOne({
			where: {
				id: workId
			}
		}).then(function(work, err) {
			if(err) console.error(err);
			else {
				fs.mkdir("./WorkPage/"+work.name, function(err){
					console.log(err);
					if (req.body.reqType == "md") {
						var html = md(req.body.md);
						fs.writeFile("./WorkPage/"+work.name+"/front.html", html, function(err){
							if(err) console.log(err);
							work.updateAttributes({
								frontboard: "./WorkPage" + work.name + "/front.html"
							}).then(function(work, err){
								if(err) console.log(err);
								res.redirect("/work/"+work.id+"/"+work.name);
							});
						});
					}
					else if ( req.body.reqType == "need" ) {
						var html = md(req.body.need)
						fs.writeFile("./WorkPage/"+work.name+"/need.html", html, function(err){
							if(err) console.log(err);
							work.updateAttributes({
								needs: "./WorkPage" + work.name + "/need.html"
							}).then(function(work, err){
								if(err) console.log(err);
								res.redirect("/work/"+work.id+"/"+work.name);
							});
						});
					}
				});
			}
		});
	});

app.route("/user/:userNick")
	.get(function(req, res){
		var userNick = req.parmas.userNick;
	})
	.post(function(req, res){
		// edit user information
	});

var server = app.listen(set.port || 8080);
var io = require('socket.io').listen(server);
console.log((set.host+":"+(set.port || 8080)).cyan+"에서 서버 시작".green);

io.sockets.on('connection',function(socket){
	socket.on('client_update_dislike',function(data){
		console.log("get socket request".red);
		console.log("this is id of work".red, data.workId);
		console.log("this is id of user".red, data.userId);

		async.waterfall([
			function(cb){
				Dislike.findOne({
					where: {
						userId: data.userId,
						workId: data.workId
					}
				}).then(function(dislike, err) {
					if(err) console.log(err);

					if(dislike != null){
						cb(true, dislike);
					} else {
						cb(false, dislike);
					}
				});
			},
			function(exist, dislike, cb){
				if(exist){
					Dislike.destroy({
						where: {
							userId: data.userId,
							workId: data.workId
						}
					}).then(function(){
						cb(null, "Destroy dislike");
					});
				} else {
					Dislike.create({
						userId: data.userId,
						workId: data.workId
					}).then(function(){
						cb(null, "Create dislike");
					});
				}
			}
		],
		function(err, result){
			console.log("dislike state :".red +result);
			socket.broadcast.emit('server_update',data);
		   	// socket.emit('server_update',data);
		});

	});
});

<|endoftext|>


<commit_before>'use strict';
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var jshint = require('gulp-jshint');
var jscs = require('gulp-jscs');
var jsdoc = require("gulp-jsdoc");
var istanbul = require('gulp-istanbul');
var plumber = require('gulp-plumber');
var browserify = require('gulp-browserify');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var size = require('gulp-size');
var mochaPhantomjs = require('gulp-mocha-phantomjs');
var spawn = require('child_process').spawn;
var git = require('gulp-git');
var runSequence = require('gulp-sequence');

var handleErr = function (err) {
  console.log(err.message);
  process.exit(1);
};

function npmVersion(type, done) {
  spawn('npm', ['version', type], { stdio: 'inherit' }).on('close', done);
}

function gitPush(file, message, optional, done) {
  spawn('git', [ 'add', file ], { stdio: 'inherit' }).on('close', function() {
    spawn('git', [ 'commit', '-m', message ], { stdio: 'inherit' }).on('close', function(err) {
      if (optional) {
        done();
      } else {
        done(err);
      }
    });
  });
}

gulp.task('docs', function() {
  return gulp.src("./lib/**/*.js")
    .pipe(jsdoc('./dist/docs'));
});

gulp.task('static', function () {
  return gulp.src([
      'lib/**/*.js',
      'test/**/*.js'
    ])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'))
    .pipe(jscs())
    .on('error', handleErr);
});

gulp.task('pre-test-node', function () {
  return gulp.src('lib/**/*.js')
    .pipe(istanbul({
      includeUntested: true
    }))
    .pipe(istanbul.hookRequire());
});

gulp.task('test-node', ['pre-test-node'], function(cb) {
  var mochaErr;

  gulp.src('test/**/*.js')
    .pipe(plumber())
    .pipe(mocha({
      reporter: 'spec'
    }))
    .on('error', function(err) {
      mochaErr = err;
    })
    .pipe(istanbul.writeReports({
      dir: 'dist/coverage'
    }))
    .on('end', function () {
      cb(mochaErr);
    });
});

gulp.task('test-browser', [ 'browserify-test' ], function() {
  return gulp.src('test/client/index.html')
    .pipe(mochaPhantomjs());
});

gulp.task('test', [ 'test-node', 'test-browser' ]);

gulp.task('browserify-lib', [ 'static' ], function() {
  return gulp.src('lib/junkie.js')
    .pipe(browserify({
      insertGlobals: true,
      standalone: 'junkie'
    }))
    .pipe(size({
      title: "Uncompressed"
    }))
    .pipe(gulp.dest('dist'));
});

gulp.task('browserify-test', [ 'static' ], function() {
  return gulp.src('test/client/index.js')
    .pipe(browserify({
      insertGlobals: true
    }))
    .pipe(rename('junkie-test.js'))
    .pipe(gulp.dest('dist'));
});

gulp.task('uglify', [ 'browserify-lib' ], function() {
  return gulp.src('dist/junkie.js')
    .pipe(uglify())
    .pipe(rename('junkie.min.js'))
    .pipe(size({
      title: "Compressed"
    }))
    .pipe(gulp.dest('dist'));
});

gulp.task('watch', function() {
  gulp.watch('lib/**/*.js', [ 'browserify-lib' ]);
  gulp.watch('test/**/*.js', [ 'browserify-test' ]);
});

gulp.task('npm-version-patch', function(done) {
  npmVersion('patch', done);
});
gulp.task('npm-version-minor', function(done) {
  npmVersion('minor', done);
});
gulp.task('npm-version-major', function(done) {
  npmVersion('major', done);
});

gulp.task('npm-publish', function(done) {
  spawn('npm', [ 'publish' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('git-push-dist', function(done) {
  gitPush('dist', 'Updated distribution files', false, done);
});

gulp.task('git-push-tags', function(done) {
  spawn('git', [ 'push', '--follow-tags' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('doctoc', function(done) {
  spawn('doctoc', [ 'README.md' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('git-push-readme', function(done) {
  gitPush('README.md', 'Updated readme', true, done);
});

function release(type, done) {
  runSequence(
    'default',
    'doctoc',
    'git-push-readme',
    'git-push-dist',
    'npm-version-' + type,
    'git-push-tags',
    'npm-publish',
    done
  );
}

gulp.task('release-patch', release.bind(null, 'patch'));
gulp.task('release-minor', release.bind(null, 'minor'));
gulp.task('release-major', release.bind(null, 'major'));

gulp.task('default', ['static', 'test', 'uglify', 'docs']);
<commit_msg>Removed erroneous gulp-git require<commit_after>'use strict';
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var jshint = require('gulp-jshint');
var jscs = require('gulp-jscs');
var jsdoc = require("gulp-jsdoc");
var istanbul = require('gulp-istanbul');
var plumber = require('gulp-plumber');
var browserify = require('gulp-browserify');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var size = require('gulp-size');
var mochaPhantomjs = require('gulp-mocha-phantomjs');
var spawn = require('child_process').spawn;
var runSequence = require('gulp-sequence');

var handleErr = function (err) {
  console.log(err.message);
  process.exit(1);
};

function npmVersion(type, done) {
  spawn('npm', ['version', type], { stdio: 'inherit' }).on('close', done);
}

function gitPush(file, message, optional, done) {
  spawn('git', [ 'add', file ], { stdio: 'inherit' }).on('close', function() {
    spawn('git', [ 'commit', '-m', message ], { stdio: 'inherit' }).on('close', function(err) {
      if (optional) {
        done();
      } else {
        done(err);
      }
    });
  });
}

gulp.task('docs', function() {
  return gulp.src("./lib/**/*.js")
    .pipe(jsdoc('./dist/docs'));
});

gulp.task('static', function () {
  return gulp.src([
      'lib/**/*.js',
      'test/**/*.js'
    ])
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'))
    .pipe(jshint.reporter('fail'))
    .pipe(jscs())
    .on('error', handleErr);
});

gulp.task('pre-test-node', function () {
  return gulp.src('lib/**/*.js')
    .pipe(istanbul({
      includeUntested: true
    }))
    .pipe(istanbul.hookRequire());
});

gulp.task('test-node', ['pre-test-node'], function(cb) {
  var mochaErr;

  gulp.src('test/**/*.js')
    .pipe(plumber())
    .pipe(mocha({
      reporter: 'spec'
    }))
    .on('error', function(err) {
      mochaErr = err;
    })
    .pipe(istanbul.writeReports({
      dir: 'dist/coverage'
    }))
    .on('end', function () {
      cb(mochaErr);
    });
});

gulp.task('test-browser', [ 'browserify-test' ], function() {
  return gulp.src('test/client/index.html')
    .pipe(mochaPhantomjs());
});

gulp.task('test', [ 'test-node', 'test-browser' ]);

gulp.task('browserify-lib', [ 'static' ], function() {
  return gulp.src('lib/junkie.js')
    .pipe(browserify({
      insertGlobals: true,
      standalone: 'junkie'
    }))
    .pipe(size({
      title: "Uncompressed"
    }))
    .pipe(gulp.dest('dist'));
});

gulp.task('browserify-test', [ 'static' ], function() {
  return gulp.src('test/client/index.js')
    .pipe(browserify({
      insertGlobals: true
    }))
    .pipe(rename('junkie-test.js'))
    .pipe(gulp.dest('dist'));
});

gulp.task('uglify', [ 'browserify-lib' ], function() {
  return gulp.src('dist/junkie.js')
    .pipe(uglify())
    .pipe(rename('junkie.min.js'))
    .pipe(size({
      title: "Compressed"
    }))
    .pipe(gulp.dest('dist'));
});

gulp.task('watch', function() {
  gulp.watch('lib/**/*.js', [ 'browserify-lib' ]);
  gulp.watch('test/**/*.js', [ 'browserify-test' ]);
});

gulp.task('npm-version-patch', function(done) {
  npmVersion('patch', done);
});
gulp.task('npm-version-minor', function(done) {
  npmVersion('minor', done);
});
gulp.task('npm-version-major', function(done) {
  npmVersion('major', done);
});

gulp.task('npm-publish', function(done) {
  spawn('npm', [ 'publish' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('git-push-dist', function(done) {
  gitPush('dist', 'Updated distribution files', false, done);
});

gulp.task('git-push-tags', function(done) {
  spawn('git', [ 'push', '--follow-tags' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('doctoc', function(done) {
  spawn('doctoc', [ 'README.md' ], { stdio: 'inherit' }).on('close', done);
});

gulp.task('git-push-readme', function(done) {
  gitPush('README.md', 'Updated readme', true, done);
});

function release(type, done) {
  runSequence(
    'default',
    'doctoc',
    'git-push-readme',
    'git-push-dist',
    'npm-version-' + type,
    'git-push-tags',
    'npm-publish',
    done
  );
}

gulp.task('release-patch', release.bind(null, 'patch'));
gulp.task('release-minor', release.bind(null, 'minor'));
gulp.task('release-major', release.bind(null, 'major'));

gulp.task('default', ['static', 'test', 'uglify', 'docs']);
<|endoftext|>


<commit_before>
//
// Copyright © 2016-present Kary Foundation, Inc. All Rights Reserved
//   Author: Pouya Kary <k@karyfoundation.org>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

//
// ─── IMPORTS ────────────────────────────────────────────────────────────────────
//

    const gulp        = require('gulp')
    const packageJson = require('./package.json')
    const exec        = require('child_process').exec
    const argv        = require('yargs').argv
    const util        = require('util')
    const path        = require('path')
    const fs          = require('fs-extra')
    const ugly        = require('gulp-uglify')
    const less        = require('less')
    const mv          = require('mv')

//
// ─── CONSTANTS ──────────────────────────────────────────────────────────────────
//

    const version = "v1.0"

//
// ─── CONSTS ─────────────────────────────────────────────────────────────────────
//

    const resultDirPath = '_compiled'

//
// ─── TOOLS ──────────────────────────────────────────────────────────────────────
//

    /** Run shell commands easy! */
    function shell ( command , callback ) {
        exec( command, err => {
            if ( err ) console.log( err )
        })
    }

//
// ─── COPY DIR FILES ─────────────────────────────────────────────────────────────
//

    /** Copy to binary from dir */
    function copyToBinaryFromDir ( dir, subfolder ) {
        fs.readdir( dir , ( err , files ) => {
            // if error
            if ( err )
                console.log(`Could not get files from directory ${ dir }`)

            // if right
            files.forEach( name => {
                let dest
                if ( !( subfolder === undefined || subfolder === '' || subfolder === null ) )
                    dest = path.join( resultDirPath , subfolder , name )
                else
                    dest = path.join( resultDirPath , name )

                if ( !( name.endsWith('.map') || name.endsWith('.d.ts') ) )
                    copyFile(
                        getLocalPath( path.join( dir , name ) ),
                        getLocalPath( dest )
                    )})})}

//
// ─── COPY SINGLE FILE ───────────────────────────────────────────────────────────
//

    /** Copy file `A` to `B` */
    function copyFile ( A, B ) {
        if ( /\.DS_Store/.test( A ) ) {
            return
        }
        fs.copy( A, B, err => {
            if ( err ) {
                console.log(`Could not copy file ${ A }`)
            }
        })
    }

//
// ─── GET LOCAL PATH ─────────────────────────────────────────────────────────────
//

    /** Get Local Path in the current directory */
    function getLocalPath ( address ) {
        return path.join( __dirname , address )
    }

//
// ─── COPY FILES ─────────────────────────────────────────────────────────────────
//

    /** Copies static resource files into the result directory */
    gulp.task( 'copyResourceFiles', callback => {

        function copyNodeModules ( handle ) {
            let address = path.join( 'node_modules', handle )
            copyToBinaryFromDir( address, address )
        }

        copyToBinaryFromDir( 'resources' )
        copyToBinaryFromDir( 'view' )
        copyToBinaryFromDir( 'editor' )
        copyToBinaryFromDir( 'libs' )
        copyToBinaryFromDir( 'windows' )
        copyToBinaryFromDir( 'winserver' )

        copyNodeModules('concerto-compiler')
        copyNodeModules('messenger')
        copyNodeModules('regulex')
        copyNodeModules('amdefine')
        copyNodeModules('monaco-editor/min/vs')

        copyFile(
            getLocalPath( 'package.json' ),
            getLocalPath( path.join( resultDirPath , 'package.json' ) )
        )

        // adding commit count
        shell(`git rev-list --all --count > ./${resultDirPath}/about/commit-count.txt`)

        callback()
    })

//
// ─── SHEETS ─────────────────────────────────────────────────────────────────────
//

    /** Compiles the Less style sheets */
    gulp.task( 'sheets', callback => {
        try {
            let lessSourceCode = fs.readFileSync(
                path.join( __dirname, 'sheets', 'ui.less' ), 'utf8' )

            less.render( lessSourceCode, ( err, output ) => {
                if ( err ) {
                    console.log(`Less failure: ${ err }`); return
                }
                fs.writeFile(
                    path.join( __dirname, '_compiled/style.css' ),
                    output.css,
                    error => {
                        if ( error ) {
                            console.log('could not store the less file')
                        } else {
                            callback()
                        }
                    }
                )
            })
        } catch ( err ) {
            console.log('Compiling less failed ' + err )
        }
    })

//
// ─── ELECTRON PACKER ────────────────────────────────────────────────────────────
//

    gulp.task( 'electron', ['copyResourceFiles', 'sheets'], ( ) => {
        if ( argv.pack ) {
            console.log('packing...')
            let iconFile = ( packageJson.productName !== 'Orchestra Nightly' )?
                './designs/icon/icns/icon.icns' : './designs/icon-nightly/icns/icon.icns'

            shell(`electron-packager _compiled "${ packageJson.productName }" --platform=darwin --arch=x64 --overwrite=true --app-copyright="Copyright 2016 by Kary Foundation, Inc." --app-version="${ packageJson.version }" --icon=${ iconFile } --name="${ packageJson.productName }" --out=_release`)
        }

        if ( argv.debug ) {
            shell('npm run electron')
        }
    })

//
// ─── AFTER PACK ─────────────────────────────────────────────────────────────────
//

    gulp.task( 'after-pack', [ 'electron' ], ( ) => {

    })

//
// ─── MAIN ───────────────────────────────────────────────────────────────────────
//

    /** Where everything starts */
    gulp.task( 'default', [ 'after-pack' ])

// ────────────────────────────────────────────────────────────────────────────────
<commit_msg>A really cool build system that fetches latest commit count from GitHub<commit_after>
//
// Copyright © 2016-present Kary Foundation, Inc. All Rights Reserved
//   Author: Pouya Kary <k@karyfoundation.org>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

//
// ─── IMPORTS ────────────────────────────────────────────────────────────────────
//

    const gulp          = require('gulp')
    const packageJson   = require('./package.json')
    const exec          = require('child_process').exec
    const argv          = require('yargs').argv
    const util          = require('util')
    const path          = require('path')
    const fs            = require('fs-extra')
    const ugly          = require('gulp-uglify')
    const less          = require('less')
    const mv            = require('mv')
    const request       = require('request')

//
// ─── CONSTANTS ──────────────────────────────────────────────────────────────────
//

    const version = "v1.0"

//
// ─── CONSTS ─────────────────────────────────────────────────────────────────────
//

    const resultDirPath = '_compiled'

//
// ─── TOOLS ──────────────────────────────────────────────────────────────────────
//

    /** Run shell commands easy! */
    function shell ( command , callback ) {
        exec( command, err => {
            if ( err ) console.log( err )
        })
    }

//
// ─── COPY DIR FILES ─────────────────────────────────────────────────────────────
//

    /** Copy to binary from dir */
    function copyToBinaryFromDir ( dir, subfolder ) {
        fs.readdir( dir , ( err , files ) => {
            // if error
            if ( err )
                console.log(`Could not get files from directory ${ dir }`)

            // if right
            files.forEach( name => {
                let dest
                if ( !( subfolder === undefined || subfolder === '' || subfolder === null ) )
                    dest = path.join( resultDirPath , subfolder , name )
                else
                    dest = path.join( resultDirPath , name )

                if ( !( name.endsWith('.map') || name.endsWith('.d.ts') ) )
                    copyFile(
                        getLocalPath( path.join( dir , name ) ),
                        getLocalPath( dest )
                    )})})}

//
// ─── COPY SINGLE FILE ───────────────────────────────────────────────────────────
//

    /** Copy file `A` to `B` */
    function copyFile ( A, B ) {
        if ( /\.DS_Store/.test( A ) ) {
            return
        }
        fs.copy( A, B, err => {
            if ( err ) {
                console.log(`Could not copy file ${ A }`)
            }
        })
    }

//
// ─── GET LOCAL PATH ─────────────────────────────────────────────────────────────
//

    /** Get Local Path in the current directory */
    function getLocalPath ( address ) {
        return path.join( __dirname , address )
    }

//
// ─── COPY FILES ─────────────────────────────────────────────────────────────────
//

    /** Copies static resource files into the result directory */
    gulp.task( 'copyResourceFiles', callback => {

        function copyNodeModules ( handle ) {
            let address = path.join( 'node_modules', handle )
            copyToBinaryFromDir( address, address )
        }

        copyToBinaryFromDir( 'resources' )
        copyToBinaryFromDir( 'view' )
        copyToBinaryFromDir( 'editor' )
        copyToBinaryFromDir( 'libs' )
        copyToBinaryFromDir( 'windows' )
        copyToBinaryFromDir( 'winserver' )

        copyNodeModules('concerto-compiler')
        copyNodeModules('messenger')
        copyNodeModules('regulex')
        copyNodeModules('amdefine')
        copyNodeModules('monaco-editor/min/vs')

        copyFile(
            getLocalPath( 'package.json' ),
            getLocalPath( path.join( resultDirPath , 'package.json' ) )
        )

        callback()
    })

//
// ─── GETTING COMMIT COUNT ───────────────────────────────────────────────────────
//

    gulp.task( 'get-commit-counts', callback => {
        const commitCountFilePath = `./${resultDirPath}/about/commit-count.txt`
        try {
            async function getCommitCountFromMasterBranchOfGithub ( ) {
                return new Promise ( ( resolve, reject ) => {
                    const options = {
                        url: 'https://api.github.com/repos/karyfoundation/orchestra/stats/contributors',
                        method: 'GET',
                        headers: {
                            'User-Agent':   'Super Agent/0.0.1',
                            'Content-Type': 'application/x-www-form-urlencoded'
                        },
                    }
                    request( options, ( error, response, body ) => {
                        if ( !error && response.statusCode == 200 ) {
                            const data = JSON.parse( body )[ 0 ].total.toString( )
                            resolve( data )
                        } else {
                            reject('Could not connect to GitHub')
                        }
                    })
                })
            }

            getCommitCountFromMasterBranchOfGithub( ).then( GitHubCommitCount => {
                fs.writeFileSync( commitCountFilePath, GitHubCommitCount )
                callback( )
            }).catch( e => {
                throw e
            })

        } catch ( error ) {
            try {
                shell('git rev-list --all --count > ' + commitCountFilePath )
                callback( )

            } catch ( error2 ) {
                callback('Could not save latest commits count')
            }
        }
    })

//
// ─── SHEETS ─────────────────────────────────────────────────────────────────────
//

    /** Compiles the Less style sheets */
    gulp.task( 'sheets', callback => {
        try {
            let lessSourceCode = fs.readFileSync(
                path.join( __dirname, 'sheets', 'ui.less' ), 'utf8' )

            less.render( lessSourceCode, ( err, output ) => {
                if ( err ) {
                    console.log(`Less failure: ${ err }`); return
                }
                fs.writeFile(
                    path.join( __dirname, '_compiled/style.css' ),
                    output.css,
                    error => {
                        if ( error ) {
                            console.log('could not store the less file')
                        } else {
                            callback()
                        }
                    }
                )
            })
        } catch ( err ) {
            console.log('Compiling less failed ' + err )
        }
    })

//
// ─── ELECTRON PACKER ────────────────────────────────────────────────────────────
//

    gulp.task( 'electron', ['copyResourceFiles', 'get-commit-counts', 'sheets'], ( ) => {
        if ( argv.pack ) {
            console.log('packing...')
            let iconFile = ( packageJson.productName !== 'Orchestra Nightly' )?
                './designs/icon/icns/icon.icns' : './designs/icon-nightly/icns/icon.icns'

            shell(`electron-packager _compiled "${ packageJson.productName }" --platform=darwin --arch=x64 --overwrite=true --app-copyright="Copyright 2016 by Kary Foundation, Inc." --app-version="${ packageJson.version }" --icon=${ iconFile } --name="${ packageJson.productName }" --out=_release`)
        }

        if ( argv.debug ) {
            shell('npm run electron')
        }
    })

//
// ─── AFTER PACK ─────────────────────────────────────────────────────────────────
//

    gulp.task( 'after-pack', [ 'electron' ], ( ) => {

    })

//
// ─── MAIN ───────────────────────────────────────────────────────────────────────
//

    /** Where everything starts */
    gulp.task( 'default', [ 'after-pack' ])

// ────────────────────────────────────────────────────────────────────────────────
<|endoftext|>


<commit_before>'use strict'

var { ResourceLoader, Repo } = require('mzen');
var ServerRemoteObject = require('./remote-object');
var ServerAcl = require('./acl');
var ServerRepoMixin = require('./repo-mixin');
var express = require('express');
var bodyParser = require('body-parser');
var clone = require('clone');
var fs = require('fs');
var merge = require('merge');

class Server
{
  constructor(modelManager, options = {})
  {
    this.modelManager = modelManager;
    this.config = options ? options : {};
    this.config['path'] = this.config['path'] ? this.config['path'] : '/api';
    this.config['port'] = this.config['port'] ? this.config['port'] : 3000;
    this.config['appDir'] = this.config['appDir'] ? this.config['appDir'] : '';
    this.config['initDirName'] = this.config['initDirName'] ? this.config['initDirName'] : '/init';
    this.config['aclDirName'] = this.config['aclDirName'] ? this.config['aclDirName'] : '/acl';

    this.app = express();
    this.server = null;
    this.router = express.Router();
    this.aclRoleAssessor = {};
    this.setLogger(console);
  }
  setLogger(logger)
  {
    this.logger = logger;
    return this;
  }
  async init()
  {
    if (this.modelManager.config['modelDirs'].length == 0) {
      this.modelManager.config['modelDirs'].push(this.config['appDir'] + '/model');
    }
    // Add default model directory
    this.modelManager.config['modelDirs'].unshift(__dirname + '/model');

    await this.modelManager.init();
    await this.loadResources();
    await this.registerServiceEndpoints();
    await this.registerRepoApiEndpoints();
  }
  bootInitScripts()
  {
    const initDirectoryPath = this.config['appDir'] + '/' + this.config['initDirName'];
    var initScripts = {};
    if (fs.existsSync(initDirectoryPath)) {
      var filenames = fs.readdirSync(initDirectoryPath);
      filenames.forEach(function(filename){
        if (fs.lstatSync(initDirectoryPath + '/' + filename).isDirectory() || filename[0] == '.') return;
        initScripts[filename] = initDirectoryPath + '/' + filename;
      });
    }
    var filenames = Object.keys(initScripts);

    // Sort by filename
    // - the order of execution is important so files should be named to give the correct order
    filenames.sort(function(a, b) {
      return (a > b) ? 1 : 0;
    });

    var filePaths = [];
    filenames.forEach(function(filename){
      filePaths.push(initScripts[filename]);
    });

    var promise = Promise.resolve();
    filePaths.forEach((filePath) => {
      promise.then(() => {
        let initFunction = require(filePath);
        promise = Promise.resolve();
        if (typeof initFunction == 'function') {
          let result = initFunction.call(this);
          if (result && result.constructor && result.constructor instanceof Promise) {
            promise = result;
          }
        }
        return promise;
      });
    });

    return promise;
  }
  loadResources()
  {
    const loader = new ResourceLoader();
    return Promise.resolve().then(() => {
      const accessors = loader.getResources([this.config['appDir']], this.config['aclDirName'] + '/assessor');
      for (let accessorName in accessors) {
        if (!accessors.hasOwnProperty(accessorName)) continue;
        const roleAssessor = new accessors[accessorName](null, this.modelManager.repos);
        this.aclRoleAssessor[roleAssessor.role] = roleAssessor;
      }
      return this;
    });
  }
  registerServiceEndpoints()
  {
    const services = this.modelManager.services;
    for (let serviceName in services)
    {
      const apiConfig = services[serviceName].config['api'] ? services[serviceName].config['api'] : {};
      const repoAclConfig = apiConfig['acl'] ? apiConfig['acl'] : {};
      const endpointsEnable = apiConfig['endpointsEnable'] ? apiConfig['endpointsEnable'] : {};
      var endpoints = apiConfig['endpoints'] ? apiConfig['endpoints'] : {};

      // Remove any endpoints that have been disabled
      for (var endpointName in endpoints) {
        if (endpointsEnable[endpointName] === false) {
          delete endpoints[endpointName];
        }
      }

      if (Object.keys(endpoints).length == 0) continue; // This service has no end points - nothing more to do

      const aclConfig = {
        rules: repoAclConfig['rules'],
        endpoints: endpoints
      };
      var acl = new ServerAcl(aclConfig);
      acl.loadDefaultRoleAssessors();
      acl.setRepos(this.modelManager.repos);
      for (var role in this.roleAssessor) {
        acl.addRoleAssessor(this.roleAssessor[role]);
      }

      const remoteConfig = {
        path: '/service/' + serviceName,
        endpoints: endpoints
      };

      var remoteObject = new ServerRemoteObject(services[serviceName], remoteConfig);
      remoteObject.setLogger(this.logger);
      remoteObject.setAcl(acl);
      remoteObject.initRouter(this.router);
    }
  }
  registerRepoApiEndpoints()
  {
    // Mixin ServerRepoMixin methods into Repo - handlers for the api endpoints
    const mixinFields = Object.getOwnPropertyNames(ServerRepoMixin.prototype);
    mixinFields.forEach(function(mixinField){
      if (mixinField == 'constructor') return;
      Repo.prototype[mixinField] = ServerRepoMixin.prototype[mixinField];
    });

    const repos = this.modelManager.repos;

    for (var repoName in repos)
    {
      const apiConfig = repos[repoName].config['api'] ? repos[repoName].config['api']: {};
      const enable = (apiConfig['enable'] !== undefined) ? apiConfig['enable'] : true;
      const repoAclConfig = apiConfig['acl'] ? apiConfig['acl'] : {};
      const endpointsDisable = apiConfig['endpointsDisable'] ? apiConfig['endpointsDisable'] : {};
      const endpointGroupsDisable = apiConfig['endpointGroupsDisable'] ? apiConfig['endpointGroupsDisable'] : {};
      var endpoints = apiConfig['endpoints'] ? apiConfig['endpoints'] : {};

      if (!enable) continue;

      // Append default endpoints to endpoint config
      for (var defaultEndpointName in ServerRepoMixin.endpoints) {
        if (endpointsDisable[endpointName] != true) {
          if (endpoints[defaultEndpointName]) {
            // The repo already has this endpoint config - merge the two configs
            endpoints[defaultEndpointName] = merge(ServerRepoMixin.endpoints[defaultEndpointName], endpoints[defaultEndpointName]);
          } else {
            endpoints[defaultEndpointName] = ServerRepoMixin.endpoints[defaultEndpointName];
          }
        }
      }

      // Remove any enpoints that have been disabled
      for (var endpointName in endpoints) {
        var groups = endpoints[endpointName]['groups'];
        if (Array.isArray(groups)) {
          groups.forEach(function(group){
            if (endpoints[endpointName] && endpointGroupsDisable[group] == true) delete endpoints[endpointName]
          });
        }
        if (endpoints[endpointName] && endpointsDisable[endpointName] == true) delete endpoints[endpointName];
      }

      if (Object.keys(endpoints).length == 0) continue; // This repo has no end points - nothing more to do

      const aclConfig = {
        rules: repoAclConfig['rules'],
        endpoints: endpoints
      };
      var acl = new ServerAcl(aclConfig);
      acl.loadDefaultRoleAssessors();
      acl.setRepos(this.modelManager.repos);
      for (var role in this.roleAssessor) {
        acl.addRoleAssessor(this.roleAssessor[role]);
      }

      const remoteConfig = {
        path: '/repo/' + repoName,
        endpoints: endpoints
      };
      var remoteObject = new ServerRemoteObject(repos[repoName], remoteConfig);
      remoteObject.setLogger(this.logger);
      remoteObject.setAcl(acl);
      remoteObject.initRouter(this.router);
    }
  }
  async start()
  {
    this.app.use(bodyParser.json()); // for parsing application/json
    this.app.use(bodyParser.text());
    this.app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded

    await this.bootInitScripts()

    this.app.use(this.config['path'], this.router);
    this.app.use((err, req, res, next) => {
      this.logger.error({err, req, res});
      res.status(500).send('Something broke!')
    });
    this.server = this.app.listen(this.config['port'], () => {
      this.logger.info('Listening on port ' + this.config['port']);
    });

    process.on('SIGINT', () => {
      this.shutdown().then(() => {
        setTimeout(function() {
          process.exit(0);
        }, 5000);
      });
    });
  }
  async shutdown()
  {
    this.logger.info('Shutting down');
    await this.modelManager.shutdown();
    return this.server ? this.server.close() : undefined;
  }
}
module.exports = Server;
<commit_msg>Server initiates its own ModelManager from config<commit_after>'use strict'

var { ResourceLoader, ModelManager, Repo } = require('mzen');
var ServerRemoteObject = require('./remote-object');
var ServerAcl = require('./acl');
var ServerRepoMixin = require('./repo-mixin');
var express = require('express');
var bodyParser = require('body-parser');
var clone = require('clone');
var fs = require('fs');
var merge = require('merge');

class Server
{
  constructor(options = {})
  {
    this.modelManager = new ModelManager(options['model']);
    this.config = options ? options : {};
    this.config['path'] = this.config['path'] ? this.config['path'] : '/api';
    this.config['port'] = this.config['port'] ? this.config['port'] : 3838;
    // Default appDir directory is the same directory as the executed script
    this.config['appDir'] = this.config['appDir'] ? this.config['appDir'] : '';
    this.config['initDirName'] = this.config['initDirName'] ? this.config['initDirName'] : '/init';
    this.config['aclDirName'] = this.config['aclDirName'] ? this.config['aclDirName'] : '/acl';

    this.app = express();
    this.server = null;
    this.router = express.Router();
    this.aclRoleAssessor = {};
    this.setLogger(console);
  }
  setLogger(logger)
  {
    this.logger = logger;
    return this;
  }
  async init()
  {
    // Add app model directory based on value of appDir if no model directories have been configured
    if (this.modelManager.config['modelDirs'].length == 0) {
      this.modelManager.config['modelDirs'].push(this.config['appDir'] + '/model');
    }
    // Add default model directory - this is model functionality provided by the mzen-server package
    this.modelManager.config['modelDirs'].unshift(__dirname + '/model');

    await this.modelManager.init();
    await this.loadResources();
    await this.registerServiceEndpoints();
    await this.registerRepoApiEndpoints();
  }
  bootInitScripts()
  {
    const initDirectoryPath = this.config['appDir'] + '/' + this.config['initDirName'];
    var initScripts = {};
    if (fs.existsSync(initDirectoryPath)) {
      var filenames = fs.readdirSync(initDirectoryPath);
      filenames.forEach(function(filename){
        if (fs.lstatSync(initDirectoryPath + '/' + filename).isDirectory() || filename[0] == '.') return;
        initScripts[filename] = initDirectoryPath + '/' + filename;
      });
    }
    var filenames = Object.keys(initScripts);

    // Sort by filename
    // - the order of execution is important so files should be named to give the correct order
    filenames.sort(function(a, b) {
      return (a > b) ? 1 : 0;
    });

    var filePaths = [];
    filenames.forEach(function(filename){
      filePaths.push(initScripts[filename]);
    });

    var promise = Promise.resolve();
    filePaths.forEach((filePath) => {
      promise.then(() => {
        let initFunction = require(filePath);
        promise = Promise.resolve();
        if (typeof initFunction == 'function') {
          let result = initFunction.call(this);
          if (result && result.constructor && result.constructor instanceof Promise) {
            promise = result;
          }
        }
        return promise;
      });
    });

    return promise;
  }
  loadResources()
  {
    const loader = new ResourceLoader();
    return Promise.resolve().then(() => {
      const accessors = loader.getResources([this.config['appDir']], this.config['aclDirName'] + '/assessor');
      for (let accessorName in accessors) {
        if (!accessors.hasOwnProperty(accessorName)) continue;
        const roleAssessor = new accessors[accessorName](null, this.modelManager.repos);
        this.aclRoleAssessor[roleAssessor.role] = roleAssessor;
      }
      return this;
    });
  }
  registerServiceEndpoints()
  {
    const services = this.modelManager.services;
    for (let serviceName in services)
    {
      const apiConfig = services[serviceName].config['api'] ? services[serviceName].config['api'] : {};
      const repoAclConfig = apiConfig['acl'] ? apiConfig['acl'] : {};
      const endpointsEnable = apiConfig['endpointsEnable'] ? apiConfig['endpointsEnable'] : {};
      var endpoints = apiConfig['endpoints'] ? apiConfig['endpoints'] : {};

      // Remove any endpoints that have been disabled
      for (var endpointName in endpoints) {
        if (endpointsEnable[endpointName] === false) {
          delete endpoints[endpointName];
        }
      }

      if (Object.keys(endpoints).length == 0) continue; // This service has no end points - nothing more to do

      const aclConfig = {
        rules: repoAclConfig['rules'],
        endpoints: endpoints
      };
      var acl = new ServerAcl(aclConfig);
      acl.loadDefaultRoleAssessors();
      acl.setRepos(this.modelManager.repos);
      for (var role in this.roleAssessor) {
        acl.addRoleAssessor(this.roleAssessor[role]);
      }

      const remoteConfig = {
        path: '/service/' + serviceName,
        endpoints: endpoints
      };

      var remoteObject = new ServerRemoteObject(services[serviceName], remoteConfig);
      remoteObject.setLogger(this.logger);
      remoteObject.setAcl(acl);
      remoteObject.initRouter(this.router);
    }
  }
  registerRepoApiEndpoints()
  {
    // Mixin ServerRepoMixin methods into Repo - handlers for the api endpoints
    const mixinFields = Object.getOwnPropertyNames(ServerRepoMixin.prototype);
    mixinFields.forEach(function(mixinField){
      if (mixinField == 'constructor') return;
      Repo.prototype[mixinField] = ServerRepoMixin.prototype[mixinField];
    });

    const repos = this.modelManager.repos;

    for (var repoName in repos)
    {
      const apiConfig = repos[repoName].config['api'] ? repos[repoName].config['api']: {};
      const enable = (apiConfig['enable'] !== undefined) ? apiConfig['enable'] : true;
      const repoAclConfig = apiConfig['acl'] ? apiConfig['acl'] : {};
      const endpointsDisable = apiConfig['endpointsDisable'] ? apiConfig['endpointsDisable'] : {};
      const endpointGroupsDisable = apiConfig['endpointGroupsDisable'] ? apiConfig['endpointGroupsDisable'] : {};
      var endpoints = apiConfig['endpoints'] ? apiConfig['endpoints'] : {};

      if (!enable) continue;

      // Append default endpoints to endpoint config
      for (var defaultEndpointName in ServerRepoMixin.endpoints) {
        if (endpointsDisable[endpointName] != true) {
          if (endpoints[defaultEndpointName]) {
            // The repo already has this endpoint config - merge the two configs
            endpoints[defaultEndpointName] = merge(ServerRepoMixin.endpoints[defaultEndpointName], endpoints[defaultEndpointName]);
          } else {
            endpoints[defaultEndpointName] = ServerRepoMixin.endpoints[defaultEndpointName];
          }
        }
      }

      // Remove any enpoints that have been disabled
      for (var endpointName in endpoints) {
        var groups = endpoints[endpointName]['groups'];
        if (Array.isArray(groups)) {
          groups.forEach(function(group){
            if (endpoints[endpointName] && endpointGroupsDisable[group] == true) delete endpoints[endpointName]
          });
        }
        if (endpoints[endpointName] && endpointsDisable[endpointName] == true) delete endpoints[endpointName];
      }

      if (Object.keys(endpoints).length == 0) continue; // This repo has no end points - nothing more to do

      const aclConfig = {
        rules: repoAclConfig['rules'],
        endpoints: endpoints
      };
      var acl = new ServerAcl(aclConfig);
      acl.loadDefaultRoleAssessors();
      acl.setRepos(this.modelManager.repos);
      for (var role in this.roleAssessor) {
        acl.addRoleAssessor(this.roleAssessor[role]);
      }

      const remoteConfig = {
        path: '/repo/' + repoName,
        endpoints: endpoints
      };
      var remoteObject = new ServerRemoteObject(repos[repoName], remoteConfig);
      remoteObject.setLogger(this.logger);
      remoteObject.setAcl(acl);
      remoteObject.initRouter(this.router);
    }
  }
  async start()
  {
    this.app.use(bodyParser.json()); // for parsing application/json
    this.app.use(bodyParser.text());
    this.app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded

    await this.bootInitScripts()

    this.app.use(this.config['path'], this.router);
    this.app.use((err, req, res, next) => {
      this.logger.error({err, req, res});
      res.status(500).send('Something broke!')
    });
    this.server = this.app.listen(this.config['port'], () => {
      this.logger.info('Listening on port ' + this.config['port']);
    });

    process.on('SIGINT', () => {
      this.shutdown().then(() => {
        setTimeout(function() {
          process.exit(0);
        }, 5000);
      });
    });
  }
  async shutdown()
  {
    this.logger.info('Shutting down');
    await this.modelManager.shutdown();
    return this.server ? this.server.close() : undefined;
  }
}
module.exports = Server;
<|endoftext|>


<commit_before>module.exports = {
  exec: function (javaScriptString) {
    var returnString = ''
    function css (cssString) {
      returnString += cssString
    }
    try {
      eval(javaScriptString)
    } catch (e) {
      console.log('Exception in your jcss')
      console.log(javaScriptString)
      console.log(e)
      return false
    }
    return returnString
  },

  split: function (jcssString) {
    /*
      ^[
          \s\t
        ]*
        (
          (
            (
              (
                [\.\#]?
                [\w\-_\d]+
              )
              |
              \*
            )
            |
            (
              (
                \[
                |
                \:{1,2}
              ){1}
              [\w\-_\d\*\^\~\|\=\"\$]+
              (
                \([^\)\;]+\)
              )?
              \]?
            )
          )+
          [\n\,\s\>\+\~]*
        )+
      \{
      [^\}]*
      \}
      \n*
    */
    var cssRegex = /^[\s\t]*(((([\.\#]?[\w\-_\d]+)|\*)|((\[|\:{1,2}){1}[\w\-_\d\*\^\~\|\=\"\$]+(\([^\)\;]+\))?\]?))+[\n\,\s\>\+\~]*)+\{[^\}]*\}\n*/gm
    var cssRegexRes, returnLang
    if(!jcssString) return false
    cssRegexRes = cssRegex.exec(jcssString)
    if(!cssRegexRes) return ['js', jcssString, false]
    returnLang = jcssString.indexOf(cssRegexRes[0]) === 0 ? 'css' : 'js'
    return [returnLang].concat(this.splitAroundSubstring(cssRegexRes[0], jcssString))
  },

  splitAroundSubstring: function (substring, string) {
    var substringFirst = string.indexOf(substring)
    var substringLast = substringFirst + substring.length
    if(substringFirst === 0) {
      return [string.substr(0, substringLast), string.substr(substringLast)]
    } else {
      return [string.substr(0, substringFirst), string.substr(substringFirst)]
    }
  },

  interpret: function (someArr) {
    return (someArr[0] == 'js' ? this.exec(someArr[1]) : someArr[1])
  },

  parse: function (jcssString) {
    var splitJcss = []
    var buffer = ''
    var parsedCss = ''
    if(typeof jcssString != 'string') return false
    do {
      splitJcss = this.split(jcssString)
      parsedCss += (buffer = this.interpret(splitJcss))
      if(buffer === false) return false
    } while (jcssString = splitJcss[2])
    return parsedCss
  }
}
<commit_msg>Implement Variables<commit_after>var _ = require('underscore')

module.exports = {
  stateJcssVars: {

  },

  exec: function (javaScriptString) {
    var returnString = ''
    var $ = {}
    function css (cssString) {
      returnString += cssString
    }
    try {
      eval(javaScriptString)
      _.extend(this.stateJcssVars, $)
      return returnString
    } catch (e) {
      console.log('Exception in your jcss')
      console.log(javaScriptString)
      console.log(e)
      return false
    }
  },

  parseCssVars: function (cssString) {
    var self = this
    var varRegex = /\$\.[\w\,\.\d\_\-]+(\([^\)]*\))*/gm
    if(!cssString) return '';
    cssString = cssString.replace(varRegex, function (match) {
      var $ = self.stateJcssVars
      console.log(match)
      return eval(match)
    })
    return cssString
  },

  split: function (jcssString) {
    /*
      ^[
          \s\t
        ]*
        (
          (
            (
              (
                [\.\#]?
                [\w\-_\d]+
              )
              |
              \*
            )
            |
            (
              (
                \[
                |
                \:{1,2}
              ){1}
              [\w\-_\d\*\^\~\|\=\"\$]+
              (
                \([^\)\;]+\)
              )?
              \]?
            )
          )+
          [\n\,\s\>\+\~]*
        )+
      \{
      [^\}]*
      \}
      \n*
    */
    var cssRegex = /^[\s\t]*(((([\.\#]?[\w\-_\d]+)|\*)|((\[|\:{1,2}){1}[\w\-_\d\*\^\~\|\=\"\$]+(\([^\)\;]+\))?\]?))+[\n\,\s\>\+\~]*)+\{[^\}]*\}\n*/gm
    var cssRegexRes, returnLang
    if(!jcssString) return false
    cssRegexRes = cssRegex.exec(jcssString)
    if(!cssRegexRes) return ['js', jcssString, false]
    returnLang = jcssString.indexOf(cssRegexRes[0]) === 0 ? 'css' : 'js'
    return [returnLang].concat(this.splitAroundSubstring(cssRegexRes[0], jcssString))
  },

  splitAroundSubstring: function (substring, string) {
    var substringFirst = string.indexOf(substring)
    var substringLast = substringFirst + substring.length
    if(substringFirst === 0) {
      return [string.substr(0, substringLast), string.substr(substringLast)]
    } else {
      return [string.substr(0, substringFirst), string.substr(substringFirst)]
    }
  },

  interpret: function (someArr) {
    return (someArr[0] == 'js' ? this.exec(someArr[1]) : this.parseCssVars(someArr[1]))
  },

  parse: function (jcssString) {
    var splitJcss = []
    var buffer = ''
    var parsedCss = ''
    if(typeof jcssString != 'string') return false
    do {
      splitJcss = this.split(jcssString)
      parsedCss += (buffer = this.interpret(splitJcss))
      if(buffer === false) return false
    } while (jcssString = splitJcss[2])
    return parsedCss
  }
}
<|endoftext|>


<commit_before>import {
  NOTIFICATIONS_UPDATE,
  NOTIFICATIONS_EXPAND_SUCCESS,
  NOTIFICATIONS_EXPAND_REQUEST,
  NOTIFICATIONS_EXPAND_FAIL,
  NOTIFICATIONS_CLEAR,
  NOTIFICATIONS_SCROLL_TOP,
  NOTIFICATIONS_DELETE_MARKED_REQUEST,
  NOTIFICATIONS_DELETE_MARKED_SUCCESS,
  NOTIFICATION_MARK_FOR_DELETE,
  NOTIFICATIONS_DELETE_MARKED_FAIL,
  NOTIFICATIONS_ENTER_CLEARING_MODE,
  NOTIFICATIONS_MARK_ALL_FOR_DELETE,
} from 'flavours/glitch/actions/notifications';
import {
  ACCOUNT_BLOCK_SUCCESS,
  ACCOUNT_MUTE_SUCCESS,
} from 'flavours/glitch/actions/accounts';
import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from 'flavours/glitch/actions/timelines';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import compareId from 'flavours/glitch/util/compare_id';

const initialState = ImmutableMap({
  items: ImmutableList(),
  hasMore: true,
  top: true,
  unread: 0,
  isLoading: false,
  cleaningMode: false,
  // notification removal mark of new notifs loaded whilst cleaningMode is true.
  markNewForDelete: false,
});

const notificationToMap = (state, notification) => ImmutableMap({
  id: notification.id,
  type: notification.type,
  account: notification.account.id,
  markedForDelete: state.get('markNewForDelete'),
  status: notification.status ? notification.status.id : null,
});

const normalizeNotification = (state, notification) => {
  const top = state.get('top');

  if (!top) {
    state = state.update('unread', unread => unread + 1);
  }

  return state.update('items', list => {
    if (top && list.size > 40) {
      list = list.take(20);
    }

    return list.unshift(notificationToMap(state, notification));
  });
};

const expandNormalizedNotifications = (state, notifications, next) => {
  let items = ImmutableList();

  notifications.forEach((n, i) => {
    items = items.set(i, notificationToMap(state, n));
  });

  return state.withMutations(mutable => {
    if (!items.isEmpty()) {
      mutable.update('items', list => {
        const lastIndex = 1 + list.findLastIndex(
          item => item !== null && (compareId(item.get('id'), items.last().get('id')) > 0 || item.get('id') === items.last().get('id'))
        );

        const firstIndex = 1 + list.take(lastIndex).findLastIndex(
          item => item !== null && compareId(item.get('id'), items.first().get('id')) > 0
        );

        return list.take(firstIndex).concat(items, list.skip(lastIndex));
      });
    }

    if (!next) {
      mutable.set('hasMore', true);
    }

    mutable.set('isLoading', false);
  });
};

const filterNotifications = (state, relationship) => {
  return state.update('items', list => list.filterNot(item => item !== null && item.get('account') === relationship.id));
};

const updateTop = (state, top) => {
  if (top) {
    state = state.set('unread', 0);
  }

  return state.set('top', top);
};

const deleteByStatus = (state, statusId) => {
  return state.update('items', list => list.filterNot(item => item !== null && item.get('status') === statusId));
};

const markForDelete = (state, notificationId, yes) => {
  return state.update('items', list => list.map(item => {
    if(item.get('id') === notificationId) {
      return item.set('markedForDelete', yes);
    } else {
      return item;
    }
  }));
};

const markAllForDelete = (state, yes) => {
  return state.update('items', list => list.map(item => {
    if(yes !== null) {
      return item.set('markedForDelete', yes);
    } else {
      return item.set('markedForDelete', !item.get('markedForDelete'));
    }
  }));
};

const unmarkAllForDelete = (state) => {
  return state.update('items', list => list.map(item => item.set('markedForDelete', false)));
};

const deleteMarkedNotifs = (state) => {
  return state.update('items', list => list.filterNot(item => item.get('markedForDelete')));
};

export default function notifications(state = initialState, action) {
  let st;

  switch(action.type) {
  case NOTIFICATIONS_EXPAND_REQUEST:
  case NOTIFICATIONS_DELETE_MARKED_REQUEST:
    return state.set('isLoading', true);
  case NOTIFICATIONS_DELETE_MARKED_FAIL:
  case NOTIFICATIONS_EXPAND_FAIL:
    return state.set('isLoading', false);
  case NOTIFICATIONS_SCROLL_TOP:
    return updateTop(state, action.top);
  case NOTIFICATIONS_UPDATE:
    return normalizeNotification(state, action.notification);
  case NOTIFICATIONS_EXPAND_SUCCESS:
    return expandNormalizedNotifications(state, action.notifications, action.next);
  case ACCOUNT_BLOCK_SUCCESS:
  case ACCOUNT_MUTE_SUCCESS:
    return filterNotifications(state, action.relationship);
  case NOTIFICATIONS_CLEAR:
    return state.set('items', ImmutableList()).set('hasMore', false);
  case TIMELINE_DELETE:
    return deleteByStatus(state, action.id);
  case TIMELINE_DISCONNECT:
    return action.timeline === 'home' ?
      state.update('items', items => items.first() ? items.unshift(null) : items) :
      state;

  case NOTIFICATION_MARK_FOR_DELETE:
    return markForDelete(state, action.id, action.yes);

  case NOTIFICATIONS_DELETE_MARKED_SUCCESS:
    return deleteMarkedNotifs(state).set('isLoading', false);

  case NOTIFICATIONS_ENTER_CLEARING_MODE:
    st = state.set('cleaningMode', action.yes);
    if (!action.yes) {
      return unmarkAllForDelete(st).set('markNewForDelete', false);
    } else {
      return st;
    }

  case NOTIFICATIONS_MARK_ALL_FOR_DELETE:
    st = state;
    if (action.yes === null) {
      // Toggle - this is a bit confusing, as it toggles the all-none mode
      //st = st.set('markNewForDelete', !st.get('markNewForDelete'));
    } else {
      st = st.set('markNewForDelete', action.yes);
    }
    return markAllForDelete(st, action.yes);

  default:
    return state;
  }
};
<commit_msg>Accurately count deleted unread notifications<commit_after>import {
  NOTIFICATIONS_UPDATE,
  NOTIFICATIONS_EXPAND_SUCCESS,
  NOTIFICATIONS_EXPAND_REQUEST,
  NOTIFICATIONS_EXPAND_FAIL,
  NOTIFICATIONS_CLEAR,
  NOTIFICATIONS_SCROLL_TOP,
  NOTIFICATIONS_DELETE_MARKED_REQUEST,
  NOTIFICATIONS_DELETE_MARKED_SUCCESS,
  NOTIFICATION_MARK_FOR_DELETE,
  NOTIFICATIONS_DELETE_MARKED_FAIL,
  NOTIFICATIONS_ENTER_CLEARING_MODE,
  NOTIFICATIONS_MARK_ALL_FOR_DELETE,
} from 'flavours/glitch/actions/notifications';
import {
  ACCOUNT_BLOCK_SUCCESS,
  ACCOUNT_MUTE_SUCCESS,
} from 'flavours/glitch/actions/accounts';
import { TIMELINE_DELETE, TIMELINE_DISCONNECT } from 'flavours/glitch/actions/timelines';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import compareId from 'flavours/glitch/util/compare_id';

const initialState = ImmutableMap({
  items: ImmutableList(),
  hasMore: true,
  top: true,
  unread: 0,
  lastReadId: '0',
  isLoading: false,
  cleaningMode: false,
  // notification removal mark of new notifs loaded whilst cleaningMode is true.
  markNewForDelete: false,
});

const notificationToMap = (state, notification) => ImmutableMap({
  id: notification.id,
  type: notification.type,
  account: notification.account.id,
  markedForDelete: state.get('markNewForDelete'),
  status: notification.status ? notification.status.id : null,
});

const normalizeNotification = (state, notification) => {
  const top = state.get('top');

  if (top) {
    state = state.set('lastReadId', notification.id);
  } else {
    state = state.update('unread', unread => unread + 1);
  }

  return state.update('items', list => {
    if (top && list.size > 40) {
      list = list.take(20);
    }

    return list.unshift(notificationToMap(state, notification));
  });
};

const expandNormalizedNotifications = (state, notifications, next) => {
  const top = state.get('top');
  const lastReadId = state.get('lastReadId');
  let items = ImmutableList();

  notifications.forEach((n, i) => {
    items = items.set(i, notificationToMap(state, n));
  });

  return state.withMutations(mutable => {
    if (!items.isEmpty()) {
      mutable.update('items', list => {
        const lastIndex = 1 + list.findLastIndex(
          item => item !== null && (compareId(item.get('id'), items.last().get('id')) > 0 || item.get('id') === items.last().get('id'))
        );

        const firstIndex = 1 + list.take(lastIndex).findLastIndex(
          item => item !== null && compareId(item.get('id'), items.first().get('id')) > 0
        );

        return list.take(firstIndex).concat(items, list.skip(lastIndex));
      });
    }

    if (top) {
      if (!items.isEmpty()) {
        mutable.update('lastReadId', id => compareId(id, items.first().get('id')) > 0 ? id : items.first().get('id'));
      }
    } else {
      mutable.update('unread', unread => unread + items.filter(item => compareId(item.get('id'), lastReadId) > 0).size);
    }

    if (!next) {
      mutable.set('hasMore', true);
    }

    mutable.set('isLoading', false);
  });
};

const filterNotifications = (state, relationship) => {
  return state.update('items', list => list.filterNot(item => item !== null && item.get('account') === relationship.id));
};

const updateTop = (state, top) => {
  if (top) {
    state = state.set('unread', 0);
    const lastNotification = state.get('items').find(item => item !== null);
    state = state.set('lastReadId', lastNotification ? lastNotification.get('id') : '0');
  }

  return state.set('top', top);
};

const deleteByStatus = (state, statusId) => {
  if (!state.get('top')) {
    const lastReadId = state.get('lastReadId');
    const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0);
    state = state.update('unread', unread => unread - deletedUnread.size);
  }
  return state.update('items', list => list.filterNot(item => item !== null && item.get('status') === statusId));
};

const markForDelete = (state, notificationId, yes) => {
  return state.update('items', list => list.map(item => {
    if(item.get('id') === notificationId) {
      return item.set('markedForDelete', yes);
    } else {
      return item;
    }
  }));
};

const markAllForDelete = (state, yes) => {
  return state.update('items', list => list.map(item => {
    if(yes !== null) {
      return item.set('markedForDelete', yes);
    } else {
      return item.set('markedForDelete', !item.get('markedForDelete'));
    }
  }));
};

const unmarkAllForDelete = (state) => {
  return state.update('items', list => list.map(item => item.set('markedForDelete', false)));
};

const deleteMarkedNotifs = (state) => {
  return state.update('items', list => list.filterNot(item => item.get('markedForDelete')));
};

export default function notifications(state = initialState, action) {
  let st;

  switch(action.type) {
  case NOTIFICATIONS_EXPAND_REQUEST:
  case NOTIFICATIONS_DELETE_MARKED_REQUEST:
    return state.set('isLoading', true);
  case NOTIFICATIONS_DELETE_MARKED_FAIL:
  case NOTIFICATIONS_EXPAND_FAIL:
    return state.set('isLoading', false);
  case NOTIFICATIONS_SCROLL_TOP:
    return updateTop(state, action.top);
  case NOTIFICATIONS_UPDATE:
    return normalizeNotification(state, action.notification);
  case NOTIFICATIONS_EXPAND_SUCCESS:
    return expandNormalizedNotifications(state, action.notifications, action.next);
  case ACCOUNT_BLOCK_SUCCESS:
  case ACCOUNT_MUTE_SUCCESS:
    return filterNotifications(state, action.relationship);
  case NOTIFICATIONS_CLEAR:
    return state.set('items', ImmutableList()).set('hasMore', false);
  case TIMELINE_DELETE:
    return deleteByStatus(state, action.id);
  case TIMELINE_DISCONNECT:
    return action.timeline === 'home' ?
      state.update('items', items => items.first() ? items.unshift(null) : items) :
      state;

  case NOTIFICATION_MARK_FOR_DELETE:
    return markForDelete(state, action.id, action.yes);

  case NOTIFICATIONS_DELETE_MARKED_SUCCESS:
    return deleteMarkedNotifs(state).set('isLoading', false);

  case NOTIFICATIONS_ENTER_CLEARING_MODE:
    st = state.set('cleaningMode', action.yes);
    if (!action.yes) {
      return unmarkAllForDelete(st).set('markNewForDelete', false);
    } else {
      return st;
    }

  case NOTIFICATIONS_MARK_ALL_FOR_DELETE:
    st = state;
    if (action.yes === null) {
      // Toggle - this is a bit confusing, as it toggles the all-none mode
      //st = st.set('markNewForDelete', !st.get('markNewForDelete'));
    } else {
      st = st.set('markNewForDelete', action.yes);
    }
    return markAllForDelete(st, action.yes);

  default:
    return state;
  }
};
<|endoftext|>