<commit_before>
// var http = require('http');
// var fs = require('fs');
// var fserve = require('node-static');
// var http = require('http');

var yaml = require('js-yaml');
var tty = require('tty');
var path = require('path');
var mustache = require('mustache');
var express = require('express')
var sio = require('socket.io')

function TTY(command, actions) {
    var self = {};

    command = command.split(" ");
    var tty_values = tty.open(command[0], command.slice(1));
    var slave = tty_values[0];
    var proc = tty_values[1];
    var fd = proc.fds[0];

    self.set_window_size = function(nrows, ncols) {
        tty.setWindowSize(fd, nrows, ncols);
    }

    self.send = function(data) {
        slave.write(data);
    }

    self.send_signal = function(signal) {
        proc.kill(signal);
    }

    self.terminate = function(signal) {
        self.send_signal(signal);
        slave.destroy();
    }

    slave.on('data', function () {
        actions.data.apply(self, arguments);
    });
    proc.on('exit', function () {
        actions.exit.apply(self, arguments);
    });

    return self;
}

function TTYHandler(settings, actions) {

    var self = {};

    self.id = 0;

    self.make = function (id) {
        if (self[id]) {
            throw settings.type + " #" + id + " already exists";
        }
        var term = TTY(settings.command, actions);
        term.backlog = "";
        term.parent = self;
        term.id = id;
        console.log('Created TTY '
                    + settings.type
                    + '#' + id +
                    '; command = ' + settings.command);
        self[id] = term;
    }

    self.create = function () {
        while (self[self.id]) {
            self.id += 1;
        }
        self.make(self.id);
        return self.id;
    }

    self.notimeout = function (id) {
        var term = self[id];
        // console.log('clearing timeout: ' + id);
        if (term && term.timeout) {
            clearTimeout(term.timeout);
            term.timeout = null;
        }
    }

    self.schedule_terminate = function(id) {
        // console.log('scheduling timeout: ' + id);
        var term = self[id];
        // self.notimeout(id);
        if (settings.grace_period !== true) {
            if (!settings.grace_period) {
                self.terminate(id);
            }
            else {
                term.timeout = setTimeout(function () {
                    if (self[id] === term) {
                        self.terminate(id)
                    }
                }, settings.grace_period * 1000);
            }
        }
    }

    self.terminate = function(id) {
        var term = self[id];
        if (!term) {
            return;
        }
        self.notimeout(id);
        if (term.socket) {
            term.socket.disconnect();
            term.socket = null;
        }
        term.terminate();
        delete self[id];
        console.log('Terminated TTY '
                    + settings.type
                    + '#' + id +
                    '; command = ' + settings.command);
    }

    self.set_socket = function(id, socket) {
        var term = self[id];
        if (!term) { return; }
        self.notimeout(id);
        if (term.socket) {
            term.socket.disconnect();
        }
        term.socket = socket;
        if (term.backlog) {
            socket.emit('data', term.backlog.toString());
            term.backlog = "";
        }
    }

    return self;
}

var mustache_templater = {
    compile: function (source, options) {
        return function (options) {
            return mustache.to_html(source, options)
        }
    },
    render: function (source, options) {
        return this.compile(source, options)(options);
    }
};

function TerminusServer(settings) {
    var self = {};

    var app = express.createServer();
    var io = sio.listen(app);

    var handlers = {}

    io.set('log level', 1);
    app.set("view options", {layout: false});
    app.register(".tpl", mustache_templater);

    self.register_configuration = function (type, cfg) {
        cfg.type = type;
        var handler = TTYHandler(cfg, {
            data: function (data) {
                if (this.socket) {
                    this.socket.emit('data', data.toString());
                }
                else {
                    this.backlog += data;
                }
            },
            exit: function () {
                // if (this.socket) {
                //     this.socket.emit('close');
                // }
                if (this.socket) {
                    this.socket.emit('exit');
                }
                this.parent.terminate(this.id);
            }
        });

        handlers[type] = handler;

        app.get('/' + type, function (req, res) {
            var id = handler.create();
            res.redirect('/' + type + '/' + id);
        });

        app.get('/' + type + '/:id', function (req, res) {
            var id = req.params.id;
            console.log('Requesting: ' + type + "/" + id);
            if (!handler[id]) {
                handler.make(id);
            }
            else {
                handler.notimeout(id);
            }
            var client_settings = cfg.settings;
            if (typeof(client_settings) != "string") {
                throw "a list of settings is unsupported"
            }
            else {
                client_settings = '/resources/settings/' + client_settings;
            }
            res.render(path.join(settings.path,
                                 'page',
                                 cfg.template + '.tpl'),
                       {termtype: type,
                        id: id,
                        magic: 12345678,
                        style: cfg.style,
                        settings: client_settings,
                        server: settings.host,
                        port: settings.port})
        });
    }

    app.get('/f/*', function (req, res) {
        var file = req.params[0]
        res.sendfile(path.join('/', file));
    });

    app.get('/resources/*', function (req, res) {
        var file = req.params[0]
        res.sendfile(path.join(settings.path, file));
    });

    for (type in settings.configurations) {
        self.register_configuration(type, settings.configurations[type]);
    }

    io.sockets.on('connection', function (socket) {

        var command = null;
        var id = null;

        socket.on('connect_to', function (data) {
            console.log('connect to: ' + data.command + '/' + data.id);
            command = data.command;
            id = data.id;
            handlers[command].set_socket(id, socket);
        });

        socket.on('setsize', function (data) {
            if (command != null) {
                console.log(command + "#" + id + ' | setsize: ' + data.h + "x" + data.w);
                handlers[command][id].set_window_size(data.h, data.w);
            }
        });

        socket.on('data', function (data) {
            if (command != null) {
                handlers[command][id].send(data);
            }
        });

        socket.on('disconnect', function () {
            if (command != null) {
                handlers[command].schedule_terminate(id);
            }
        });
    });

    app.listen(settings.port);

    return self;
}

function main() {

    // var resource_path = path.resolve(process.argv[2]);
    // if (!resource_path) {
    //     console.error("Usage: "
    //                   + process.argv[0]
    //                   + " " + process.argv[1]
    //                   + " <resource path>");
    //     return
    // }

    // var settings_file = path.join(resource_path, 'settings', 'server.yaml');
    // var settings = require(settings_file)[0];
    // settings.path = resource_path;

    // TerminusServer(settings);

    var settings_file = path.resolve(process.argv[2]);
    var settings_dir = path.normalize(path.join(settings_file, '..'));
    var resource_path = process.argv[3];
    if (!settings_file) {
        console.error("Usage: "
                      + process.argv[0]
                      + " " + process.argv[1]
                      + " <server-settings.yaml>");
        return
    }

    // var settings_file = path.join(resource_path, 'settings', 'server.yaml');
    var settings = require(settings_file)[0];
    settings.path = path.resolve((resource_path || settings.path)
                                 .replace('$', settings_dir));

    console.log('resource path: ' + settings.path);

    TerminusServer(settings);
}

main();
<commit_msg>cleanup<commit_after>
var yaml = require('js-yaml');
var tty = require('tty');
var path = require('path');
var mustache = require('mustache');
var express = require('express')
var sio = require('socket.io')

function TTY(command, actions) {
    var self = {};

    command = command.split(" ");
    var tty_values = tty.open(command[0], command.slice(1));
    var slave = tty_values[0];
    var proc = tty_values[1];
    var fd = proc.fds[0];

    self.set_window_size = function(nrows, ncols) {
        tty.setWindowSize(fd, nrows, ncols);
    }

    self.send = function(data) {
        slave.write(data);
    }

    self.send_signal = function(signal) {
        proc.kill(signal);
    }

    self.terminate = function(signal) {
        self.send_signal(signal);
        slave.destroy();
    }

    slave.on('data', function () {
        actions.data.apply(self, arguments);
    });
    proc.on('exit', function () {
        actions.exit.apply(self, arguments);
    });

    return self;
}

function TTYHandler(settings, actions) {

    var self = {};

    self.id = 0;

    self.make = function (id) {
        if (self[id]) {
            throw settings.type + " #" + id + " already exists";
        }
        var term = TTY(settings.command, actions);
        term.backlog = "";
        term.parent = self;
        term.id = id;
        console.log('Created TTY '
                    + settings.type
                    + '#' + id +
                    '; command = ' + settings.command);
        self[id] = term;
    }

    self.create = function () {
        while (self[self.id]) {
            self.id += 1;
        }
        self.make(self.id);
        return self.id;
    }

    self.notimeout = function (id) {
        var term = self[id];
        if (term && term.timeout) {
            clearTimeout(term.timeout);
            term.timeout = null;
        }
    }

    self.schedule_terminate = function(id) {
        var term = self[id];
        self.notimeout(id);
        if (settings.grace_period !== true) {
            if (!settings.grace_period) {
                self.terminate(id);
            }
            else {
                term.timeout = setTimeout(function () {
                    if (self[id] === term) {
                        self.terminate(id)
                    }
                }, settings.grace_period * 1000);
            }
        }
    }

    self.terminate = function(id) {
        var term = self[id];
        if (!term) {
            return;
        }
        self.notimeout(id);
        if (term.socket) {
            term.socket.disconnect();
            term.socket = null;
        }
        term.terminate();
        delete self[id];
        console.log('Terminated TTY '
                    + settings.type
                    + '#' + id +
                    '; command = ' + settings.command);
    }

    self.set_socket = function(id, socket) {
        var term = self[id];
        if (!term) { return; }
        self.notimeout(id);
        if (term.socket) {
            term.socket.disconnect();
        }
        term.socket = socket;
        if (term.backlog) {
            socket.emit('data', term.backlog.toString());
            term.backlog = "";
        }
    }

    return self;
}

var mustache_templater = {
    compile: function (source, options) {
        return function (options) {
            return mustache.to_html(source, options)
        }
    },
    render: function (source, options) {
        return this.compile(source, options)(options);
    }
};

function TerminusServer(settings) {
    var self = {};

    var app = express.createServer();
    var io = sio.listen(app);

    var handlers = {}

    io.set('log level', 1);
    app.set("view options", {layout: false});
    app.register(".tpl", mustache_templater);

    self.register_configuration = function (type, cfg) {
        cfg.type = type;
        var handler = TTYHandler(cfg, {
            data: function (data) {
                if (this.socket) {
                    this.socket.emit('data', data.toString());
                }
                else {
                    this.backlog += data;
                }
            },
            exit: function () {
                if (this.socket) {
                    this.socket.emit('exit');
                }
                this.parent.terminate(this.id);
            }
        });

        handlers[type] = handler;

        app.get('/' + type, function (req, res) {
            var id = handler.create();
            res.redirect('/' + type + '/' + id);
        });

        app.get('/' + type + '/:id', function (req, res) {
            var id = req.params.id;
            console.log('Requesting: ' + type + "/" + id);
            if (!handler[id]) {
                handler.make(id);
            }
            else {
                handler.notimeout(id);
            }
            var client_settings = cfg.settings;
            if (typeof(client_settings) != "string") {
                throw "a list of settings is unsupported"
            }
            else {
                client_settings = '/resources/settings/' + client_settings;
            }
            res.render(path.join(settings.path,
                                 'page',
                                 cfg.template + '.tpl'),
                       {termtype: type,
                        id: id,
                        magic: 12345678,
                        style: cfg.style,
                        settings: client_settings,
                        server: settings.host,
                        port: settings.port})
        });
    }

    app.get('/f/*', function (req, res) {
        var file = req.params[0]
        res.sendfile(path.join('/', file));
    });

    app.get('/resources/*', function (req, res) {
        var file = req.params[0]
        res.sendfile(path.join(settings.path, file));
    });

    for (type in settings.configurations) {
        self.register_configuration(type, settings.configurations[type]);
    }

    io.sockets.on('connection', function (socket) {

        var command = null;
        var id = null;

        socket.on('connect_to', function (data) {
            console.log('connect to: ' + data.command + '/' + data.id);
            command = data.command;
            id = data.id;
            handlers[command].set_socket(id, socket);
        });

        socket.on('setsize', function (data) {
            if (command != null) {
                console.log(command + "#" + id + ' | setsize: ' + data.h + "x" + data.w);
                handlers[command][id].set_window_size(data.h, data.w);
            }
        });

        socket.on('data', function (data) {
            if (command != null) {
                handlers[command][id].send(data);
            }
        });

        socket.on('disconnect', function () {
            if (command != null) {
                handlers[command].schedule_terminate(id);
            }
        });
    });

    app.listen(settings.port);

    return self;
}

function main() {

    var settings_file = path.resolve(process.argv[2]);
    var settings_dir = path.normalize(path.join(settings_file, '..'));
    var resource_path = process.argv[3];
    if (!settings_file) {
        console.error("Usage: "
                      + process.argv[0]
                      + " " + process.argv[1]
                      + " <server-settings.yaml>");
        return
    }

    var settings = require(settings_file)[0];
    settings.path = path.resolve((resource_path || settings.path)
                                 .replace('$', settings_dir));

    console.log('resource path: ' + settings.path);

    TerminusServer(settings);
}

main();
<|endoftext|>


<commit_before><commit_msg>Убрал не нужные функции из asc_showRevision<commit_after><|endoftext|>


<commit_before>/*
 * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
 * Licence: MIT
 */

CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
{
    function pushCommand(state, command) {
	state.cmdState.push(command);
    }

    function peekCommand(state) {
	if (state.cmdState.length>0)
	    return state.cmdState[state.cmdState.length-1];
	else
	    return null;
    }

    function popCommand(state) {
	if (state.cmdState.length>0) {
	    var plug = state.cmdState.pop();
	    plug.closeBracket();
	}
    }

    function applyMostPowerful(state) {
      var context = state.cmdState;
      for (var i = context.length - 1; i >= 0; i--) {
	  var plug = context[i];
	  if (plug.name=="DEFAULT")
	      continue;
	  return plug.styleIdentifier();
      }
      return null;
    }

    function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
	return function () {
	    this.name=pluginName;
	    this.bracketNo = 0;
	    this.style=cmdStyle;
	    this.styles = styles;
	    this.brackets = brackets;

	    this.styleIdentifier = function(content) {
		if (this.bracketNo<=this.styles.length)
		    return this.styles[this.bracketNo-1];
		else
		    return null;
	    };
	    this.openBracket = function(content) {
		this.bracketNo++;
		return "bracket";
	    };
	    this.closeBracket = function(content) {
	    };
	}
    }

    var plugins = new Array();

    plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
    plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
    plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
    plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
    plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);

    plugins["DEFAULT"] = function () {
	this.name="DEFAULT";
	this.style="tag";

	this.styleIdentifier = function(content) {
	};
	this.openBracket = function(content) {
	};
	this.closeBracket = function(content) {
	};
    };

    function setState(state, f) {
	state.f = f;
    }

    function normal(source, state) {
	if (source.match(/^\\[a-zA-Z@]+/)) {
	    var cmdName = source.current();
	    cmdName = cmdName.substr(1, cmdName.length-1);
            var plug;
            if (plugins.hasOwnProperty(cmdName)) {
	      plug = plugins[cmdName];
            } else {
              plug = plugins["DEFAULT"];
            }
	    plug = new plug();
	    pushCommand(state, plug);
	    setState(state, beginParams);
	    return plug.style;
	}

        // escape characters
        if (source.match(/^\\[$&%#{}_]/)) {
          return "tag";
        }

        // white space control characters
        if (source.match(/^\\[,;!\/]/)) {
          return "tag";
        }

	var ch = source.next();
	if (ch == "%") {
            // special case: % at end of its own line; stay in same state
            if (!source.eol()) {
              setState(state, inCComment);
            }
	    return "comment";
	}
	else if (ch=='}' || ch==']') {
	    plug = peekCommand(state);
	    if (plug) {
		plug.closeBracket(ch);
		setState(state, beginParams);
	    } else
		return "error";
	    return "bracket";
	} else if (ch=='{' || ch=='[') {
	    plug = plugins["DEFAULT"];
	    plug = new plug();
	    pushCommand(state, plug);
	    return "bracket";
	}
	else if (/\d/.test(ch)) {
	    source.eatWhile(/[\w.%]/);
	    return "atom";
	}
	else {
	    source.eatWhile(/[\w-_]/);
	    return applyMostPowerful(state);
	}
    }

    function inCComment(source, state) {
	source.skipToEnd();
	setState(state, normal);
	return "comment";
    }

    function beginParams(source, state) {
	var ch = source.peek();
	if (ch == '{' || ch == '[') {
	   var lastPlug = peekCommand(state);
	   var style = lastPlug.openBracket(ch);
	   source.eat(ch);
	   setState(state, normal);
	   return "bracket";
	}
	if (/[ \t\r]/.test(ch)) {
	    source.eat(ch);
	    return null;
	}
	setState(state, normal);
	lastPlug = peekCommand(state);
	if (lastPlug) {
	    popCommand(state);
	}
        return normal(source, state);
    }

    return {
     startState: function() { return { f:normal, cmdState:[] }; },
	 copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },

	 token: function(stream, state) {
	 var t = state.f(stream, state);
	 var w = stream.current();
	 return t;
     }
 };
});

CodeMirror.defineMIME("text/x-stex", "stex");
<commit_msg>[stex] support mime type `text/x-latex`<commit_after>/*
 * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
 * Licence: MIT
 */

CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
{
    function pushCommand(state, command) {
	state.cmdState.push(command);
    }

    function peekCommand(state) {
	if (state.cmdState.length>0)
	    return state.cmdState[state.cmdState.length-1];
	else
	    return null;
    }

    function popCommand(state) {
	if (state.cmdState.length>0) {
	    var plug = state.cmdState.pop();
	    plug.closeBracket();
	}
    }

    function applyMostPowerful(state) {
      var context = state.cmdState;
      for (var i = context.length - 1; i >= 0; i--) {
	  var plug = context[i];
	  if (plug.name=="DEFAULT")
	      continue;
	  return plug.styleIdentifier();
      }
      return null;
    }

    function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
	return function () {
	    this.name=pluginName;
	    this.bracketNo = 0;
	    this.style=cmdStyle;
	    this.styles = styles;
	    this.brackets = brackets;

	    this.styleIdentifier = function(content) {
		if (this.bracketNo<=this.styles.length)
		    return this.styles[this.bracketNo-1];
		else
		    return null;
	    };
	    this.openBracket = function(content) {
		this.bracketNo++;
		return "bracket";
	    };
	    this.closeBracket = function(content) {
	    };
	}
    }

    var plugins = new Array();

    plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
    plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
    plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
    plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
    plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);

    plugins["DEFAULT"] = function () {
	this.name="DEFAULT";
	this.style="tag";

	this.styleIdentifier = function(content) {
	};
	this.openBracket = function(content) {
	};
	this.closeBracket = function(content) {
	};
    };

    function setState(state, f) {
	state.f = f;
    }

    function normal(source, state) {
	if (source.match(/^\\[a-zA-Z@]+/)) {
	    var cmdName = source.current();
	    cmdName = cmdName.substr(1, cmdName.length-1);
            var plug;
            if (plugins.hasOwnProperty(cmdName)) {
	      plug = plugins[cmdName];
            } else {
              plug = plugins["DEFAULT"];
            }
	    plug = new plug();
	    pushCommand(state, plug);
	    setState(state, beginParams);
	    return plug.style;
	}

        // escape characters
        if (source.match(/^\\[$&%#{}_]/)) {
          return "tag";
        }

        // white space control characters
        if (source.match(/^\\[,;!\/]/)) {
          return "tag";
        }

	var ch = source.next();
	if (ch == "%") {
            // special case: % at end of its own line; stay in same state
            if (!source.eol()) {
              setState(state, inCComment);
            }
	    return "comment";
	}
	else if (ch=='}' || ch==']') {
	    plug = peekCommand(state);
	    if (plug) {
		plug.closeBracket(ch);
		setState(state, beginParams);
	    } else
		return "error";
	    return "bracket";
	} else if (ch=='{' || ch=='[') {
	    plug = plugins["DEFAULT"];
	    plug = new plug();
	    pushCommand(state, plug);
	    return "bracket";
	}
	else if (/\d/.test(ch)) {
	    source.eatWhile(/[\w.%]/);
	    return "atom";
	}
	else {
	    source.eatWhile(/[\w-_]/);
	    return applyMostPowerful(state);
	}
    }

    function inCComment(source, state) {
	source.skipToEnd();
	setState(state, normal);
	return "comment";
    }

    function beginParams(source, state) {
	var ch = source.peek();
	if (ch == '{' || ch == '[') {
	   var lastPlug = peekCommand(state);
	   var style = lastPlug.openBracket(ch);
	   source.eat(ch);
	   setState(state, normal);
	   return "bracket";
	}
	if (/[ \t\r]/.test(ch)) {
	    source.eat(ch);
	    return null;
	}
	setState(state, normal);
	lastPlug = peekCommand(state);
	if (lastPlug) {
	    popCommand(state);
	}
        return normal(source, state);
    }

    return {
     startState: function() { return { f:normal, cmdState:[] }; },
	 copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },

	 token: function(stream, state) {
	 var t = state.f(stream, state);
	 var w = stream.current();
	 return t;
     }
 };
});

CodeMirror.defineMIME("text/x-stex", "stex");
CodeMirror.defineMIME("text/x-latex", "stex");
<|endoftext|>


<commit_before>var pg = require('pg');
var step = require('step');
var ltx = require('ltx');
var errors = require('./errors');

/* ready DB connections */
var pool = [];
/* waiting transaction requests */
var queue = [];

/* at start and when connection died */
function connectDB(config) {
    var db = new pg.Client(config);
    db.connect();

    /* Reconnect in up to 5s */
    db.on('error', function(err) {
	console.error('Postgres: ' + err.message);
	setTimeout(function() {
	    connectDB(config);
	}, Math.ceil(Math.random() * 5000));
	try { db.end(); } catch (e) { /* Alright */ }
    });

    /* wait until connected & authed */
    db.connection.once('readyForQuery', function() {
	dbIsAvailable(db);
    });
}

function dbIsAvailable(db) {
    var cb;
    if ((cb = queue.shift())) {
	/* request was waiting in queue */
	cb(db);
    } else {
	/* no request, put into pool */
	pool.push(db);
    }
}

/* config: { user, database, host, port, poolSize: 4 } */
exports.start = function(config) {
    for(var i = 0; i < (config.poolSize || 4); i++) {
	connectDB(config);
    }
};

exports.transaction = function(cb) {
    var db;
    if ((db = pool.shift())) {
	/* Got one from pool */
	new Transaction(db, cb);
    } else {
	/* Pool was empty, waiting... TODO: limit length, shift first */
	queue.push(function() {
	    new Transaction(db, cb);
	});
    }
};

/**
 * Wraps the postgres-js transaction with our model operations.
 */
function Transaction(db, cb) {
    var that = this;
    this.db = db;

    db.query("BEGIN", [], function(err, res) {
	cb(err, that);
    });
}

Transaction.prototype.commit = function(cb) {
    var db = this.db;
    db.query("COMMIT", [], function(err, res) {
	process.nextTick(function() {
	    dbIsAvailable(db);
	});

	cb(err);
    });
};

Transaction.prototype.rollback = function(cb) {
    var db = this.db;

    db.query("ROLLBACK", [], function(err, res) {
	process.nextTick(function() {
	    dbIsAvailable(db);
	});

	cb(err);
    });
};

/**
 * Actual data model
 */

Transaction.prototype.nodeExists = function(db, node) {
    return function(cb) {
	step(function() {
		 db.query("SELECT node FROM nodes WHERE node=$1",
			  [node], this);
	     }, function(err, res) {
		 if (err) throw err;

		 if (res.rowCount < 1)
		     throw new errors.NotFound('Node does not exist');

		 this();
	     }, cb);
    };
};

Transaction.prototype.createNode = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node FROM nodes WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rowCount > 0)
	    throw new errors.Conflict('Node already exists');

	db.query("INSERT INTO nodes (node) VALUES ($1)", [node], this);
    }, cb);
};

/**
 * cb(err, [{ node: String, title: String }])
 */
Transaction.prototype.listNodes = function(cb) {
    var db = this.db;

    step(function() {
	/* TODO: order by COUNT(subscribers) */
	db.query("SELECT node FROM nodes WHERE node IN (SELECT node FROM node_config WHERE \"key\"=\'accessModel\' AND \"value\"=\'open\') " +
		 "ORDER BY node ASC", this);
    }, function(err, res) {
	if (err) throw err;

	var nodes = res.rows.map(function(row) {
	    return { node: row.node,
		     title: row.title
		   };
	});
	this(null, nodes);
    }, cb);
};

/**
 * Subscription management
 */

Transaction.prototype.getSubscription = function(node, user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT subscription FROM subscriptions WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, (res.rows[0] && res.rows[0].subscription) || 'none');
    }, cb);
};

Transaction.prototype.setSubscription = function(node, user, subscription, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT subscription FROM subscriptions WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	var toDelete = !subscription || subscription == 'none';
	if (isSet && !toDelete)
	    db.query("UPDATE subscriptions SET subscription=$1 WHERE node=$2 AND \"user\"=$3",
		     [subscription, node, user], this);
	else if (!isSet && !toDelete)
	    db.query("INSERT INTO subscriptions (node, \"user\", subscription) VALUES ($1, $2, $3)",
		     [node, user, subscription], this);
	else if (isSet && toDelete)
	    db.query("DELETE FROM subscriptions WHERE node=$1 AND \"user\"=$2",
		     [node, user], this);
	else if (!isSet && toDelete)
	    cb(null);  /* do nothing */
    }, cb);
};

Transaction.prototype.getSubscribers = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\", subscription FROM subscriptions WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var subscribers = [];
	res.rows.forEach(function(row) {
	    subscribers.push({ user: row.user,
			       subscription: row.subscription });
	});
	this(null, subscribers);
    }, cb);
};

Transaction.prototype.getSubscriptions = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node, subscription FROM subscriptions WHERE \"user\"=$1",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	var subscriptions = [];
	res.rows.forEach(function(row) {
	    subscriptions.push({ node: row.node,
				 subscription: row.subscription });
	});
	this(null, subscriptions);
    }, cb);
};

Transaction.prototype.getAllSubscribers = function(cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT DISTINCT \"user\" FROM subscriptions",
		 this);
    }, function(err, res) {
	if (err) throw err;

	var subscribers = [];
	res.rows.forEach(function(row) {
	    subscribers.push(row.user);
	});
	this(null, subscribers);
    }, cb);
};

Transaction.prototype.getPendingNodes = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node FROM affiliations WHERE affiliation = 'owner' AND user = $1 AND EXISTS (SELECT user FROM subscriptions WHERE subscription = 'pending' AND node = affiliations.node)",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.node;
	}));
    }, cb);
};

Transaction.prototype.getPending = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT user FROM subscriptions WHERE subscription = 'pending' AND node = $1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.user;
	}));
    }, cb);
};

/**
 * Affiliation management
 */

Transaction.prototype.getAffiliation = function(node, user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT affiliation FROM affiliations WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, (res.rows[0] && res.rows[0].affiliation) || 'none');
    }, cb);
};

Transaction.prototype.setAffiliation = function(node, user, affiliation, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT affiliation FROM affiliations WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	var toDelete = !affiliation || affiliation == 'none';
	if (isSet && !toDelete)
	    db.query("UPDATE affiliations SET affiliation=$1 WHERE node=$2 AND \"user\"=$3",
		     [affiliation, node, user], this);
	else if (!isSet && !toDelete)
	    db.query("INSERT INTO affiliations (node, \"user\", affiliation) VALUES ($1, $2, $3)",
		     [node, user, affiliation], this);
	else if (isSet && toDelete)
	    db.query("DELETE FROM affiliations WHERE node=$1 AND \"user\"=$2",
		     [node, user], this);
	else if (!isSet && toDelete)
	    cb(null);  /* do nothing */
    }, cb);
};

Transaction.prototype.getAffiliations = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node, affiliation FROM affiliations WHERE \"user\"=$1",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	var affiliations = [];
	res.rows.forEach(function(row) {
	    affiliations.push({ node: row.node,
				affiliation: row.affiliation });
	});
	this(null, affiliations);
    }, cb);
};

Transaction.prototype.getAffiliated = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\", affiliation FROM affiliations WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var affiliations = [];
	res.rows.forEach(function(row) {
	    affiliations.push({ user: row.user,
				affiliation: row.affiliation });
	});
	this(null, affiliations);
    }, cb);
};

Transaction.prototype.getOwners = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\" FROM affiliations WHERE node=$1 AND affiliation='owner'",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.user;
	}));
    }, cb);
};

Transaction.prototype.writeItem = function(publisher, node, id, item, cb) {
    var db = this.db;
    var xml = item.join('').toString();

    step(function() {
	db.query("SELECT id FROM items WHERE node=$1 AND id=$2",
		 [node, id], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	if (isSet)
	    db.query("UPDATE items SET xml=$1, published=CURRENT_TIMESTAMP WHERE node=$2 AND id=$3",
		     [xml, node, id], this);
	else if (!isSet)
	    db.query("INSERT INTO items (node, id, xml, published) VALUES ($1, $2, $3, CURRENT_TIMESTAMP)",
		     [node, id, xml], this);
    }, cb);
};

Transaction.prototype.deleteItem = function(node, itemId, cb) {
    var db = this.db;

    step(function() {
	db.query("DELETE FROM items WHERE node=$1 AND id=$2",
		 [node, itemId], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rowCount < 1)
	    throw new errors.NotFound('No such item');

	this(null);
    }, cb);
};

/**
 * sorted by time
 */
Transaction.prototype.getItemIds = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT id FROM items WHERE node=$1 ORDER BY published DESC",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var ids = res.rows.map(function(row) {
	    return row.id;
	});
	this(null, ids);
    }, cb);
};

Transaction.prototype.getItem = function(node, id, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT xml FROM items WHERE node=$1 AND id=$2",
		 [node, id], this);
    }, function(err, res) {
	if (err) throw err;

	if (res && res.rows && res.rows[0]) {
	    var item;
	    try {
		item = ltx.parse('<r>' + res.rows[0].xml + '</r>').children;
	    } catch (e) {
		console.error('Parsing ' + JSON.stringify({node:node,id:id}) + ': ' + e.stack);
		item = [];
	    }
	    this(null, item);
	} else {
	    throw new errors.NotFound('No such item');
	}
    }, cb);
};

/**
 * Config management
 */

Transaction.prototype.getConfig = function(node, cb) {
    var db = this.db;

    step(this.nodeExists(db, node),
    function() {
	db.query("SELECT \"key\", \"value\" FROM node_config WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rows) {
	    var config = {};
	    res.rows.forEach(function(row) {
		config[row.key] = row.value;
	    });
	    this(null, config);
	} else
	    throw new errors.NotFound('No such node');
    }, cb);
};

Transaction.prototype.setConfig = function(node, config, cb) {
    var db = this.db;

    step(this.nodeExists(db, node),
    function() {
	var g = this.group();
	for(var key in config)
	    if (config.hasOwnProperty(key)) {
		var value = config[key];
		db.query("UPDATE node_config SET key=$1, value=$2 WHERE node=$3",
		    [key, value, node], g);
	    }
	g();
    }, function(err, res) {
	if (err) throw err;

	this(null);
    }, cb);
};
<commit_msg>model_postgres: config fixes<commit_after>var pg = require('pg');
var step = require('step');
var ltx = require('ltx');
var errors = require('./errors');

/* ready DB connections */
var pool = [];
/* waiting transaction requests */
var queue = [];

/* at start and when connection died */
function connectDB(config) {
    var db = new pg.Client(config);
    db.connect();

    /* Reconnect in up to 5s */
    db.on('error', function(err) {
	console.error('Postgres: ' + err.message);
	setTimeout(function() {
	    connectDB(config);
	}, Math.ceil(Math.random() * 5000));
	try { db.end(); } catch (e) { /* Alright */ }
    });

    /* wait until connected & authed */
    db.connection.once('readyForQuery', function() {
	dbIsAvailable(db);
    });
}

function dbIsAvailable(db) {
    var cb;
    if ((cb = queue.shift())) {
	/* request was waiting in queue */
	cb(db);
    } else {
	/* no request, put into pool */
	pool.push(db);
    }
}

/* config: { user, database, host, port, poolSize: 4 } */
exports.start = function(config) {
    for(var i = 0; i < (config.poolSize || 4); i++) {
	connectDB(config);
    }
};

exports.transaction = function(cb) {
    var db;
    if ((db = pool.shift())) {
	/* Got one from pool */
	new Transaction(db, cb);
    } else {
	/* Pool was empty, waiting... TODO: limit length, shift first */
	queue.push(function() {
	    new Transaction(db, cb);
	});
    }
};

/**
 * Wraps the postgres-js transaction with our model operations.
 */
function Transaction(db, cb) {
    var that = this;
    this.db = db;

    db.query("BEGIN", [], function(err, res) {
	cb(err, that);
    });
}

Transaction.prototype.commit = function(cb) {
    var db = this.db;
    db.query("COMMIT", [], function(err, res) {
	process.nextTick(function() {
	    dbIsAvailable(db);
	});

	cb(err);
    });
};

Transaction.prototype.rollback = function(cb) {
    var db = this.db;

    db.query("ROLLBACK", [], function(err, res) {
	process.nextTick(function() {
	    dbIsAvailable(db);
	});

	cb(err);
    });
};

/**
 * Actual data model
 */

/**
 * Can be dropped in a step() sequence to validate presence of a node.
 */
Transaction.prototype.nodeExists = function(node) {
    var db = this.db;

    return function() {
	step(function() {
		 db.query("SELECT node FROM nodes WHERE node=$1",
			  [node], this);
	     }, function(err, res) {
		 if (err) throw err;

		 if (res.rowCount < 1)
		     throw new errors.NotFound('Node does not exist');

		 this();
	     }, this);
    };
};

Transaction.prototype.createNode = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node FROM nodes WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rowCount > 0)
	    throw new errors.Conflict('Node already exists');

	db.query("INSERT INTO nodes (node) VALUES ($1)", [node], this);
    }, cb);
};

/**
 * cb(err, [{ node: String, title: String }])
 */
Transaction.prototype.listNodes = function(cb) {
    var db = this.db;

    step(function() {
	/* TODO: order by COUNT(subscribers) */
	db.query("SELECT node FROM nodes WHERE node IN (SELECT node FROM node_config WHERE \"key\"=\'accessModel\' AND \"value\"=\'open\') " +
		 "ORDER BY node ASC", this);
    }, function(err, res) {
	if (err) throw err;

	var nodes = res.rows.map(function(row) {
	    return { node: row.node,
		     title: row.title
		   };
	});
	this(null, nodes);
    }, cb);
};

/**
 * Subscription management
 */

Transaction.prototype.getSubscription = function(node, user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT subscription FROM subscriptions WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, (res.rows[0] && res.rows[0].subscription) || 'none');
    }, cb);
};

Transaction.prototype.setSubscription = function(node, user, subscription, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT subscription FROM subscriptions WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	var toDelete = !subscription || subscription == 'none';
	if (isSet && !toDelete)
	    db.query("UPDATE subscriptions SET subscription=$1 WHERE node=$2 AND \"user\"=$3",
		     [subscription, node, user], this);
	else if (!isSet && !toDelete)
	    db.query("INSERT INTO subscriptions (node, \"user\", subscription) VALUES ($1, $2, $3)",
		     [node, user, subscription], this);
	else if (isSet && toDelete)
	    db.query("DELETE FROM subscriptions WHERE node=$1 AND \"user\"=$2",
		     [node, user], this);
	else if (!isSet && toDelete)
	    cb(null);  /* do nothing */
    }, cb);
};

Transaction.prototype.getSubscribers = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\", subscription FROM subscriptions WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var subscribers = [];
	res.rows.forEach(function(row) {
	    subscribers.push({ user: row.user,
			       subscription: row.subscription });
	});
	this(null, subscribers);
    }, cb);
};

Transaction.prototype.getSubscriptions = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node, subscription FROM subscriptions WHERE \"user\"=$1",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	var subscriptions = [];
	res.rows.forEach(function(row) {
	    subscriptions.push({ node: row.node,
				 subscription: row.subscription });
	});
	this(null, subscriptions);
    }, cb);
};

Transaction.prototype.getAllSubscribers = function(cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT DISTINCT \"user\" FROM subscriptions",
		 this);
    }, function(err, res) {
	if (err) throw err;

	var subscribers = [];
	res.rows.forEach(function(row) {
	    subscribers.push(row.user);
	});
	this(null, subscribers);
    }, cb);
};

Transaction.prototype.getPendingNodes = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node FROM affiliations WHERE affiliation = 'owner' AND user = $1 AND EXISTS (SELECT user FROM subscriptions WHERE subscription = 'pending' AND node = affiliations.node)",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.node;
	}));
    }, cb);
};

Transaction.prototype.getPending = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT user FROM subscriptions WHERE subscription = 'pending' AND node = $1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.user;
	}));
    }, cb);
};

/**
 * Affiliation management
 */

Transaction.prototype.getAffiliation = function(node, user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT affiliation FROM affiliations WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, (res.rows[0] && res.rows[0].affiliation) || 'none');
    }, cb);
};

Transaction.prototype.setAffiliation = function(node, user, affiliation, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT affiliation FROM affiliations WHERE node=$1 AND user=$2",
		 [node, user], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	var toDelete = !affiliation || affiliation == 'none';
	if (isSet && !toDelete)
	    db.query("UPDATE affiliations SET affiliation=$1 WHERE node=$2 AND \"user\"=$3",
		     [affiliation, node, user], this);
	else if (!isSet && !toDelete)
	    db.query("INSERT INTO affiliations (node, \"user\", affiliation) VALUES ($1, $2, $3)",
		     [node, user, affiliation], this);
	else if (isSet && toDelete)
	    db.query("DELETE FROM affiliations WHERE node=$1 AND \"user\"=$2",
		     [node, user], this);
	else if (!isSet && toDelete)
	    cb(null);  /* do nothing */
    }, cb);
};

Transaction.prototype.getAffiliations = function(user, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT node, affiliation FROM affiliations WHERE \"user\"=$1",
		 [user], this);
    }, function(err, res) {
	if (err) throw err;

	var affiliations = [];
	res.rows.forEach(function(row) {
	    affiliations.push({ node: row.node,
				affiliation: row.affiliation });
	});
	this(null, affiliations);
    }, cb);
};

Transaction.prototype.getAffiliated = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\", affiliation FROM affiliations WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var affiliations = [];
	res.rows.forEach(function(row) {
	    affiliations.push({ user: row.user,
				affiliation: row.affiliation });
	});
	this(null, affiliations);
    }, cb);
};

Transaction.prototype.getOwners = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT \"user\" FROM affiliations WHERE node=$1 AND affiliation='owner'",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	this(null, res.rows.map(function(row) {
	    return row.user;
	}));
    }, cb);
};

Transaction.prototype.writeItem = function(publisher, node, id, item, cb) {
    var db = this.db;
    var xml = item.join('').toString();

    step(function() {
	db.query("SELECT id FROM items WHERE node=$1 AND id=$2",
		 [node, id], this);
    }, function(err, res) {
	if (err) throw err;

	var isSet = res && res.rows && res.rows[0];
	if (isSet)
	    db.query("UPDATE items SET xml=$1, published=CURRENT_TIMESTAMP WHERE node=$2 AND id=$3",
		     [xml, node, id], this);
	else if (!isSet)
	    db.query("INSERT INTO items (node, id, xml, published) VALUES ($1, $2, $3, CURRENT_TIMESTAMP)",
		     [node, id, xml], this);
    }, cb);
};

Transaction.prototype.deleteItem = function(node, itemId, cb) {
    var db = this.db;

    step(function() {
	db.query("DELETE FROM items WHERE node=$1 AND id=$2",
		 [node, itemId], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rowCount < 1)
	    throw new errors.NotFound('No such item');

	this(null);
    }, cb);
};

/**
 * sorted by time
 */
Transaction.prototype.getItemIds = function(node, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT id FROM items WHERE node=$1 ORDER BY published DESC",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	var ids = res.rows.map(function(row) {
	    return row.id;
	});
	this(null, ids);
    }, cb);
};

Transaction.prototype.getItem = function(node, id, cb) {
    var db = this.db;

    step(function() {
	db.query("SELECT xml FROM items WHERE node=$1 AND id=$2",
		 [node, id], this);
    }, function(err, res) {
	if (err) throw err;

	if (res && res.rows && res.rows[0]) {
	    var item;
	    try {
		item = ltx.parse('<r>' + res.rows[0].xml + '</r>').children;
	    } catch (e) {
		console.error('Parsing ' + JSON.stringify({node:node,id:id}) + ': ' + e.stack);
		item = [];
	    }
	    this(null, item);
	} else {
	    throw new errors.NotFound('No such item');
	}
    }, cb);
};

/**
 * Config management
 */

Transaction.prototype.getConfig = function(node, cb) {
    var db = this.db;

    step(this.nodeExists(node),
    function(err) {
	if (err) throw err;

	db.query("SELECT \"key\", \"value\" FROM node_config WHERE node=$1",
		 [node], this);
    }, function(err, res) {
	if (err) throw err;

	if (res.rows) {
	    var config = {};
	    res.rows.forEach(function(row) {
		config[row.key] = row.value;
	    });
	    this(null, config);
	} else
	    throw new errors.NotFound('No such node');
    }, cb);
};

Transaction.prototype.setConfig = function(node, config, cb) {
    var db = this.db;

console.log('setConfig ' + node + ': ' + require('util').inspect(config));
    step(this.nodeExists(node),
    function(err) {
	if (err) throw err;

	/* If user supplied only partial information, old/default
	 * values will be added by controller. That way we can just
	 * INSERT later. */
	 db.query("DELETE FROM node_config WHERE node=$1", [node], this);
    }, function(err) {
	if (err) throw err;

	var g = this.group();
	for(var key in config)
	    if (config.hasOwnProperty(key)) {
		var value = config[key];
		db.query("INSERT node_config SET key=$1, value=$2 WHERE node=$3",
		    [key, value, node], g);
	    }
	g();
    }, function(err, res) {
	if (err) throw err;

	this(null);
    }, cb);
};
<|endoftext|>


<commit_before>var request = require('request'),
    $ = cheerio = require('cheerio'),
    q = require('q'),
    config = require('../config'),
    analyse = require('./analysis.' + config.analyser.api),
    countriesToCities = require('../vendor/CountriesToCitiesJSON/countriesToCities'),
    countryCodes = require('../countries');

var cities = loadCities(countriesToCities);

var countries = loadCountries(countriesToCities);

function loadCountries (countriesToCities) {

    console.log('loadCountries()');

    var countries = [];

    countries = countries.concat(Object.keys(countriesToCities));

    console.log(countries.length);

    return countries;
}

function loadCities (countriesToCities) {

    // console.log('loadCities()');

    var cities = [];

    Object.keys(countriesToCities).forEach(function (country) {
        if (countriesToCities[country].length) {
            cities = cities.concat(countriesToCities[country]);
        }
    });

    return cities;
}

var Article = function (url, headlineSelector, storySelector, isConflict) {

    this.url = url;
    this.headlineSelector = headlineSelector;
    this.storySelector = storySelector;
    this.isConflict = isConflict;
    this.countries = [];
    this.cities = [];

    this.analysis = {
        locations : [],
        classifications : []
    };
    this.data = {};
    this.inaccuracy = 0.01;
    this.created = Date.now();
}

Article.prototype.scrape = function () {

    console.log('scrape()');

    console.log(this.url);

    var dfd = q.defer();

    request(this.url, function (error, response, body) {

        var isOk = !error && response.statusCode === 200;

        body = isOk ? body : '';

        dfd.resolve(body);
    });

    return dfd.promise;
};

Article.prototype.format = function (body) {

    // console.log('format()');

    var $ = cheerio.load(body);

    var $headline = $(this.headlineSelector).first();

    var $story = $(this.storySelector);

    // console.log($headline.text());

    if ($headline.length > 0) {

        this.data.headline = $headline.text().trim();

        this.data.story = $story.text().trim();
    }

    return q();
};

Article.prototype.interpret = function () {

    // console.log('interpret()');

    var article = this;

    // http://cv.iptc.org/newscodes/subjectcode/16000000
    function isConflict (classifications) {

        article.inaccuracy += config.analyser.imprecision.classification;

        var isConflict = false;
        var regex = /^160[0-9]*/;
        classifications.forEach(function (classification) {
            if (regex.test(classification.code)) {
                isConflict = true;
                return false;
            }
        });
        return isConflict;
    }

    function processLocations () {

        console.log('processLocations()');

        var locations = article.analysis.locations || [];

        for (var i = 0, j = locations.length; i < j; i++) {

            console.log(locations[i]);

            if (isCountry(locations[i])) {

                console.log('country ', locations[i]);

                article.countries.push({
                    name : locations[i],
                    code : getCountryCode(locations[i])
                });

            } else if (isCity(locations[i])) {

                console.log('city ', locations[i]);

                article.cities.push(locations[i]);

            }
        }
    }

    function isCountry (location) {

        // console.log('isCountry()');

        article.inaccuracy += config.analyser.imprecision.country;

        return (countries.indexOf(location) != -1);
    }

    function getCountryCode (country) {
        // console.log('getCountryCode() ', country);
        var code = '';
        for (var i = 0, j = countryCodes.length; i < j; i++) {
            if (country.toLowerCase() === countryCodes[i].name.toLowerCase()) {
                code = countryCodes[i].code;
                break;
            }
        }
        console.log(code);
        return code;
    }

    function isCity (location) {

        // console.log('isCity()');

        // console.log(location);

        article.inaccuracy += config.analyser.imprecision.city;

        return (cities.indexOf(location) != -1);
    }

    if (!article.isConflict) {

        article.isConflict = isConflict(article.analysis.classifications);
    }

    processLocations();

    return q();

};

Article.prototype.analyse = analyse;

module.exports = Article;

<commit_msg>empty body check<commit_after>var request = require('request'),
    $ = cheerio = require('cheerio'),
    q = require('q'),
    config = require('../config'),
    analyse = require('./analysis.' + config.analyser.api),
    countriesToCities = require('../vendor/CountriesToCitiesJSON/countriesToCities'),
    countryCodes = require('../countries');

var cities = loadCities(countriesToCities);

var countries = loadCountries(countriesToCities);

function loadCountries (countriesToCities) {

    console.log('loadCountries()');

    var countries = [];

    countries = countries.concat(Object.keys(countriesToCities));

    console.log(countries.length);

    return countries;
}

function loadCities (countriesToCities) {

    // console.log('loadCities()');

    var cities = [];

    Object.keys(countriesToCities).forEach(function (country) {
        if (countriesToCities[country].length) {
            cities = cities.concat(countriesToCities[country]);
        }
    });

    return cities;
}

var Article = function (url, headlineSelector, storySelector, isConflict) {

    this.url = url;
    this.headlineSelector = headlineSelector;
    this.storySelector = storySelector;
    this.isConflict = isConflict;
    this.countries = [];
    this.cities = [];

    this.analysis = {
        locations : [],
        classifications : []
    };
    this.data = {};
    this.inaccuracy = 0.01;
    this.created = Date.now();
}

Article.prototype.scrape = function () {

    console.log('scrape()');

    console.log(this.url);

    var dfd = q.defer();

    request(this.url, function (error, response, body) {

        var isOk = !error && response.statusCode === 200;

        body = isOk ? body : '';

        dfd.resolve(body);
    });

    return dfd.promise;
};

Article.prototype.format = function (body) {

    // console.log('format()');

    var $ = cheerio.load(body);

    var $headline = $(this.headlineSelector).first();

    var $story = $(this.storySelector);

    // console.log($headline.text());

    if ($headline.length > 0 && $story.length > 0) {

        this.data.headline = $headline.text().trim();

        this.data.story = $story.text().trim();
    }

    return q();
};

Article.prototype.interpret = function () {

    // console.log('interpret()');

    var article = this;

    // http://cv.iptc.org/newscodes/subjectcode/16000000
    function isConflict (classifications) {

        article.inaccuracy += config.analyser.imprecision.classification;

        var isConflict = false;
        var regex = /^160[0-9]*/;
        classifications.forEach(function (classification) {
            if (regex.test(classification.code)) {
                isConflict = true;
                return false;
            }
        });
        return isConflict;
    }

    function processLocations () {

        console.log('processLocations()');

        var locations = article.analysis.locations || [];

        for (var i = 0, j = locations.length; i < j; i++) {

            console.log(locations[i]);

            if (isCountry(locations[i])) {

                console.log('country ', locations[i]);

                article.countries.push({
                    name : locations[i],
                    code : getCountryCode(locations[i])
                });

            } else if (isCity(locations[i])) {

                console.log('city ', locations[i]);

                article.cities.push(locations[i]);

            }
        }
    }

    function isCountry (location) {

        // console.log('isCountry()');

        article.inaccuracy += config.analyser.imprecision.country;

        return (countries.indexOf(location) != -1);
    }

    function getCountryCode (country) {
        // console.log('getCountryCode() ', country);
        var code = '';
        for (var i = 0, j = countryCodes.length; i < j; i++) {
            if (country.toLowerCase() === countryCodes[i].name.toLowerCase()) {
                code = countryCodes[i].code;
                break;
            }
        }
        console.log(code);
        return code;
    }

    function isCity (location) {

        // console.log('isCity()');

        // console.log(location);

        article.inaccuracy += config.analyser.imprecision.city;

        return (cities.indexOf(location) != -1);
    }

    if (!article.isConflict) {

        article.isConflict = isConflict(article.analysis.classifications);
    }

    processLocations();

    return q();

};

Article.prototype.analyse = analyse;

module.exports = Article;

<|endoftext|>


<commit_before>'use strict';

var YAML = require('yamljs');
var evaluate = require('static-eval');
var parse = require('esprima').parse;

module.exports = function (sequelize, DataTypes) {
    var Projects = sequelize.define('projects', {
        id: {type: DataTypes.INTEGER, primaryKey: true},
        name: DataTypes.STRING,
        description: DataTypes.TEXT,
        configuration: DataTypes.TEXT,
        ready: DataTypes.BOOLEAN,
        status: DataTypes.BOOLEAN,
        user_owner_id: DataTypes.INTEGER,
        repo_name: DataTypes.STRING
    }, {
        scopes: {
            findProject: function (models, userId, nameSpace, nameProject) {
                return {
                    include: [
                        {
                            model: models.spaces,
                            where: {name: nameSpace}
                        }],
                    where: {name: nameProject, user_id: userId }
                }
            }
        },
        classMethods: {
            associate: function (models) {
                Projects.belongsTo(models.users);
                Projects.belongsTo(models.spaces)
            },
            findProject: function (models, userId, nameSpace, nameProject, callbackProject) {
                models.projects.scope({method: ['findProject', models, userId, nameSpace, nameProject]})
                    .findOne()
                    .then(callbackProject);
            }
        },
        instanceMethods: {
            parse: function () {
                return YAML.parse(this.configuration);
            },
            valideMetrics: function (metrics) {
                var config = this.parse();
                var configMetrics = config.metrics;

                var errors = {};
                for(var metric in metrics) {
                    if(configMetrics.hasOwnProperty(metric)) {
                        var metricType = configMetrics[metric];
                        var metricValue = metrics[metric];

                        if (typeof metricValue !== metricType) {
                            errors[metric] = "The value type of metric " + metric + " has to be " + metricType;
                        }
                    }
                    else {
                        errors[metric] = "The metric " + metric + " does not exist into the configuration yml project.";
                    }
                }

                return errors;
            },
            evaluateMetrics: function(metrics, callbackSuccess, callbackErrors) {
                var config = this.parse();
                for(var status in config) {
                    if(status !== "metrics" && status !== "default") {
                        try {
                            var src = config[status].when;
                            if(src) {
                                var ast = parse(src).body[0].expression;
                                if (evaluate(ast, metrics)) {
                                    return callbackSuccess(status);
                                }
                            }
                        } catch(err) {
                            callbackErrors(err);
                        }
                    }
                }

                callbackSuccess(config["default"]);
            },
            saveMetrics: function(status, metrics) {
                console.log(status);
                console.log(JSON.stringify(metrics));
            }
        }
    });
    return Projects;
};<commit_msg>Fix evaluate Metrics conditions.<commit_after>'use strict';

var YAML = require('yamljs');
var evaluate = require('static-eval');
var parse = require('esprima').parse;

module.exports = function (sequelize, DataTypes) {
    var Projects = sequelize.define('projects', {
        id: {type: DataTypes.INTEGER, primaryKey: true},
        name: DataTypes.STRING,
        description: DataTypes.TEXT,
        configuration: DataTypes.TEXT,
        ready: DataTypes.BOOLEAN,
        status: DataTypes.BOOLEAN,
        user_owner_id: DataTypes.INTEGER,
        repo_name: DataTypes.STRING
    }, {
        scopes: {
            findProject: function (models, userId, nameSpace, nameProject) {
                return {
                    include: [
                        {
                            model: models.spaces,
                            where: {name: nameSpace}
                        }],
                    where: {name: nameProject, user_id: userId }
                }
            }
        },
        classMethods: {
            associate: function (models) {
                Projects.belongsTo(models.users);
                Projects.belongsTo(models.spaces)
            },
            findProject: function (models, userId, nameSpace, nameProject, callbackProject) {
                models.projects.scope({method: ['findProject', models, userId, nameSpace, nameProject]})
                    .findOne()
                    .then(callbackProject);
            }
        },
        instanceMethods: {
            parse: function () {
                return YAML.parse(this.configuration);
            },
            valideMetrics: function (metrics) {
                var config = this.parse();
                var configMetrics = config.metrics;

                var errors = {};
                for(var metric in metrics) {
                    if(configMetrics.hasOwnProperty(metric)) {
                        var metricType = configMetrics[metric];
                        var metricValue = metrics[metric];

                        if (typeof metricValue !== metricType) {
                            errors[metric] = "The value type of metric " + metric + " has to be " + metricType;
                        }
                    }
                    else {
                        errors[metric] = "The metric " + metric + " does not exist into the configuration yml project.";
                    }
                }

                return errors;
            },
            evaluateMetrics: function(metrics, callbackSuccess, callbackErrors) {
                var config = this.parse();
                for(var status in config) {
                    if(status !== "metrics" && status !== "default") {
                        try {
                            var src = config[status].when;
                            if(src) {
                                var ast = parse(src).body[0].expression;
                                if (evaluate(ast, metrics)) {
                                    return callbackSuccess(status);
                                }
                            }
                        } catch(err) {
                            return callbackErrors(err);
                        }
                    }
                }

                callbackSuccess(config["default"]);
            },
            saveMetrics: function(status, metrics) {
                console.log(status);
                console.log(JSON.stringify(metrics));
            }
        }
    });
    return Projects;
};<|endoftext|>


<commit_before>module.exports = function(sequelize, DataTypes) {

    const Server = sequelize.define('server', {
        uuid: { type: DataTypes.STRING, unique: true, validate: { isUUID: 4 } },
        boot_order: {
            type: DataTypes.ENUM,
            values: [ 'disk / cdrom / disk', 'cdrom / cdrom', 'disk' ],
            defaultValue: 'disk' },
        core_number: { type: DataTypes.INTEGER },
        firewall: {
            type: DataTypes.ENUM,
            values: [ 'on', 'off' ],
            defaultValue: 'on'
        },
        host: { type: DataTypes.INTEGER },
        hostname: { type: DataTypes.STRING, validate: { isFQDN: true, len: [0,128] } },
        license: { type: DataTypes.INTEGER },
        memory_amount: { type: DataTypes.INTEGER },
        nic_model: {
            type: DataTypes.ENUM,
            values: [ 'e1000', 'virtio', 'rtl8139' ]
        },
        plan: { type: DataTypes.STRING },
        state: {
            type: DataTypes.ENUM,
            values: [ 'started', 'stopped', 'maintenance', 'error' ]
        },
        tags: { type: DataTypes.STRING },
        timezone: { type: DataTypes.STRING },
        title: { type: DataTypes.STRING, validate: { len: [0,64] } },
        video_model: {
            type: DataTypes.ENUM,
            values: [ 'cirrus', 'vga' ],
            defaultValue: 'vga'
        },
        vnc: {
            type: DataTypes.ENUM,
            values: [ 'on', 'off' ],
            defaultValue: 'off'
        },
        vnc_host: { type: DataTypes.STRING },
        vnc_password: { type: DataTypes.STRING },
        vnc_port: { type: DataTypes.INTEGER },
        zone: {
            type: DataTypes.ENUM,
            values: [ 'fi-hel1', 'uk-lon1', 'us-chi1', 'de-fra1', 'sg-sin1', 'ne-ams1' ]
        },
    });

    Server.associate = (models) => {
        Server.belongsToMany(models.storage_device, { as: 'storage_devices', through: 'ServerStorage' });
        Server.hasMany(models.ip_address, {as: 'ip_addresses'});
    };

    return Server;
}<commit_msg>Server model hostname validation fix<commit_after>module.exports = function(sequelize, DataTypes) {

    const Server = sequelize.define('server', {
        uuid: { type: DataTypes.STRING, unique: true, validate: { isUUID: 4 } },
        boot_order: {
            type: DataTypes.ENUM,
            values: [ 'disk / cdrom / disk', 'cdrom / cdrom', 'disk' ],
            defaultValue: 'disk' },
        core_number: { type: DataTypes.INTEGER },
        firewall: {
            type: DataTypes.ENUM,
            values: [ 'on', 'off' ],
            defaultValue: 'on'
        },
        host: { type: DataTypes.INTEGER },
        hostname: {
            type: DataTypes.STRING,
            validate: {
                isFQDN: {
                    require_tld: true,
                    allow_underscores: false,
                    allow_trailing_dot: false
                },
                len: [0,128]
            }
        },
        license: { type: DataTypes.INTEGER },
        memory_amount: { type: DataTypes.INTEGER },
        nic_model: {
            type: DataTypes.ENUM,
            values: [ 'e1000', 'virtio', 'rtl8139' ]
        },
        plan: { type: DataTypes.STRING },
        state: {
            type: DataTypes.ENUM,
            values: [ 'started', 'stopped', 'maintenance', 'error' ]
        },
        tags: { type: DataTypes.STRING },
        timezone: { type: DataTypes.STRING },
        title: { type: DataTypes.STRING, validate: { len: [0,64] } },
        video_model: {
            type: DataTypes.ENUM,
            values: [ 'cirrus', 'vga' ],
            defaultValue: 'vga'
        },
        vnc: {
            type: DataTypes.ENUM,
            values: [ 'on', 'off' ],
            defaultValue: 'off'
        },
        vnc_host: { type: DataTypes.STRING },
        vnc_password: { type: DataTypes.STRING },
        vnc_port: { type: DataTypes.INTEGER },
        zone: {
            type: DataTypes.ENUM,
            values: [ 'fi-hel1', 'uk-lon1', 'us-chi1', 'de-fra1', 'sg-sin1', 'ne-ams1' ]
        },
    });

    Server.associate = (models) => {
        Server.belongsToMany(models.storage_device, { as: 'storage_devices', through: 'ServerStorage' });
        Server.hasMany(models.ip_address, {as: 'ip_addresses'});
    };

    return Server;
}<|endoftext|>


<commit_before>const { Command } = require('discord.js-commando');
const Redis = require('../../redis/Redis');

const redis = new Redis();

module.exports = class MoneyCheckCommand extends Command {
	constructor(client) {
		super(client, {
			name: 'money',
			group: 'info',
			memberName: 'money',
			description: 'Displays the money you have earned.',
			details: 'Display the amount of money you have earned.',

			args: [
				{
					key: 'member',
					prompt: 'What user\'s earning do you want to view?',
					type: 'member',
					default: ''
				}
			]
		});
	}

	async run(msg, args) {
		let user = args.member || msg.author;

		redis.db.getAsync(user.id).then(balance => {
			if (args.member) {
				if (!balance) return msg.reply(`${args.member.displayName} hasn't earned any money yet :(`);
				return msg.reply(`${args.member.displayName} has earned ${balance}Đ so far. Good on them!`);
			} else {
				if (!balance) return msg.reply('you haven\'t earned any money yet, sorry :(');
				return msg.reply(`You have earned ${balance}Đ so far. Good on you!`);
			}
		});
	}
};
<commit_msg>Fix money check command<commit_after>const { Command } = require('discord.js-commando');
const Redis = require('../../redis/Redis');

const redis = new Redis();

module.exports = class MoneyCheckCommand extends Command {
	constructor(client) {
		super(client, {
			name: 'money',
			group: 'info',
			memberName: 'money',
			description: 'Displays the money you have earned.',
			details: 'Display the amount of money you have earned.',

			args: [
				{
					key: 'member',
					prompt: 'What user\'s earning do you want to view?',
					type: 'member',
					default: ''
				}
			]
		});
	}

	async run(msg, args) {
		let user = args.member || msg.author;

		redis.db.getAsync(`money${user.id}`).then(balance => {
			if (args.member) {
				if (!balance) return msg.reply(`${args.member.displayName} hasn't earned any money yet :(`);
				return msg.reply(`${args.member.displayName} has earned ${balance}Đ so far. Good on them!`);
			} else {
				if (!balance) return msg.reply('you haven\'t earned any money yet, sorry :(');
				return msg.reply(`You have earned ${balance}Đ so far. Good on you!`);
			}
		});
	}
};
<|endoftext|>


<commit_before>const { Command } = require('discord.js-commando')
const { stripIndents } = require('common-tags')
const { escapeMarkdown } = require('discord.js')

module.exports = class InfoCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'info',
      memberName: 'info',
      group: 'information',
      description: 'Displays information about the bot.',
      aliases: [
        'about'
      ],
      clientPermissions: [
        'EMBED_LINKS'
      ],
      throttling: {
        usages: 2,
        duration: 10
      },
      guarded: true
    })
  }

  async run (message) {
    var dev
    try { dev = this.client.users.find('id', '196443959558406144').tag } catch (e) { dev = 'Aceheliflyer#0950' }

    var contributorsList = ''
    this.client.config.contributors.forEach(contributor => {
      try {
        let contribTemp = this.client.users.find('id', contributor.id).tag
        if (contributor.github) {
          contributorsList = `${contributorsList}\n**[${escapeMarkdown(contribTemp)}](http://github.com/${contributor.github}) -** ${contributor.info}`
        } else {
          contributorsList = `${contributorsList}\n**${escapeMarkdown(contribTemp)}** - ${contributor.info}`
        }
      } catch (e) {
        if (contributor.github) {
          contributorsList = `${contributorsList}\n**[${escapeMarkdown(contributor.name)}](http://github.com/${contributor.github}) -** ${contributor.info}`
        } else {
          contributorsList = `${contributorsList}\n**${escapeMarkdown(contributor.name)}** - ${contributor.info}`
        }
      }
    })

    var totalGuilds; var totalChannels; var totalUsers
    if (!this.client.shard) {
      totalGuilds = await this.client.guilds.size
      totalChannels = await this.client.channels.size
      totalUsers = await this.client.users.size
    } else {
      var totalGuildsData = await this.client.shard.fetchClientValues('guilds.size')
      totalGuilds = await totalGuildsData.reduce((prev, val) => prev + val, 0)
      var totalChannelsData = await this.client.shard.fetchClientValues('channels.size')
      totalChannels = await totalChannelsData.reduce((prev, val) => prev + val, 0)
      var totalUsersData = await this.client.shard.fetchClientValues('users.size')
      totalUsers = await totalUsersData.reduce((prev, val) => prev + val, 0)
    }

    message.embed({
      author: {
        name: await this.client.fetchApplication().then(app => { return `${app.owner.tag} | ${this.client.user.tag}` }),
        icon_url: this.client.user.displayAvatarURL(),
        url: require('../../package.json').homepageGithub
      },
      footer: {
        text: message.author.tag,
        icon_url: message.author.displayAvatarURL()
      },
      timestamp: new Date(),
      fields: [
        /* eslint-disable object-property-newline */
        {
          'name': 'Developer',
          'value': stripIndents`
            Discord: **${escapeMarkdown(dev)}**
            GitHub: [@Aceheliflyer](http://github.com/Aceheliflyer)
          `,
          'inline': false
        },
        {
          'name': 'Developed In',
          'value': stripIndents`
            Language: **JavaScript** (NodeJS)
            Library: **discord.js** (v${require('discord.js/package.json').version})
            Framework: **discord.js-commando** (v${require('discord.js-commando/package.json').version})
            Bot Version: **${require('../../package.json').version}**
          `,
          'inline': false
        },
        {
          'name': 'Links', 'value': stripIndents`
          Bot Invite: [Click Here!](${await this.client.generateInvite()})
          Server Invite: [Click Here!](${this.client.config.client.invite})
          Homepage: [Click Here!](${require('../../package.json').homepage})
          Repository: [Click Here!](${require('../../package.json').homepageGithub})
          Trello: [Click Here!](${require('../../package.json').homepageTrello})
        `, 'inline': false
        },
        {
          'name': 'Discord Stats', 'value': stripIndents`
          ${this.client.shard ? `Shards: **${this.client.shard.count}**\n` : ''}Guilds: **${totalGuilds}**
          Channels: **${totalChannels}**
          Users: **${totalUsers}**
        `, 'inline': false
        },
        {
          'name': 'Special Thanks to the Following:',
          'value': contributorsList,
          'inline': false
        }
        /* eslint-enable object-property-newline */
      ],
      color: 0x7289DA
    })
  }
}
<commit_msg>Fix: Fix bold text in info command.<commit_after>const { Command } = require('discord.js-commando')
const { stripIndents } = require('common-tags')
const { escapeMarkdown } = require('discord.js')

module.exports = class InfoCommand extends Command {
  constructor (client) {
    super(client, {
      name: 'info',
      memberName: 'info',
      group: 'information',
      description: 'Displays information about the bot.',
      aliases: [
        'about'
      ],
      clientPermissions: [
        'EMBED_LINKS'
      ],
      throttling: {
        usages: 2,
        duration: 10
      },
      guarded: true
    })
  }

  async run (message) {
    var dev
    try { dev = this.client.users.find('id', '196443959558406144').tag } catch (e) { dev = 'Aceheliflyer#0950' }

    var contributorsList = ''
    this.client.config.contributors.forEach(contributor => {
      try {
        let contribTemp = this.client.users.find('id', contributor.id).tag
        if (contributor.github) {
          contributorsList = `${contributorsList}\n**[${escapeMarkdown(contribTemp)}](http://github.com/${contributor.github})** - ${contributor.info}`
        } else {
          contributorsList = `${contributorsList}\n**${escapeMarkdown(contribTemp)}** - ${contributor.info}`
        }
      } catch (e) {
        if (contributor.github) {
          contributorsList = `${contributorsList}\n**[${escapeMarkdown(contributor.name)}](http://github.com/${contributor.github})** - ${contributor.info}`
        } else {
          contributorsList = `${contributorsList}\n**${escapeMarkdown(contributor.name)}** - ${contributor.info}`
        }
      }
    })

    var totalGuilds; var totalChannels; var totalUsers
    if (!this.client.shard) {
      totalGuilds = await this.client.guilds.size
      totalChannels = await this.client.channels.size
      totalUsers = await this.client.users.size
    } else {
      var totalGuildsData = await this.client.shard.fetchClientValues('guilds.size')
      totalGuilds = await totalGuildsData.reduce((prev, val) => prev + val, 0)
      var totalChannelsData = await this.client.shard.fetchClientValues('channels.size')
      totalChannels = await totalChannelsData.reduce((prev, val) => prev + val, 0)
      var totalUsersData = await this.client.shard.fetchClientValues('users.size')
      totalUsers = await totalUsersData.reduce((prev, val) => prev + val, 0)
    }

    message.embed({
      author: {
        name: await this.client.fetchApplication().then(app => { return `${app.owner.tag} | ${this.client.user.tag}` }),
        icon_url: this.client.user.displayAvatarURL(),
        url: require('../../package.json').homepageGithub
      },
      footer: {
        text: message.author.tag,
        icon_url: message.author.displayAvatarURL()
      },
      timestamp: new Date(),
      fields: [
        /* eslint-disable object-property-newline */
        {
          'name': 'Developer',
          'value': stripIndents`
            Discord: **${escapeMarkdown(dev)}**
            GitHub: [@Aceheliflyer](http://github.com/Aceheliflyer)
          `,
          'inline': false
        },
        {
          'name': 'Developed In',
          'value': stripIndents`
            Language: **JavaScript** (NodeJS)
            Library: **discord.js** (v${require('discord.js/package.json').version})
            Framework: **discord.js-commando** (v${require('discord.js-commando/package.json').version})
            Bot Version: **${require('../../package.json').version}**
          `,
          'inline': false
        },
        {
          'name': 'Links', 'value': stripIndents`
          Bot Invite: [Click Here!](${await this.client.generateInvite()})
          Server Invite: [Click Here!](${this.client.config.client.invite})
          Homepage: [Click Here!](${require('../../package.json').homepage})
          Repository: [Click Here!](${require('../../package.json').homepageGithub})
          Trello: [Click Here!](${require('../../package.json').homepageTrello})
        `, 'inline': false
        },
        {
          'name': 'Discord Stats', 'value': stripIndents`
          ${this.client.shard ? `Shards: **${this.client.shard.count}**\n` : ''}Guilds: **${totalGuilds}**
          Channels: **${totalChannels}**
          Users: **${totalUsers}**
        `, 'inline': false
        },
        {
          'name': 'Special Thanks to the Following:',
          'value': contributorsList,
          'inline': false
        }
        /* eslint-enable object-property-newline */
      ],
      color: 0x7289DA
    })
  }
}
<|endoftext|>


<commit_before>/**
@module ember
@submodule ember-runtime
*/

var get = Ember.get, set = Ember.set;

/**
`Ember.TargetActionSupport` is a mixin that can be included in a class
to add a `triggerAction` method with semantics similar to the Handlebars
`{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
usually the best choice. This mixin is most often useful when you are
doing more complex event handling in View objects.

See also `Ember.ViewTargetActionSupport`, which has
view-aware defaults for target and actionContext.

@class TargetActionSupport
@namespace Ember
@extends Ember.Mixin
*/
Ember.TargetActionSupport = Ember.Mixin.create({
  target: null,
  action: null,
  actionContext: null,

  targetObject: Ember.computed(function() {
    var target = get(this, 'target');

    if (Ember.typeOf(target) === "string") {
      var value = get(this, target);
      if (value === undefined) { value = get(Ember.lookup, target); }
      return value;
    } else {
      return target;
    }
  }).property('target'),

  actionContextObject: Ember.computed(function() {
    var actionContext = get(this, 'actionContext');

    if (Ember.typeOf(actionContext) === "string") {
      var value = get(this, actionContext);
      if (value === undefined) { value = get(Ember.lookup, actionContext); }
      return value;
    } else {
      return actionContext;
    }
  }).property('actionContext'),

  /**
  Send an "action" with an "actionContext" to a "target". The action, actionContext
  and target will be retrieved from properties of the object. For example:

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    target: Ember.computed.alias('controller'),
    action: 'save',
    actionContext: Ember.computed.alias('context'),
    click: function() {
      this.triggerAction(); // Sends the `save` action, along with the current context
                            // to the current controller
    }
  });
  ```

  The `target`, `action`, and `actionContext` can be provided as properties of
  an optional object argument to `triggerAction` as well.

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    click: function() {
      this.triggerAction({
        action: 'save',
        target: this.get('controller'),
        actionContext: this.get('context'),
      }); // Sends the `save` action, along with the current context
          // to the current controller
    }
  });
  ```

  The `actionContext` defaults to the object you mixing `TargetActionSupport` into.
  But `target` and `action` must be specified either as properties or with the argument
  to `triggerAction`, or a combination:

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    target: Ember.computed.alias('controller'),
    click: function() {
      this.triggerAction({
        action: 'save'
      }); // Sends the `save` action, along with a reference to `this`,
          // to the current controller
    }
  });
  ```

  @method triggerAction
  @param opts {Hash} (optional, with the optional keys action, target and/or actionContext)
  @return {Boolean} true if the action was sent successfully and did not return false
  */
  triggerAction: function(opts) {
    opts = opts || {};
    var action = opts.action || get(this, 'action'),
        target = opts.target || get(this, 'targetObject'),
        actionContext = opts.actionContext;

    function args(options, actionName) {
      var ret = [];
      if (actionName) { ret.push(actionName); }

      return ret.concat(options);
    }

    if (typeof actionContext === 'undefined') {
      actionContext = get(this, 'actionContextObject') || this;
    }

    if (target && action) {
      var ret;

      if (target.send) {
        ret = target.send.apply(target, args(actionContext, action));
      } else {
        Ember.assert("The action '" + action + "' did not exist on " + target, typeof target[action] === 'function');
        ret = target[action].apply(target, args(actionContext));
      }

      if (ret !== false) ret = true;

      return ret;
    } else {
      return false;
    }
  }
});
<commit_msg>[DOC] Minor doc fix<commit_after>/**
@module ember
@submodule ember-runtime
*/

var get = Ember.get, set = Ember.set;

/**
`Ember.TargetActionSupport` is a mixin that can be included in a class
to add a `triggerAction` method with semantics similar to the Handlebars
`{{action}}` helper. In normal Ember usage, the `{{action}}` helper is
usually the best choice. This mixin is most often useful when you are
doing more complex event handling in View objects.

See also `Ember.ViewTargetActionSupport`, which has
view-aware defaults for target and actionContext.

@class TargetActionSupport
@namespace Ember
@extends Ember.Mixin
*/
Ember.TargetActionSupport = Ember.Mixin.create({
  target: null,
  action: null,
  actionContext: null,

  targetObject: Ember.computed(function() {
    var target = get(this, 'target');

    if (Ember.typeOf(target) === "string") {
      var value = get(this, target);
      if (value === undefined) { value = get(Ember.lookup, target); }
      return value;
    } else {
      return target;
    }
  }).property('target'),

  actionContextObject: Ember.computed(function() {
    var actionContext = get(this, 'actionContext');

    if (Ember.typeOf(actionContext) === "string") {
      var value = get(this, actionContext);
      if (value === undefined) { value = get(Ember.lookup, actionContext); }
      return value;
    } else {
      return actionContext;
    }
  }).property('actionContext'),

  /**
  Send an `action` with an `actionContext` to a `target`. The action, actionContext
  and target will be retrieved from properties of the object. For example:

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    target: Ember.computed.alias('controller'),
    action: 'save',
    actionContext: Ember.computed.alias('context'),
    click: function() {
      this.triggerAction(); // Sends the `save` action, along with the current context
                            // to the current controller
    }
  });
  ```

  The `target`, `action`, and `actionContext` can be provided as properties of
  an optional object argument to `triggerAction` as well.

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    click: function() {
      this.triggerAction({
        action: 'save',
        target: this.get('controller'),
        actionContext: this.get('context'),
      }); // Sends the `save` action, along with the current context
          // to the current controller
    }
  });
  ```

  The `actionContext` defaults to the object you mixing `TargetActionSupport` into.
  But `target` and `action` must be specified either as properties or with the argument
  to `triggerAction`, or a combination:

  ```javascript
  App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, {
    target: Ember.computed.alias('controller'),
    click: function() {
      this.triggerAction({
        action: 'save'
      }); // Sends the `save` action, along with a reference to `this`,
          // to the current controller
    }
  });
  ```

  @method triggerAction
  @param opts {Hash} (optional, with the optional keys action, target and/or actionContext)
  @return {Boolean} true if the action was sent successfully and did not return false
  */
  triggerAction: function(opts) {
    opts = opts || {};
    var action = opts.action || get(this, 'action'),
        target = opts.target || get(this, 'targetObject'),
        actionContext = opts.actionContext;

    function args(options, actionName) {
      var ret = [];
      if (actionName) { ret.push(actionName); }

      return ret.concat(options);
    }

    if (typeof actionContext === 'undefined') {
      actionContext = get(this, 'actionContextObject') || this;
    }

    if (target && action) {
      var ret;

      if (target.send) {
        ret = target.send.apply(target, args(actionContext, action));
      } else {
        Ember.assert("The action '" + action + "' did not exist on " + target, typeof target[action] === 'function');
        ret = target[action].apply(target, args(actionContext));
      }

      if (ret !== false) ret = true;

      return ret;
    } else {
      return false;
    }
  }
});
<|endoftext|>


<commit_before>import React from 'react';
import {
  arrayOf,
  shape,
  string,
  number,
  bool,
  func,
  objectOf,
  any,
  object
} from 'prop-types';
import { noop } from 'lodash';
import { connect } from 'react-redux';
import { Player, ControlBar, BigPlayButton } from 'video-react';

import { Overlay, OverlayPositioningProvider } from 'veritone-react-common';
import VideoSource from './VideoSource';
import { getPolysForTime } from './helpers';

import styles from './styles.scss';

@connect(state => ({
  videoHeight: state.player.videoHeight,
  videoWidth: state.player.videoWidth,
  hasStarted: state.player.hasStarted,
  isActive: state.player.isActive,
  currentTime: state.player.currentTime,
  paused: state.player.paused
}))
class MediaPlayerComponent extends React.Component {
  static propTypes = {
    src: string,
    streams: arrayOf(
      shape({
        protocol: string,
        uri: string
      })
    ),
    boundingPolySeries: arrayOf(
      shape({
        startTimeMs: number.isRequired,
        stopTimeMs: number.isRequired,
        object: shape({
          boundingPoly: arrayOf(
            shape({ x: number.isRequired, y: number.isRequired })
          ).isRequired
        })
      })
    ),
    onBoundingBoxChange: func,
    overlayBorderStyle: string,
    readOnly: bool,
    width: number,
    height: number,
    // fluid = 100% width by default, see video-react docs
    fluid: bool,
    videoHeight: number,
    videoWidth: number,
    hasStarted: bool,
    isActive: bool,
    paused: bool,
    currentTime: number,
    forwardedRef: objectOf(any)
  };

  static contextTypes = {
    store: object
  };

  static defaultProps = {
    onBoundingBoxChange: noop,
    fluid: true
  };

  handleBoundingBoxChange = (allPolys, newPoly) => {
    this.props.onBoundingBoxChange(allPolys, newPoly, {
      currentTime: this.props.currentTime
    });
  };

  render() {
    const { src, streams, ...props } = this.props;

    return (
      <OverlayPositioningProvider
        contentHeight={this.props.videoHeight}
        contentWidth={this.props.videoWidth}
        fixedWidth={!props.fluid}
      >
        {this.props.hasStarted && (
          <Overlay
            wrapperStyles={{ zIndex: 100 }}
            onBoundingBoxChange={this.handleBoundingBoxChange}
            overlayBackgroundColor="rgba(238, 110, 105, 0.5)"
            overlayBorderStyle={this.props.overlayBorderStyle}
            initialBoundingBoxPolys={
              this.props.boundingPolySeries
                ? getPolysForTime(
                    this.props.boundingPolySeries,
                    this.props.currentTime * 1000
                  )
                : undefined
            }
            readOnly={this.props.readOnly || !this.props.paused}
            key={this.props.currentTime}
          />
        )}
        <Player
          className={styles.mediaPlayer}
          ref={this.props.forwardedRef}
          store={this.context.store}
          {...props}
        >
          {/* prevent video-react from adding its own control bar */}
          <ControlBar autoHide className={styles.hiddenDummyControls} />

          <VideoSource isVideoChild src={src} streams={streams} />
          <BigPlayButton position="center" className={styles.mediaPlayButton} />
        </Player>
      </OverlayPositioningProvider>
    );
  }
}

const MediaPlayer = React.forwardRef((props, ref) => {
  return <MediaPlayerComponent {...props} forwardedRef={ref} />;
});

export { MediaPlayer };
<commit_msg>+comment<commit_after>import React from 'react';
import {
  arrayOf,
  shape,
  string,
  number,
  bool,
  func,
  objectOf,
  any,
  object
} from 'prop-types';
import { noop } from 'lodash';
import { connect } from 'react-redux';
import { Player, ControlBar, BigPlayButton } from 'video-react';

import { Overlay, OverlayPositioningProvider } from 'veritone-react-common';
import VideoSource from './VideoSource';
import { getPolysForTime } from './helpers';

import styles from './styles.scss';

@connect(state => ({
  videoHeight: state.player.videoHeight,
  videoWidth: state.player.videoWidth,
  hasStarted: state.player.hasStarted,
  isActive: state.player.isActive,
  currentTime: state.player.currentTime,
  paused: state.player.paused
}))
class MediaPlayerComponent extends React.Component {
  static propTypes = {
    src: string,
    streams: arrayOf(
      shape({
        protocol: string,
        uri: string
      })
    ),
    boundingPolySeries: arrayOf(
      shape({
        startTimeMs: number.isRequired,
        stopTimeMs: number.isRequired,
        object: shape({
          boundingPoly: arrayOf(
            shape({ x: number.isRequired, y: number.isRequired })
          ).isRequired
        })
      })
    ),
    onBoundingBoxChange: func,
    overlayBorderStyle: string,
    readOnly: bool,
    width: number,
    height: number,
    // fluid = 100% width by default, see video-react docs
    fluid: bool,
    videoHeight: number,
    videoWidth: number,
    hasStarted: bool,
    isActive: bool,
    paused: bool,
    currentTime: number,
    forwardedRef: objectOf(any)
  };

  static contextTypes = {
    // need to pass our app's redux store to the Player, or else it will create
    // its own internal store that we can't integrate with
    store: object
  };

  static defaultProps = {
    onBoundingBoxChange: noop,
    fluid: true
  };

  handleBoundingBoxChange = (allPolys, newPoly) => {
    this.props.onBoundingBoxChange(allPolys, newPoly, {
      currentTime: this.props.currentTime
    });
  };

  render() {
    const { src, streams, ...props } = this.props;

    return (
      <OverlayPositioningProvider
        contentHeight={this.props.videoHeight}
        contentWidth={this.props.videoWidth}
        fixedWidth={!props.fluid}
      >
        {this.props.hasStarted && (
          <Overlay
            wrapperStyles={{ zIndex: 100 }}
            onBoundingBoxChange={this.handleBoundingBoxChange}
            overlayBackgroundColor="rgba(238, 110, 105, 0.5)"
            overlayBorderStyle={this.props.overlayBorderStyle}
            initialBoundingBoxPolys={
              this.props.boundingPolySeries
                ? getPolysForTime(
                    this.props.boundingPolySeries,
                    this.props.currentTime * 1000
                  )
                : undefined
            }
            readOnly={this.props.readOnly || !this.props.paused}
            key={this.props.currentTime}
          />
        )}
        <Player
          className={styles.mediaPlayer}
          ref={this.props.forwardedRef}
          store={this.context.store}
          {...props}
        >
          {/* prevent video-react from adding its own control bar */}
          <ControlBar autoHide className={styles.hiddenDummyControls} />

          <VideoSource isVideoChild src={src} streams={streams} />
          <BigPlayButton position="center" className={styles.mediaPlayButton} />
        </Player>
      </OverlayPositioningProvider>
    );
  }
}

const MediaPlayer = React.forwardRef((props, ref) => {
  return <MediaPlayerComponent {...props} forwardedRef={ref} />;
});

export { MediaPlayer };
<|endoftext|>